<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Guo Le&#39;s Blog</title>
  <icon>https://www.gravatar.com/avatar/2f1eaea04ec39048522d17f213862066</icon>
  
  <link href="https://blog.guole.fun/atom.xml" rel="self"/>
  
  <link href="https://blog.guole.fun/"/>
  <updated>2025-11-01T19:36:14.000Z</updated>
  <id>https://blog.guole.fun/</id>
  
  <author>
    <name>八章</name>
    <email>guole.fun@qq.com</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>使用 Vercel 部署 Umami 统计，获取访客操作系统、国家/地区、浏览器等数据</title>
    <link href="https://blog.guole.fun/posts/32784/"/>
    <id>https://blog.guole.fun/posts/32784/</id>
    <published>2024-12-24T20:31:11.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近本站升级到了<code>Umami</code>统计，在<a href="/about/#statistic">关于我</a>页面，也添加了简单的网站统计数据概览效果。  </p><p><img src="/img/posts/32784-2.jpg" alt="本站效果预览">  </p><p>洪哥提供了<a href="https://blog.zhheo.com/p/ce30.html">使用Docker搭建Umami统计</a>方法，林木木提供了<a href="https://immmmm.com/hi-umami-api/">前端调用 Umami API 数据</a>，我这个是基于<a href="https://vercel.com/">Vercel</a>自部署的功能实现。  </p><p>个人认为我自己这套方案的主要优点如下：  </p><div class="note success no-icon flat"><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>基于<code>Vercel</code>部署，免费</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>Json 输出，便于使用</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>新增接口方式，尽量不改动<code>Umami</code>官方代码，后续升级容易</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>一次调用即可获得：概览数据、访客浏览器数据、访客操作系统数据、访客来源国家&#x2F;地区数据（其他<code>Umami</code>统计数据也可返回，个人认为这些足够了就没折腾了）</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>访客浏览器数据：返回了浏览器 icon、格式化后的名称</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>访客操作系统数据：返回了操作系统 icon、格式化后的名称</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>访客来源国家&#x2F;地区数据：返回了国家&#x2F;地区旗帜、中文的名称，前端拿到手即用</p>            </div>  </div><p>感兴趣吗？开干！  </p><h2 id="Vercel-部署-Umami"><a href="#Vercel-部署-Umami" class="headerlink" title="Vercel 部署 Umami"></a>Vercel 部署 Umami</h2><p>首先<code>Fork</code>官方仓库<a href="https://github.com/umami-software/umami">Umami</a>，名称随便。顺手也点个小星星吧，支持下开源项目。  </p><p>接着在 Vercel 中，创建一个新项目，选择刚刚<code>Fork</code>的这个仓库，点击<code>Import</code>部署该项目。  </p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">创建 Serverless Postgres</button><button type="button" class="tab">设置环境变量</button></div><div class="tab-contents"><div class="tab-item-content active"><p>在自己 Vercel 首页，点击“Storage” —&gt; “Create Database” —&gt; “Serverless Postgres”。   </p><p><img src="/img/posts/32784-3.png" alt="Storage">  </p><p>接着地区建议选择新加坡 “Singapore - sin1”，其他默认，创建完成。  </p><p><img src="/img/posts/32784-4.png" alt="创建 Serverless Postgres">  </p><p>访问刚创建的这个服务，点击“Show secret”查看<code>DATABASE_URL</code>的值，并保存好稍后使用。  </p><div class="note info flat"><p><strong>小贴士：</strong><br>通过此处的信息，后期还可以在桌面端如<code>DBeaver</code>软件中，直连数据库，访问<code>Umami</code>数据表,用<code>SQL</code>取数自己分析等等。  </p><p>以<code>DBeaver</code>为例，在<code>DBeaver</code>中创建一个链接，选择<code>PostgreSQL</code>后，简要配置如下：</p><ul><li>主机：即该页面的<code>PGHOST</code>  </li><li>端口：默认<code>5432</code>就行  </li><li>认证：选择<code>Database Native</code>  </li><li>用户名：即该页面的<code>PGUSER</code>  </li><li>密码：即该页面的<code>PGPASSWORD</code></li></ul><p>随后点击左下角“测试链接”，如果正常的话，勾选<code>Save password locally</code>保存密码到本地，然后确定即可。  </p></div></div><div class="tab-item-content"><p>回到 Vercel 中刚才创建的<code>Umami</code>项目，点击该项目，在 “Settings” —&gt; “Environment Variables” 下，创建以下环境变量：  </p><table><thead><tr><th>变量名</th><th>取值</th><th>说明</th></tr></thead><tbody><tr><td>CORS_ALLOWED_ORIGINS</td><td>配置你自己网站域名，解决跨域问题，如<code>https://blog.guole.fun</code></td><td>解决<code>Umami</code>跨域问题，同时一定程度保障网站数据安全性</td></tr><tr><td>CORS_ALLOWED_HOST</td><td>配置你自己的主域名，如<code>guole.fun</code></td><td>解决<code>Umami</code>跨域问题</td></tr><tr><td>DATABASE_URL</td><td>刚才记录的<code>DATABASE_URL</code>值</td><td>官方配置项，数据库链接</td></tr><tr><td>TRACKER_SCRIPT_NAME</td><td>script.js</td><td>脚本名称，就是给<code>Umami</code>前端嵌入的跟踪器脚本一个新的名称，随便自定义</td></tr></tbody></table><p>先不要急着去重新部署，因为我们还要调整代码。  </p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="在-Umami-中新增接口"><a href="#在-Umami-中新增接口" class="headerlink" title="在 Umami 中新增接口"></a>在 Umami 中新增接口</h2><p>在本地创建一个文件夹比如<code>umami</code>，然后执行以下命令关联和拉取远程仓库：  </p><figure class="highlight bash"><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 init  </span><br><span class="line">git remote add origin <span class="variable">$&#123;刚才 Fork 的 Umami 官方仓库 ssh 地址&#125;</span>  </span><br><span class="line">git pull origin main</span><br></pre></td></tr></table></figure><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">第一步：修改 package.json</button><button type="button" class="tab">第二步：修改 .env</button><button type="button" class="tab">第三步：修改 tsconfig.json</button><button type="button" class="tab">第四步：修改 middleware.ts</button><button type="button" class="tab">第五步：修改 [shareId].ts</button><button type="button" class="tab">第六步：新建 getWebsiteMetrics.ts</button><button type="button" class="tab">第七步：大功告成，推送到 Github</button></div><div class="tab-contents"><div class="tab-item-content active"><p>在本地编辑器中打开<code>umami/package.json</code>，在<code>scripts</code>的<code>build</code>下面插入一行：  </p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;build-dev&quot;</span><span class="punctuation">:</span> <span class="string">&quot;npm-run-all check-env build-db check-db build-tracker build-app&quot;</span><span class="punctuation">,</span></span><br></pre></td></tr></table></figure><p>这是为了解决本地调试时，除了第一次，后面无需执行<code>build-geo</code>步骤（安装完依赖，首次执行 <code>npm run build</code>，后续使用 <code>npm run build-dev</code>），避免国内网络情况每次构建都要等很久很久……  </p></div><div class="tab-item-content"><p>记得上面配置的环境变量<code>DATABASE_URL</code>和<code>CORS_ALLOWED_ORIGINS</code>吗？在<code>umami/.env</code>中新增：  </p><figure class="highlight plaintext"><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">DATABASE_URL=postgres://neondb******ire  # 刚才记录的值</span><br><span class="line">CORS_ALLOWED_ORIGINS=https://blog.guole.fun,http://127.0.0.1:4000,http://127.0.0.1:8000,https://hoppscotch.io # 换成你自己的</span><br><span class="line">CORS_ALLOWED_HOST=guole.fun # 换成你自己的主域名</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>在本地编辑器中打开<code>umami/tsconfig.json</code>，在原文<code>&quot;styles/*&quot;: [&quot;./styles/*&quot;],</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></pre></td><td class="code"><pre><span class="line">- <span class="attr">&quot;styles/*&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;./styles/*&quot;</span><span class="punctuation">]</span></span><br><span class="line">+ <span class="attr">&quot;styles/*&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;./styles/*&quot;</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">+ <span class="attr">&quot;public/*&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="string">&quot;../public/*&quot;</span><span class="punctuation">]</span></span><br></pre></td></tr></table></figure><details blue><summary> 修改后完整 tsconfig.json </summary>              <div class='content'>              <figure class="highlight ts"><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></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;compilerOptions&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;target&quot;</span>: <span class="string">&quot;es2021&quot;</span>,</span><br><span class="line">    <span class="string">&quot;outDir&quot;</span>: <span class="string">&quot;./build&quot;</span>,</span><br><span class="line">    <span class="string">&quot;module&quot;</span>: <span class="string">&quot;esnext&quot;</span>,</span><br><span class="line">    <span class="string">&quot;moduleResolution&quot;</span>: <span class="string">&quot;node&quot;</span>,</span><br><span class="line">    <span class="string">&quot;resolveJsonModule&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;isolatedModules&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;lib&quot;</span>: [<span class="string">&quot;dom&quot;</span>, <span class="string">&quot;dom.iterable&quot;</span>, <span class="string">&quot;esnext&quot;</span>],</span><br><span class="line">    <span class="string">&quot;skipLibCheck&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;esModuleInterop&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;noImplicitAny&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="string">&quot;preserveConstEnums&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;removeComments&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;sourceMap&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;allowSyntheticDefaultImports&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;forceConsistentCasingInFileNames&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;allowJs&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;strict&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;strictNullChecks&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="string">&quot;noEmit&quot;</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">&quot;jsx&quot;</span>: <span class="string">&quot;preserve&quot;</span>,</span><br><span class="line">    <span class="string">&quot;incremental&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="string">&quot;baseUrl&quot;</span>: <span class="string">&quot;./src&quot;</span>,</span><br><span class="line">    <span class="string">&quot;types&quot;</span>: [<span class="string">&quot;jest&quot;</span>],</span><br><span class="line">    <span class="string">&quot;typeRoots&quot;</span>: [<span class="string">&quot;node_modules/@types&quot;</span>],</span><br><span class="line">    <span class="string">&quot;paths&quot;</span>: &#123;</span><br><span class="line">      <span class="string">&quot;react&quot;</span>: [<span class="string">&quot;./node_modules/@types/react&quot;</span>],</span><br><span class="line">      <span class="string">&quot;assets/*&quot;</span>: [<span class="string">&quot;./assets/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;components/*&quot;</span>: [<span class="string">&quot;./components/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;lib/*&quot;</span>: [<span class="string">&quot;./lib/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;pages/*&quot;</span>: [<span class="string">&quot;./pages/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;queries/*&quot;</span>: [<span class="string">&quot;./queries/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;store/*&quot;</span>: [<span class="string">&quot;./store/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;styles/*&quot;</span>: [<span class="string">&quot;./styles/*&quot;</span>],</span><br><span class="line">      <span class="string">&quot;public/*&quot;</span>: [<span class="string">&quot;../public/*&quot;</span>]</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;plugins&quot;</span>: [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="string">&quot;name&quot;</span>: <span class="string">&quot;next&quot;</span></span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">&quot;include&quot;</span>: [<span class="string">&quot;**/*.ts&quot;</span>, <span class="string">&quot;**/*.tsx&quot;</span>, <span class="string">&quot;**/*.js&quot;</span>, <span class="string">&quot;**/*.jsx&quot;</span>, <span class="string">&quot;next-env.d.ts&quot;</span>, <span class="string">&quot;.next/types/**/*.ts&quot;</span>],</span><br><span class="line">  <span class="string">&quot;exclude&quot;</span>: [<span class="string">&quot;node_modules&quot;</span>, <span class="string">&quot;./cypress.config.ts&quot;</span>, <span class="string">&quot;cypress&quot;</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>              </div>            </details></div><div class="tab-item-content"><p>在本地编辑器中打开<code>umami/src/lib/middleware.ts</code>，修改<code>createMiddleware</code>内容如下：  </p><figure class="highlight ts"><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">export</span> <span class="keyword">const</span> useCors = <span class="title function_">createMiddleware</span>(<span class="function">(<span class="params"><span class="attr">req</span>: <span class="title class_">NextApiRequestWithPath</span>, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="title function_">cors</span>(&#123;</span><br><span class="line">    <span class="attr">origin</span>: <span class="function">(<span class="params"><span class="attr">origin</span>: <span class="built_in">string</span> | <span class="literal">undefined</span>, callback</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">const</span> allowedOrigins = (process.<span class="property">env</span>.<span class="property">CORS_ALLOWED_ORIGINS</span> || <span class="string">&#x27;&#x27;</span>).<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>);</span><br><span class="line">      <span class="comment">// 如果没有提供 origin，允许请求</span></span><br><span class="line">      <span class="keyword">if</span> (</span><br><span class="line">        !origin ||</span><br><span class="line">        allowedOrigins.<span class="title function_">includes</span>(origin) ||</span><br><span class="line">        (process.<span class="property">env</span>.<span class="property">CORS_ALLOWED_HOST</span> &amp;&amp; origin?.<span class="title function_">endsWith</span>(process.<span class="property">env</span>.<span class="property">CORS_ALLOWED_HOST</span>)) ||</span><br><span class="line">        (req.<span class="property">path</span> &amp;&amp; req.<span class="property">path</span> === <span class="string">&#x27;/api/send&#x27;</span>)</span><br><span class="line">      ) &#123;</span><br><span class="line">        res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Access-Control-Allow-Origin&#x27;</span>, origin || <span class="string">&#x27;&#x27;</span>);</span><br><span class="line">        <span class="title function_">callback</span>(<span class="literal">null</span>, <span class="literal">true</span>);</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="title function_">callback</span>(<span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;Not allowed by CORS&#x27;</span>));</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// Cache CORS preflight request 24 hours by default</span></span><br><span class="line">    <span class="attr">maxAge</span>: <span class="title class_">Number</span>(process.<span class="property">env</span>.<span class="property">CORS_MAX_AGE</span>) || <span class="number">86400</span>,</span><br><span class="line">  &#125;)(req, res, next);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>在本地编辑器中打开<code>umami/src/pages/api/share/[shareId].ts</code>，修改原文：</p><figure class="highlight ts"><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 class="keyword">import</span> &#123; useValidate &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/middleware&#x27;</span>;</span><br><span class="line">+ <span class="keyword">import</span> &#123; useCors, useValidate &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/middleware&#x27;</span>;</span><br></pre></td></tr></table></figure><p>另外，该文件中新增对<code>useCors</code>的调用：  </p><figure class="highlight ts"><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 class="keyword">await</span> <span class="title function_">useCors</span>(req, res);</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">useValidate</span>(schema, req, res);</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>接着在本地编辑器中打开<code>umami/src/pages/api/websites/[websiteId]/</code>目录，新建一个文件<code>getWebsiteMetrics.ts</code>，内容如下：</p><figure class="highlight ts"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> yup <span class="keyword">from</span> <span class="string">&#x27;yup&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">NextApiResponse</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;next&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; methodNotAllowed, ok, unauthorized &#125; <span class="keyword">from</span> <span class="string">&#x27;next-basics&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; canViewWebsite &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/auth&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; useAuth, useCors, useValidate &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/middleware&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">NextApiRequestQueryBody</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/types&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; getRequestFilters, getRequestDateRange &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/request&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; getPageviewMetrics, getSessionMetrics, getWebsiteStats &#125; <span class="keyword">from</span> <span class="string">&#x27;queries&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123;</span><br><span class="line">  <span class="variable constant_">SESSION_COLUMNS</span>,</span><br><span class="line">  <span class="variable constant_">EVENT_COLUMNS</span>,</span><br><span class="line">  <span class="variable constant_">FILTER_COLUMNS</span>,</span><br><span class="line">  <span class="variable constant_">OPERATORS</span>,</span><br><span class="line">  <span class="variable constant_">OS_NAMES</span>,</span><br><span class="line">  <span class="variable constant_">BROWSERS</span>,</span><br><span class="line">&#125; <span class="keyword">from</span> <span class="string">&#x27;lib/constants&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; getCompareDate &#125; <span class="keyword">from</span> <span class="string">&#x27;lib/date&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> countryNames <span class="keyword">from</span> <span class="string">&#x27;public/intl/country/zh-CN.json&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> <span class="title class_">CombinedMetricsRequestQuery</span> &#123;</span><br><span class="line">  <span class="attr">websiteId</span>: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">startAt</span>: <span class="built_in">number</span>;</span><br><span class="line">  <span class="attr">endAt</span>: <span class="built_in">number</span>;</span><br><span class="line">  limit?: <span class="built_in">number</span>;</span><br><span class="line">  offset?: <span class="built_in">number</span>;</span><br><span class="line">  search?: <span class="built_in">string</span>;</span><br><span class="line">  url?: <span class="built_in">string</span>;</span><br><span class="line">  referrer?: <span class="built_in">string</span>;</span><br><span class="line">  title?: <span class="built_in">string</span>;</span><br><span class="line">  query?: <span class="built_in">string</span>;</span><br><span class="line">  event?: <span class="built_in">string</span>;</span><br><span class="line">  host?: <span class="built_in">string</span>;</span><br><span class="line">  os?: <span class="built_in">string</span>;</span><br><span class="line">  browser?: <span class="built_in">string</span>;</span><br><span class="line">  device?: <span class="built_in">string</span>;</span><br><span class="line">  country?: <span class="built_in">string</span>;</span><br><span class="line">  region?: <span class="built_in">string</span>;</span><br><span class="line">  city?: <span class="built_in">string</span>;</span><br><span class="line">  tag?: <span class="built_in">string</span>;</span><br><span class="line">  compare?: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">type</span>: <span class="built_in">string</span>;</span><br><span class="line">  language?: <span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> schema = &#123;</span><br><span class="line">  <span class="attr">GET</span>: yup.<span class="title function_">object</span>().<span class="title function_">shape</span>(&#123;</span><br><span class="line">    <span class="attr">websiteId</span>: yup.<span class="title function_">string</span>().<span class="title function_">uuid</span>().<span class="title function_">required</span>(),</span><br><span class="line">    <span class="attr">startAt</span>: yup.<span class="title function_">number</span>().<span class="title function_">required</span>(),</span><br><span class="line">    <span class="attr">endAt</span>: yup.<span class="title function_">number</span>().<span class="title function_">required</span>(),</span><br><span class="line">    <span class="attr">limit</span>: yup.<span class="title function_">number</span>(),</span><br><span class="line">    <span class="attr">offset</span>: yup.<span class="title function_">number</span>(),</span><br><span class="line">    <span class="attr">search</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">type</span>: yup.<span class="title function_">string</span>().<span class="title function_">required</span>(),</span><br><span class="line">    <span class="attr">url</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">referrer</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">title</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">query</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">host</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">os</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">browser</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">device</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">country</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">region</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">city</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">language</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">event</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">tag</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">    <span class="attr">compare</span>: yup.<span class="title function_">string</span>(),</span><br><span class="line">  &#125;),</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> dataType = <span class="title class_">ItemType</span>[];</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> <span class="title class_">SourceType</span> = &#123;</span><br><span class="line">  [<span class="attr">key</span>: <span class="built_in">string</span>]: <span class="built_in">string</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">ItemType</span> &#123;</span><br><span class="line">  <span class="attr">x</span>: <span class="built_in">string</span>;</span><br><span class="line">  <span class="attr">y</span>: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">async</span> (</span><br><span class="line">  <span class="attr">req</span>: <span class="title class_">NextApiRequestQueryBody</span>&lt;<span class="title class_">CombinedMetricsRequestQuery</span>&gt;,</span><br><span class="line">  <span class="attr">res</span>: <span class="title class_">NextApiResponse</span>,</span><br><span class="line">) =&gt; &#123;</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">useCors</span>(req, res);</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">useAuth</span>(req, res);</span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">useValidate</span>(schema, req, res);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> &#123; websiteId, <span class="keyword">type</span>, limit, offset, search, compare &#125; = req.<span class="property">query</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;GET&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!(<span class="keyword">await</span> <span class="title function_">canViewWebsite</span>(req.<span class="property">auth</span>, websiteId))) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">unauthorized</span>(res);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> &#123; startDate, endDate &#125; = <span class="keyword">await</span> <span class="title function_">getRequestDateRange</span>(req);</span><br><span class="line">    <span class="keyword">const</span> &#123; <span class="attr">startDate</span>: compareStartDate, <span class="attr">endDate</span>: compareEndDate &#125; = <span class="title function_">getCompareDate</span>(</span><br><span class="line">      compare,</span><br><span class="line">      startDate,</span><br><span class="line">      endDate,</span><br><span class="line">    );</span><br><span class="line">    <span class="keyword">const</span> column = <span class="variable constant_">FILTER_COLUMNS</span>[<span class="keyword">type</span>] || <span class="keyword">type</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> filters = <span class="title function_">getRequestFilters</span>(req);</span><br><span class="line">    <span class="keyword">const</span> filters_search = &#123;</span><br><span class="line">      ...<span class="title function_">getRequestFilters</span>(req),</span><br><span class="line">      startDate,</span><br><span class="line">      endDate,</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (search) &#123;</span><br><span class="line">      filters_search[<span class="keyword">type</span>] = &#123;</span><br><span class="line">        <span class="attr">name</span>: <span class="keyword">type</span>,</span><br><span class="line">        column,</span><br><span class="line">        <span class="attr">operator</span>: <span class="variable constant_">OPERATORS</span>.<span class="property">contains</span>,</span><br><span class="line">        <span class="attr">value</span>: search,</span><br><span class="line">      &#125;;</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">const</span> metrics = <span class="keyword">await</span> <span class="title function_">getWebsiteStats</span>(websiteId, &#123;</span><br><span class="line">      ...filters,</span><br><span class="line">      startDate,</span><br><span class="line">      endDate,</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> prevPeriod = <span class="keyword">await</span> <span class="title function_">getWebsiteStats</span>(websiteId, &#123;</span><br><span class="line">      ...filters,</span><br><span class="line">      <span class="attr">startDate</span>: compareStartDate,</span><br><span class="line">      <span class="attr">endDate</span>: compareEndDate,</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> stats = <span class="title class_">Object</span>.<span class="title function_">keys</span>(metrics[<span class="number">0</span>]).<span class="title function_">reduce</span>(<span class="function">(<span class="params">obj, key</span>) =&gt;</span> &#123;</span><br><span class="line">      obj[key] = &#123;</span><br><span class="line">        <span class="attr">value</span>: <span class="title class_">Number</span>(metrics[<span class="number">0</span>][key]) || <span class="number">0</span>,</span><br><span class="line">        <span class="attr">prev</span>: <span class="title class_">Number</span>(prevPeriod[<span class="number">0</span>][key]) || <span class="number">0</span>,</span><br><span class="line">      &#125;;</span><br><span class="line">      <span class="keyword">return</span> obj;</span><br><span class="line">    &#125;, &#123;&#125;);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 获取操作系统/浏览器/国家地区的统计数据</span></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">getMetricsData</span> = <span class="keyword">async</span> (<span class="params">websiteId, filters_search, limit, offset, types</span>) =&gt; &#123;</span><br><span class="line">      <span class="keyword">if</span> (<span class="variable constant_">SESSION_COLUMNS</span>.<span class="title function_">includes</span>(types)) &#123;</span><br><span class="line">        <span class="keyword">const</span> data = <span class="keyword">await</span> <span class="title function_">getSessionMetrics</span>(websiteId, types, filters_search, limit, offset);</span><br><span class="line">        <span class="comment">// console.log(&quot;data：&quot;, data);</span></span><br><span class="line">        <span class="keyword">if</span> (types === <span class="string">&#x27;language&#x27;</span>) &#123;</span><br><span class="line">          <span class="keyword">const</span> combined = &#123;&#125;;</span><br><span class="line">          <span class="keyword">for</span> (<span class="keyword">const</span> &#123; x, y &#125; <span class="keyword">of</span> data) &#123;</span><br><span class="line">            <span class="keyword">const</span> key = <span class="title class_">String</span>(x).<span class="title function_">toLowerCase</span>().<span class="title function_">split</span>(<span class="string">&#x27;-&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">            <span class="keyword">if</span> (combined[key] === <span class="literal">undefined</span>) &#123;</span><br><span class="line">              combined[key] = &#123; <span class="attr">x</span>: key, y &#125;;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">              combined[key].<span class="property">y</span> += y;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="keyword">return</span> <span class="title class_">Object</span>.<span class="title function_">values</span>(combined);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> data;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> (<span class="variable constant_">EVENT_COLUMNS</span>.<span class="title function_">includes</span>(types)) &#123;</span><br><span class="line">        <span class="keyword">const</span> data = <span class="keyword">await</span> <span class="title function_">getPageviewMetrics</span>(websiteId, types, filters_search, limit, offset);</span><br><span class="line">        <span class="keyword">return</span> data;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">return</span> [];</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> osData = <span class="keyword">await</span> <span class="title function_">getMetricsData</span>(websiteId, filters_search, limit, offset, <span class="string">&#x27;os&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> browserData = <span class="keyword">await</span> <span class="title function_">getMetricsData</span>(websiteId, filters_search, limit, offset, <span class="string">&#x27;browser&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> countryData = <span class="keyword">await</span> <span class="title function_">getMetricsData</span>(websiteId, filters_search, limit, offset, <span class="string">&#x27;country&#x27;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">formattedData</span> = <span class="keyword">async</span> (<span class="params"><span class="attr">data</span>: dataType, <span class="attr">type</span>: <span class="built_in">string</span></span>) =&gt; &#123;</span><br><span class="line">      <span class="keyword">let</span> <span class="attr">source</span>: <span class="title class_">SourceType</span>;</span><br><span class="line">      <span class="keyword">let</span> <span class="attr">icon</span>: <span class="built_in">string</span>;</span><br><span class="line">      <span class="keyword">switch</span> (<span class="keyword">type</span>) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;os&#x27;</span>:</span><br><span class="line">          source = <span class="variable constant_">OS_NAMES</span>;</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;browser&#x27;</span>:</span><br><span class="line">          source = <span class="variable constant_">BROWSERS</span>;</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;country&#x27;</span>:</span><br><span class="line">          source = countryNames;</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (source) &#123;</span><br><span class="line">        <span class="keyword">return</span> data.<span class="title function_">map</span>(<span class="function">(<span class="params"><span class="attr">item</span>: <span class="title class_">ItemType</span></span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="keyword">const</span> <span class="attr">itemName</span>: <span class="built_in">string</span> = item.<span class="property">x</span>.<span class="title function_">toLowerCase</span>().<span class="title function_">replace</span>(<span class="regexp">/ /g</span>, <span class="string">&#x27;-&#x27;</span>);</span><br><span class="line">          <span class="keyword">switch</span> (<span class="keyword">type</span>) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;os&#x27;</span>:</span><br><span class="line">              icon = <span class="string">`//umami.guole.fun/images/os/<span class="subst">$&#123;itemName&#125;</span>.png`</span>;</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;browser&#x27;</span>:</span><br><span class="line">              icon = <span class="string">`//umami.guole.fun/images/browser/<span class="subst">$&#123;itemName&#125;</span>.png`</span>;</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;country&#x27;</span>:</span><br><span class="line">              icon = <span class="string">`//umami.guole.fun/images/country/<span class="subst">$&#123;itemName&#125;</span>.png`</span>;</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> <span class="string">&#x27;device&#x27;</span>:</span><br><span class="line">              icon = <span class="string">`//umami.guole.fun/images/device/<span class="subst">$&#123;itemName&#125;</span>.png`</span>;</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            <span class="attr">default</span>:</span><br><span class="line">              icon = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="attr">name</span>: source[item.<span class="property">x</span>] || item.<span class="property">x</span>,</span><br><span class="line">            <span class="attr">icon</span>: icon,</span><br><span class="line">            <span class="attr">x</span>: item.<span class="property">x</span>,</span><br><span class="line">            <span class="attr">y</span>: item.<span class="property">y</span>,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">false</span>;</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> <span class="title function_">ok</span>(res, &#123;</span><br><span class="line">      <span class="attr">os</span>: (<span class="keyword">await</span> <span class="title function_">formattedData</span>(osData, <span class="string">&#x27;os&#x27;</span>)) || [],</span><br><span class="line">      <span class="attr">browser</span>: (<span class="keyword">await</span> <span class="title function_">formattedData</span>(browserData, <span class="string">&#x27;browser&#x27;</span>)) || [],</span><br><span class="line">      <span class="attr">country</span>: (<span class="keyword">await</span> <span class="title function_">formattedData</span>(countryData, <span class="string">&#x27;country&#x27;</span>)) || [],</span><br><span class="line">      <span class="attr">stats</span>: stats || [],</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">methodNotAllowed</span>(res);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>记得把代码中<code>umami.guole.fun</code>，换成你部署<code>Umami</code>后的自定义域名（在 Vercel 中设置）。  </p></div><div class="tab-item-content"><p>至此已完成修改，提交推送到远程仓库，Vercel 就会自动部署，并应用刚才设置的环境变量。  </p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="测试接口"><a href="#测试接口" class="headerlink" title="测试接口"></a>测试接口</h2><p>确保你的网站已完成<code>Umami</code>接入（官方文档很详细，就不赘述了）。  </p><p>在<code>Umami</code>前端界面中，访问 “设置” —&gt; “网站” —&gt; 选择你的网站 —&gt; “共享链接”，创建一个共享链接（也可以用<a href="https://umami.is/docs/api/authentication">官方指导</a>里的方法，创建一个 API 秘钥，然后去调用……），这个共享链接只需其中的标识<code>share/</code>与<code>/$&#123;你的域名&#125;</code>中间这部分字符串。  </p><p>获取 token 地址：<code>https://你的 umami 域名/api/share/</code> + <code>上文这个字符串</code>  </p><p>打开<a href="https://hoppscotch.io/">hoppscotch.io</a>，创建一个获取 <code>token</code> 的 <code>get</code> 请求，地址就是上面这个，发送看看。应该可以拿到结果。  </p><p>如果<code>hoppscotch</code>无法发送请求，去安装下这个<a href="https://chromewebstore.google.com/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld">浏览器插件</a>。  </p><p>再创建一个 <code>get</code> 请求，地址是：<code>https://你的 umami 域名/api/websites/在umami设置中，你的网站ID/getWebsiteMetrics</code>  </p><p>添加一些请求参数：  </p><figure class="highlight plaintext"><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">startAt: 1731859200000</span><br><span class="line">endAt: 1734451199999</span><br><span class="line">unit: hour</span><br><span class="line">timezone: Asia%2FShanghai</span><br><span class="line">compare: false</span><br><span class="line">limit: 10</span><br><span class="line">type: os //这里随意 os / browser / country 都行</span><br></pre></td></tr></table></figure><p>添加请求头：  </p><figure class="highlight plaintext"><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">X-Umami-Share-Token: //刚才调用获得的 token</span><br><span class="line">Content-Type: application/json</span><br></pre></td></tr></table></figure><p>发送请求试试看吧！应该可以获得下面这样的输出结果：  </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><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</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;os&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Windows 10/11&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/os/windows-10.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Windows 10&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">44</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Android&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/os/android-os.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Android OS&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">9</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;macOS&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/os/mac-os.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Mac OS&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">4</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;iOS&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/os/ios.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;iOS&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">4</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Linux&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/os/linux.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Linux&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Windows 7&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/os/windows-7.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Windows 7&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;browser&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Chrome&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/browser/chrome.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;chrome&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">35</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Edge (Chromium)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/browser/edge-chromium.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;edge-chromium&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">18</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;iOS&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/browser/ios.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;ios&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">4</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Chrome (webview)&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/browser/chromium-webview.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;chromium-webview&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">3</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Firefox&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/browser/firefox.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;firefox&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">2</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Safari&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/browser/safari.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;safari&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;country&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;中国&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/cn.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;CN&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">39</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;中国香港特别行政区&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/hk.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;HK&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">10</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;新加坡&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/sg.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;SG&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">5</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;日本&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/jp.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;JP&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">3</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;美国&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/us.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;US&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">2</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;墨西哥&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/mx.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;MX&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;加拿大&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/ca.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;CA&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;台湾&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/tw.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;TW&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;澳大利亚&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;//umami.guole.fun/images/country/au.png&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;x&quot;</span><span class="punctuation">:</span> <span class="string">&quot;AU&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;y&quot;</span><span class="punctuation">:</span> <span class="number">1</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;stats&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;pageviews&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="number">194</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;prev&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;visitors&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="number">63</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;prev&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;visits&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="number">80</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;prev&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;bounces&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="number">51</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;prev&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;totaltime&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="number">9259</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;prev&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>至此，接口完成。拿到数据随便怎么玩吧。其中<code>name</code>就是格式化后的名称，<code>icon</code>是图标，<code>y</code>就是对应数据值。  </p><h2 id="使用接口"><a href="#使用接口" class="headerlink" title="使用接口"></a>使用接口</h2><p>直接把我自己的实现放出来吧。  </p><p>之前参考洪哥页面，搞了个<code>about</code>页面，在其中插入这样的代码：  </p><figure class="highlight plaintext"><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">.author-content</span><br><span class="line">  .about-statistic.author-content-item</span><br><span class="line">    .card-content</span><br><span class="line">      .author-content-item-tips 网站数据</span><br><span class="line">      span.author-content-item-title 访问统计</span><br><span class="line">      #statistic</span><br><span class="line">        #stats</span><br><span class="line">        #metrics</span><br><span class="line">      .post-tips(style=&quot;opacity: 0.6;&quot;) * 数据来自：</span><br><span class="line">        a(href=&#x27;https://umami.guole.fun/&#x27; target=&quot;_blank&quot;) Umami</span><br></pre></td></tr></table></figure><p>在该文件末尾，插入一段脚本：  </p><figure class="highlight plaintext"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br></pre></td><td class="code"><pre><span class="line">script.</span><br><span class="line">  //- 访问统计 umami</span><br><span class="line">  //- 这个 cachedData 方法，可以放到其他自定义脚本里，其他地方也可以用……为了演示方便，我写到这里了</span><br><span class="line">  function cachedData: (customCacheName) =&gt; &#123;</span><br><span class="line">      const cacheName = customCacheName || &#x27;default-cache&#x27;; // 提供默认缓存名称</span><br><span class="line"></span><br><span class="line">      return &#123;</span><br><span class="line">        // 缓存数据</span><br><span class="line">        cache: function (key, value) &#123;</span><br><span class="line">          if (!cacheName) &#123;</span><br><span class="line">            throw new Error(&#x27;Cache name is required&#x27;); // 抛出错误</span><br><span class="line">          &#125; else &#123;</span><br><span class="line">            localStorage.setItem(`$&#123;cacheName&#125;-$&#123;key&#125;`, JSON.stringify(value)); // 使用 localStorage 缓存数据</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        // 获取缓存数据</span><br><span class="line">        get: function (key) &#123;</span><br><span class="line">          const value = localStorage.getItem(`$&#123;cacheName&#125;-$&#123;key&#125;`);</span><br><span class="line">          return value ? JSON.parse(value) : null; // 如果没有找到数据，返回 null</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        // 清除缓存数据</span><br><span class="line">        clear: function (key) &#123;</span><br><span class="line">          localStorage.removeItem(`$&#123;cacheName&#125;-$&#123;key&#125;`);</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br><span class="line">        // 检查缓存</span><br><span class="line">        has: function (key) &#123;</span><br><span class="line">          return localStorage.getItem(`$&#123;cacheName&#125;-$&#123;key&#125;`) !== null; // 如果存在，返回 true</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">  async function getToken() &#123;</span><br><span class="line">    const url = &#x27;换成你获取 token 的地址&#x27;; // 似乎这玩意儿不会过期，反正我目前是假设它 4h 过期，然后去更新  </span><br><span class="line">    try &#123;</span><br><span class="line">        const res = await fetch(url);</span><br><span class="line">        if (!res.ok) &#123;</span><br><span class="line">            throw new Error(&#x27;Network response was not ok&#x27;);</span><br><span class="line">        &#125;</span><br><span class="line">        const data = await res.json();</span><br><span class="line">        return data.token;</span><br><span class="line">    &#125; catch (error) &#123;</span><br><span class="line">        console.error(&#x27;Error fetching token:&#x27;, error);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  async function getData(token) &#123;</span><br><span class="line">      const currentDate = new Date();</span><br><span class="line">      const endAt = new Date(currentDate);</span><br><span class="line">      endAt.setHours(23, 59, 59, 999);</span><br><span class="line">      const startAt = new Date(currentDate);</span><br><span class="line">      startAt.setDate(currentDate.getDate() - 30); //这里表示查询最近 30 天数据，可自行修改</span><br><span class="line">      startAt.setHours(0, 0, 0, 0);</span><br><span class="line"></span><br><span class="line">      const startAtTimestamp = startAt.getTime();</span><br><span class="line">      const endAtTimestamp = endAt.getTime();</span><br><span class="line"></span><br><span class="line">      // 如果没有有效缓存，进行网络请求</span><br><span class="line">      const url = `https://你的umami域名/api/websites/你的网站ID/getWebsiteMetrics?startAt=$&#123;startAtTimestamp&#125;&amp;endAt=$&#123;endAtTimestamp&#125;&amp;unit=hour&amp;timezone=Asia%2FShanghai&amp;compare=false&amp;limit=5&amp;type=os`;</span><br><span class="line">      </span><br><span class="line">      try &#123;</span><br><span class="line">          const res = await fetch(url, &#123;</span><br><span class="line">              method: &#x27;GET&#x27;,</span><br><span class="line">              headers: &#123;</span><br><span class="line">                  &#x27;Content-Type&#x27;: &#x27;application/json&#x27;,</span><br><span class="line">                  &#x27;X-Umami-Share-Token&#x27;: token</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;);</span><br><span class="line"></span><br><span class="line">          if (!res.ok) &#123;</span><br><span class="line">              throw new Error(&#x27;Network response was not ok&#x27;);</span><br><span class="line">          &#125;</span><br><span class="line"></span><br><span class="line">          const data = await res.json();</span><br><span class="line">          return data;</span><br><span class="line">      &#125; catch (error) &#123;</span><br><span class="line">          console.error(&#x27;Error fetching data:&#x27;, error);</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  (async () =&gt; &#123;</span><br><span class="line">      let token, data;</span><br><span class="line">      const umamiCache = cachedData(&#x27;umami&#x27;);</span><br><span class="line">      const currentTime = Date.now();</span><br><span class="line">      const cacheDuration = 4 * 60 * 60 * 1000; // 缓存 4h</span><br><span class="line"></span><br><span class="line">      // 尝试获取已缓存数据</span><br><span class="line">      const cachedToken = await umamiCache.get(&#x27;token&#x27;);</span><br><span class="line">      const cachedData = await umamiCache.get(&#x27;data&#x27;);</span><br><span class="line"></span><br><span class="line">      if (!cachedToken || currentTime &gt; parseInt(cachedToken.cacheTime, 10) + cacheDuration ) &#123;</span><br><span class="line">        token = await getToken();</span><br><span class="line">        await umamiCache.cache(&#x27;token&#x27;, &#123;</span><br><span class="line">          cacheTime: currentTime,</span><br><span class="line">          token: token</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">        token = cachedToken.token; </span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      if (!cachedData || currentTime &gt; parseInt(cachedData.cacheTime, 10) + cacheDuration ) &#123;</span><br><span class="line">        data = await getData(token); </span><br><span class="line">        await umamiCache.cache(&#x27;data&#x27;, &#123;</span><br><span class="line">          cacheTime: currentTime,</span><br><span class="line">          data: data</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125; else &#123;</span><br><span class="line">        data = cachedData.data;</span><br><span class="line">      &#125;</span><br><span class="line">      </span><br><span class="line">      const stats = document.getElementById(&quot;stats&quot;);</span><br><span class="line">      const metrics = document.getElementById(&quot;metrics&quot;);</span><br><span class="line"></span><br><span class="line">      const pageviews = data.stats.pageviews.value;</span><br><span class="line">      const visitors = data.stats.visitors.value;</span><br><span class="line">      const visits = data.stats.visits.value;</span><br><span class="line"></span><br><span class="line">      const countryHTML = data.country.map((item) =&gt; &#123;</span><br><span class="line">        return `</span><br><span class="line">        &lt;div class=&quot;list&quot;&gt;</span><br><span class="line">          &lt;div class=&quot;item&quot;&gt;</span><br><span class="line">            &lt;img class=&quot;loading nolazyload&quot; alt=&quot;$&#123;item.x&#125;&quot; width=&quot;16&quot; height=&quot;16&quot; src=&quot;$&#123;item.icon&#125;&quot;&gt;&lt;/img&gt;</span><br><span class="line">            &lt;span class=&quot;name&quot;&gt;$&#123;item.name&#125;&lt;/span&gt;</span><br><span class="line">          &lt;/div&gt;</span><br><span class="line">          &lt;div class=&quot;value&quot;&gt;$&#123;item.y&#125;&lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;`</span><br><span class="line">      &#125;).join(&#x27;&#x27;);</span><br><span class="line">      const browserHTML = data.browser.map((item) =&gt; &#123;</span><br><span class="line">        return `</span><br><span class="line">        &lt;div class=&quot;list&quot;&gt;</span><br><span class="line">          &lt;div class=&quot;item&quot;&gt;</span><br><span class="line">            &lt;img class=&quot;loading nolazyload&quot; alt=&quot;$&#123;item.x&#125;&quot; width=&quot;16&quot; height=&quot;16&quot; src=&quot;$&#123;item.icon&#125;&quot;&gt;&lt;/img&gt;</span><br><span class="line">            &lt;span class=&quot;name&quot;&gt;$&#123;item.name&#125;&lt;/span&gt;</span><br><span class="line">          &lt;/div&gt;</span><br><span class="line">          &lt;div class=&quot;value&quot;&gt;$&#123;item.y&#125;&lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;`</span><br><span class="line">      &#125;).join(&#x27;&#x27;);</span><br><span class="line">      const osHTML = data.os.map((item) =&gt; &#123;</span><br><span class="line">        return `</span><br><span class="line">        &lt;div class=&quot;list&quot;&gt;</span><br><span class="line">          &lt;div class=&quot;item&quot;&gt;</span><br><span class="line">            &lt;img class=&quot;loading nolazyload&quot; alt=&quot;$&#123;item.x&#125;&quot; width=&quot;16&quot; height=&quot;16&quot; src=&quot;$&#123;item.icon&#125;&quot;&gt;&lt;/img&gt;</span><br><span class="line">            &lt;span class=&quot;name&quot;&gt;$&#123;item.name&#125;&lt;/span&gt;</span><br><span class="line">          &lt;/div&gt;</span><br><span class="line">          &lt;div class=&quot;value&quot;&gt;$&#123;item.y&#125;&lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;`</span><br><span class="line">      &#125;).join(&#x27;&#x27;);</span><br><span class="line"></span><br><span class="line">      if (stats &amp;&amp; metrics) &#123;</span><br><span class="line">          stats.innerHTML += `&lt;div&gt;&lt;span&gt;浏览量&lt;/span&gt;&lt;span&gt;$&#123;pageviews&#125;&lt;/span&gt;&lt;/div&gt;`;</span><br><span class="line">          stats.innerHTML += `&lt;div&gt;&lt;span&gt;访问次数&lt;/span&gt;&lt;span&gt;$&#123;visitors&#125;&lt;/span&gt;&lt;/div&gt;`;</span><br><span class="line">          stats.innerHTML += `&lt;div&gt;&lt;span&gt;访客&lt;/span&gt;&lt;span&gt;$&#123;visits&#125;&lt;/span&gt;&lt;/div&gt;`;</span><br><span class="line">          metrics.innerHTML += `</span><br><span class="line">          &lt;div class=&quot;country&quot;&gt;&lt;span&gt;访客国家/地区 (TOP5)&lt;/span&gt;$&#123;countryHTML&#125;&lt;/div&gt;</span><br><span class="line">          &lt;div class=&quot;os&quot;&gt;&lt;span&gt;访客操作系统 (TOP5)&lt;/span&gt;$&#123;osHTML&#125;&lt;/div&gt;</span><br><span class="line">          &lt;div class=&quot;browser&quot;&gt;&lt;span&gt;访客浏览器 (TOP5)&lt;/span&gt;$&#123;browserHTML&#125;&lt;/div&gt;`;</span><br><span class="line">          if (window.lazyLoadInstance) window.lazyLoadInstance.update();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)();</span><br></pre></td></tr></table></figure><p>收工~~ </p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;最近本站升级到了&lt;code&gt;Umami&lt;/code&gt;统计，在&lt;a href=&quot;/about/#statistic&quot;&gt;关于我&lt;/a&gt;页面，也添加了简单的网站统计数据概览效果。  &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/img/posts/32784-2.jpg&quot; alt=&quot;本站</summary>
      
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Butterfly美化" scheme="https://blog.guole.fun/tags/Butterfly%E7%BE%8E%E5%8C%96/"/>
    
    <category term="Umami" scheme="https://blog.guole.fun/tags/Umami/"/>
    
  </entry>
  
  <entry>
    <title>解决腾讯云 COSCMD 安装报错：无法导入 SafeConfigParser 问题</title>
    <link href="https://blog.guole.fun/posts/12743/"/>
    <id>https://blog.guole.fun/posts/12743/</id>
    <published>2024-12-20T14:41:50.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近本站的部署脚本执行报错：  </p><figure class="highlight yml"><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="attr">Traceback (most recent call last):</span></span><br><span class="line">  <span class="string">File</span> <span class="string">&quot;/usr/local/bin/coscmd&quot;</span><span class="string">,</span> <span class="string">line</span> <span class="number">5</span><span class="string">,</span> <span class="string">in</span> <span class="string">&lt;module&gt;</span></span><br><span class="line">    <span class="string">from</span> <span class="string">coscmd.cos_cmd</span> <span class="string">import</span> <span class="string">_main</span></span><br><span class="line">  <span class="string">File</span> <span class="string">&quot;/usr/local/lib/python3.12/dist-packages/coscmd/cos_cmd.py&quot;</span><span class="string">,</span> <span class="string">line</span> <span class="number">2</span><span class="string">,</span> <span class="string">in</span> <span class="string">&lt;module&gt;</span></span><br><span class="line">    <span class="string">from</span> <span class="string">six.moves.configparser</span> <span class="string">import</span> <span class="string">SafeConfigParser</span></span><br><span class="line"><span class="attr">ImportError:</span> <span class="string">cannot</span> <span class="string">import</span> <span class="string">name</span> <span class="string">&#x27;SafeConfigParser&#x27;</span> <span class="string">from</span> <span class="string">&#x27;configparser&#x27;</span> <span class="string">(/usr/lib/python3.12/configparser.py).</span> <span class="attr">Did you mean:</span> <span class="string">&#x27;RawConfigParser&#x27;</span><span class="string">?</span></span><br></pre></td></tr></table></figure><p>核心问题在于尝试从<code>configparser</code>模块导入<code>SafeConfigParser</code>时失败了。  </p><p>原因是使用的腾讯云<code>coscmd</code>命令行工具，因为要兼容<code>Python 2.x</code>版本，在<code>pip</code>上最新版本停更于<code>1.8.6.34</code>。Python 3.12 之后，<code>SafeConfigParser</code>已经被移除，应该使用<code>ConfigParser</code>。  </p><div class="tag link"><a class="link-card" title="官方答复 - Github Issues" href="https://github.com/tencentyun/coscmd/issues/311#issuecomment-2119592061"><div class="left"><img class="no-lightbox" src="/img/icon/github.png"/></div><div class="right"><p class="text">官方答复 - Github Issues</p><p class="url">https://github.com/tencentyun/coscmd/issues/311#issuecomment-2119592061</p></div></a></div><p>搞清楚原因就好解决了，直接在 Github Action 脚本中，限制为<code>Python 3.11</code>版本即可。  </p><figure class="highlight yml"><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></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">Python</span> <span class="number">3.11</span></span><br><span class="line">  <span class="attr">uses:</span> <span class="string">actions/setup-python@v4</span></span><br><span class="line">  <span class="attr">with:</span></span><br><span class="line">    <span class="attr">python-version:</span> <span class="string">&#x27;3.11&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Install</span> <span class="string">tencent</span> <span class="string">cloud</span> <span class="string">coscmd</span></span><br><span class="line">  <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    python -m pip install --upgrade pip</span></span><br><span class="line"><span class="string">    pip install coscmd</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Configuration</span> <span class="string">tencent</span> <span class="string">cloud</span> <span class="string">coscmd</span></span><br><span class="line">  <span class="attr">env:</span></span><br><span class="line">    <span class="attr">SECRET_ID:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.TENCENT_CLOUD_SECRET_ID</span> <span class="string">&#125;&#125;</span></span><br><span class="line">    <span class="attr">SECRET_KEY:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.TENCENT_CLOUD_SECRET_KEY</span> <span class="string">&#125;&#125;</span></span><br><span class="line">    <span class="attr">BUCKET:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.COS_BUCKET</span> <span class="string">&#125;&#125;</span></span><br><span class="line">    <span class="attr">REGION:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.COS_REGION</span> <span class="string">&#125;&#125;</span></span><br><span class="line">  <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">upload</span> <span class="string">tencent</span> <span class="string">cloud</span> <span class="string">COS</span></span><br><span class="line">  <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line">    <span class="string">coscmd</span> <span class="string">upload</span> <span class="string">-rfs</span> <span class="string">--delete</span> <span class="string">./public/</span> <span class="string">/</span></span><br></pre></td></tr></table></figure><p>收工~  </p>]]></content>
    
    
    <summary type="html">解决腾讯云 COSCMD 报错：cannot import name &#39;SafeConfigParser&#39; from &#39;configparser&#39; 问题</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
    <category term="踩坑笔记" scheme="https://blog.guole.fun/tags/%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>腾讯云函数实现 ACME 协议下自动申请配置 SSL 证书</title>
    <link href="https://blog.guole.fun/posts/23745/"/>
    <id>https://blog.guole.fun/posts/23745/</id>
    <published>2023-10-27T21:21:20.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>早在今日之前，本站一直使用<code>OHTTPS</code>来申请、部署 CDN 加速域名的 SSL 证书，以便开启<code>HTTPS</code>支持。  </p><div class="tag link"><a class="link-card" title="免费申请SSL证书" href="/posts/38768"><div class="left"><img class="no-lightbox" src="/img/icon/blog.png"/></div><div class="right"><p class="text">免费申请SSL证书</p><p class="url">/posts/38768</p></div></a></div><p>为什么不再使用该方法了？  </p><ul><li>收费……虽然有额度，但看着每次更新一次扣 50，部署一次扣 50，多少有点隐忧；  </li><li>繁琐。这是因为，每次新增 CDN 域名时，都需要重新在<code>OHTTPS</code>管理台手动新增配置；</li></ul><h2 id="云函数自动申请-部署证书"><a href="#云函数自动申请-部署证书" class="headerlink" title="云函数自动申请&amp;部署证书"></a>云函数自动申请&amp;部署证书</h2><p>终极解决方案就是本篇。通过腾讯云函数（SCF），借助<code>ACME</code>协议，从 Let’s Encrypt 获得免费的 SSL 证书！优点：  </p><ol><li>部署在 SCF 上，成本基本为 0 （腾讯云托管的域名，一定要备案关联到某个 IP 上，当时就买了这个备案用的 SCF 套餐，3 年也没多少钱，还能用在好多地方）；  </li><li>自动申请：配置定时任务后，证书到期前自动申请；  </li><li>自动配置：改进后的版本，支持从 CDN 自动获取已配置的加速域名，自动完成域名证书绑定；  </li><li>事件通知：配置成功 or 失败时，会通过企业微信机器人通知；</li></ol><p>感谢原作者 <a href="https://github.com/Jeff2Ma/acme-qcloud-scf">Jeff2Ma</a> 分享方法，我只是略作以下改进：  </p><ul><li>自动获取域名:无需配置 cdnDomainList，不再从配置中获取 cdn 域名列表；  </li><li>延迟处理：执行删除旧证书时，增加 300ms 延迟，避免超出 1s 最多 10 条的最大限制导致的接口报错；  </li><li>环境变量：变量信息调整为环境变量获取；  </li><li>成功通知：增加了更新成功时机器人通知信息；</li></ul><h3 id="第一步：克隆本项目，本地安装依赖"><a href="#第一步：克隆本项目，本地安装依赖" class="headerlink" title="第一步：克隆本项目，本地安装依赖"></a>第一步：克隆本项目，本地安装依赖</h3><p>本地新建一个文件夹，直接克隆：  </p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> git@github.com:kuole-o/acme-qcloud-scf.git</span><br></pre></td></tr></table></figure><p>或点击下面链接直接下载代码包，解压缩；  </p><div class="tag link"><a class="link-card" title="acme-qcloud-scf" href="https://github.com/kuole-o/acme-qcloud-scf"><div class="left"><img class="no-lightbox" src="/img/icon/github.png"/></div><div class="right"><p class="text">acme-qcloud-scf</p><p class="url">https://github.com/kuole-o/acme-qcloud-scf</p></div></a></div><h3 id="第二步：安装依赖"><a href="#第二步：安装依赖" class="headerlink" title="第二步：安装依赖"></a>第二步：安装依赖</h3><p>进入该文件夹，执行<code>npm install</code>安装依赖。</p><h3 id="第三步：打包依赖包，创建层"><a href="#第三步：打包依赖包，创建层" class="headerlink" title="第三步：打包依赖包，创建层"></a>第三步：打包依赖包，创建层</h3><p>进入<code>node_modules</code>目录，全选压缩为 .zip 包（一定要进入后全选）。随后打开 <a href="https://console.cloud.tencent.com/scf/layer?rid=5">云函数 · 层</a>，新建层，名称随意，上传该压缩包。运行环境与下文创建的云函数相同即可，建议 Node.js 16.13 及以上版本。  </p><p><img src="https://cdn.guole.fun/img/202310/%E5%B1%82.png" alt="层"></p><h3 id="第四步：新建云函数"><a href="#第四步：新建云函数" class="headerlink" title="第四步：新建云函数"></a>第四步：新建云函数</h3><p>在刚才层的界面，点击<code>函数服务 — 新建</code>，选择“从头开始”，接着“事件函数”。函数名称自定义，地域建议香港一类的海外，运行环境同上述层的环境比如 Node.js 16.13。其他默认，在线编辑代码中，粘贴我代码仓里<code>index.js</code>内容，再新建一个<code>config.js</code>同理粘贴代码。  </p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">index.js</button><button type="button" class="tab">config.js</button></div><div class="tab-contents"><div class="tab-item-content active"><figure class="highlight js"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> isScfEnv = <span class="literal">false</span>; <span class="comment">// 是否是云函数环境</span></span><br><span class="line"><span class="keyword">const</span> moment = <span class="built_in">require</span>(<span class="string">&#x27;moment&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> acme = <span class="built_in">require</span>(<span class="string">&#x27;acme-client&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> tencentcloud = <span class="built_in">require</span>(<span class="string">&quot;tencentcloud-sdk-nodejs&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> axios = <span class="built_in">require</span>(<span class="string">&#x27;axios&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> appName = <span class="string">&#x27;[acme-qcloud-scf]&#x27;</span>;</span><br><span class="line"></span><br><span class="line">acme.<span class="title function_">setLogger</span>(<span class="function">(<span class="params">message</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(message);</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">let</span> config = &#123;&#125;;</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">  config = <span class="built_in">require</span>(<span class="string">&#x27;./config.js&#x27;</span>)</span><br><span class="line">&#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(e);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">log</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> args = [];</span><br><span class="line">  args.<span class="title function_">push</span>(appName);</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="variable language_">arguments</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    args.<span class="title function_">push</span>(<span class="variable language_">arguments</span>[i]);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="property">log</span>.<span class="title function_">apply</span>(<span class="variable language_">console</span>, args);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// dnspod 实例</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">DnspodApi</span> = <span class="built_in">require</span>(<span class="string">&#x27;dnspod-api&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> dnspodApi = <span class="keyword">new</span> <span class="title class_">DnspodApi</span>(&#123;</span><br><span class="line">  <span class="attr">server</span>: config.<span class="property">dnspodServer</span> || <span class="string">&#x27;dnspod.cn&#x27;</span>,</span><br><span class="line">  <span class="attr">token</span>: config.<span class="property">dnspodToken</span> <span class="comment">// your login token, you can find how to get this at the top.</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> sslClient = <span class="keyword">new</span> tencentcloud.<span class="property">ssl</span>.<span class="property">v20191205</span>.<span class="title class_">Client</span>(&#123;</span><br><span class="line">  <span class="attr">credential</span>: &#123;</span><br><span class="line">    <span class="attr">secretId</span>: config.<span class="property">qcloudSecretId</span>,</span><br><span class="line">    <span class="attr">secretKey</span>: config.<span class="property">qcloudSecretKey</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// region: &quot;ap-shanghai&quot;,</span></span><br><span class="line">  <span class="attr">profile</span>: &#123;</span><br><span class="line">    <span class="attr">signMethod</span>: <span class="string">&quot;TC3-HMAC-SHA256&quot;</span>,</span><br><span class="line">    <span class="attr">httpProfile</span>: &#123;</span><br><span class="line">      <span class="attr">reqMethod</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">      <span class="attr">reqTimeout</span>: <span class="number">30</span>,</span><br><span class="line">      <span class="attr">endpoint</span>: <span class="string">&quot;ssl.tencentcloudapi.com&quot;</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> cdnClient = <span class="keyword">new</span> tencentcloud.<span class="property">cdn</span>.<span class="property">v20180606</span>.<span class="title class_">Client</span>(&#123;</span><br><span class="line">  <span class="attr">credential</span>: &#123;</span><br><span class="line">    <span class="attr">secretId</span>: config.<span class="property">qcloudSecretId</span>,</span><br><span class="line">    <span class="attr">secretKey</span>: config.<span class="property">qcloudSecretKey</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">profile</span>: &#123;</span><br><span class="line">    <span class="attr">signMethod</span>: <span class="string">&quot;TC3-HMAC-SHA256&quot;</span>,</span><br><span class="line">    <span class="attr">httpProfile</span>: &#123;</span><br><span class="line">      <span class="attr">reqMethod</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">      <span class="attr">reqTimeout</span>: <span class="number">30</span>,</span><br><span class="line">      <span class="attr">endpoint</span>: <span class="string">&quot;cdn.tencentcloudapi.com&quot;</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">cdnList</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> params = &#123;&#125;;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> data = <span class="keyword">await</span> cdnClient.<span class="title class_">DescribeDomains</span>(params);</span><br><span class="line">    <span class="keyword">if</span> (data &amp;&amp; data.<span class="property">Domains</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> domainArray = data.<span class="property">Domains</span>.<span class="title function_">map</span>(<span class="function">(<span class="params">domainInfo</span>) =&gt;</span> domainInfo.<span class="property">Domain</span>);</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(domainArray);</span><br><span class="line">      <span class="keyword">return</span> domainArray;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&quot;Error: Unable to retrieve domain data&quot;</span>);</span><br><span class="line">      <span class="keyword">return</span> [];</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&quot;error&quot;</span>, err);</span><br><span class="line">    <span class="keyword">return</span> [];</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> webHookUrl = config?.<span class="property">wecomWebHook</span> || <span class="string">&#x27;&#x27;</span>; <span class="comment">// 暂时不用</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">challengeCreateFn</span>(<span class="params">authz, challenge, keyAuthorization</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> dnsRecord = <span class="string">`_acme-challenge.<span class="subst">$&#123;authz.identifier.value&#125;</span>`</span>;</span><br><span class="line">  <span class="keyword">const</span> recordValue = keyAuthorization;</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">`Creating TXT record for <span class="subst">$&#123;authz.identifier.value&#125;</span>: <span class="subst">$&#123;dnsRecord&#125;</span>`</span>);</span><br><span class="line">  <span class="comment">// 清空所有的 DNS 记录</span></span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">removeOldDNSRecords</span>(<span class="string">&#x27;firstTime&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> createRes = <span class="keyword">await</span> dnspodApi.<span class="title function_">do</span>(&#123;</span><br><span class="line">    <span class="attr">action</span>: <span class="string">&#x27;Record.Create&#x27;</span>,</span><br><span class="line">    <span class="attr">params</span>: &#123;</span><br><span class="line">      <span class="attr">domain</span>: config.<span class="property">domain</span>,</span><br><span class="line">      <span class="attr">sub_domain</span>: <span class="string">&#x27;_acme-challenge&#x27;</span>,</span><br><span class="line">      <span class="attr">record_line</span>: <span class="string">&#x27;默认&#x27;</span>,</span><br><span class="line">      <span class="attr">mx</span>: <span class="string">&#x27;1&#x27;</span>,</span><br><span class="line">      <span class="attr">record_type</span>: <span class="string">&#x27;TXT&#x27;</span>,</span><br><span class="line">      <span class="attr">value</span>: recordValue</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">&#x27;createRes&#x27;</span>, createRes.<span class="property">status</span>)</span><br><span class="line">  <span class="keyword">return</span> createRes</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">challengeRemoveFn</span>(<span class="params">authz, challenge, keyAuthorization</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> dnsRecord = <span class="string">`_acme-challenge.<span class="subst">$&#123;authz.identifier.value&#125;</span>`</span>;</span><br><span class="line">  <span class="keyword">const</span> recordValue = keyAuthorization;</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">`Removing TXT record for <span class="subst">$&#123;authz.identifier.value&#125;</span>: <span class="subst">$&#123;dnsRecord&#125;</span>`</span>);</span><br><span class="line">  <span class="keyword">const</span> recordListData = <span class="keyword">await</span> dnspodApi.<span class="title function_">do</span>(&#123;</span><br><span class="line">    <span class="attr">action</span>: <span class="string">&#x27;Record.List&#x27;</span>,</span><br><span class="line">    <span class="attr">params</span>: &#123;</span><br><span class="line">      <span class="attr">domain</span>: config.<span class="property">domain</span>,</span><br><span class="line">      <span class="attr">sub_domain</span>: <span class="string">&#x27;_acme-challenge&#x27;</span>,</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">log</span>(e)</span><br><span class="line">    <span class="keyword">return</span> &#123;&#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">&#x27;challengeRemoveFn:recordListData&#x27;</span>, recordListData.<span class="property">status</span>)</span><br><span class="line">  <span class="comment">//   status: &#123; code: &#x27;10&#x27;, message: &#x27;记录列表为空&#x27;, created_at: &#x27;2022-05-01 11:23:49&#x27; &#125;,</span></span><br><span class="line">  <span class="keyword">if</span> (recordListData?.<span class="property">status</span>?.<span class="property">code</span> + <span class="string">&#x27;&#x27;</span> === <span class="string">&#x27;10&#x27;</span>) &#123;</span><br><span class="line">    <span class="title function_">log</span>(<span class="string">&#x27;删除 dns 记录，已为空&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> &#123;&#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> records = recordListData?.<span class="property">records</span>;</span><br><span class="line">    <span class="comment">// log(&#x27;records&#x27;, records)</span></span><br><span class="line">    <span class="keyword">const</span> record = records.<span class="title function_">find</span>(<span class="function"><span class="params">item</span> =&gt;</span> item.<span class="property">value</span> === dnsRecord)</span><br><span class="line">    <span class="keyword">const</span> res = <span class="keyword">await</span> dnspodApi.<span class="title function_">do</span>(&#123;</span><br><span class="line">      <span class="attr">action</span>: <span class="string">&#x27;Record.Remove&#x27;</span>,</span><br><span class="line">      <span class="attr">params</span>: &#123;</span><br><span class="line">        <span class="attr">domain</span>: config.<span class="property">domain</span>,</span><br><span class="line">        <span class="attr">sub_domain</span>: <span class="string">&#x27;_acme-challenge&#x27;</span>,</span><br><span class="line">        <span class="attr">record_line</span>: <span class="string">&#x27;默认&#x27;</span>,</span><br><span class="line">        <span class="attr">mx</span>: <span class="string">&#x27;1&#x27;</span>,</span><br><span class="line">        <span class="attr">record_id</span>: record.<span class="property">id</span>,</span><br><span class="line">        <span class="attr">record_type</span>: <span class="string">&#x27;TXT&#x27;</span>,</span><br><span class="line">        <span class="comment">// value: recordValue</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="title function_">log</span>(<span class="string">&#x27;Record.Remove Success:&#x27;</span>, res.<span class="property">status</span>);</span><br><span class="line">    <span class="keyword">return</span> &#123;&#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">removeOldDNSRecords</span>(<span class="params"><span class="keyword">from</span> = <span class="string">&#x27;&#x27;</span></span>) &#123;</span><br><span class="line">  <span class="comment">// https://docs.dnspod.cn/api/modify-records/</span></span><br><span class="line">  <span class="keyword">const</span> recordListData = <span class="keyword">await</span> dnspodApi.<span class="title function_">do</span>(&#123;</span><br><span class="line">    <span class="attr">action</span>: <span class="string">&#x27;Record.List&#x27;</span>,</span><br><span class="line">    <span class="attr">params</span>: &#123;</span><br><span class="line">      <span class="attr">domain</span>: config.<span class="property">domain</span>,</span><br><span class="line">      <span class="attr">sub_domain</span>: <span class="string">&#x27;_acme-challenge&#x27;</span>,</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">log</span>(e)</span><br><span class="line">    <span class="keyword">return</span> &#123;&#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">&#x27;removeOldDNSRecords:recordListData&#x27;</span>, recordListData.<span class="property">status</span>);</span><br><span class="line">  <span class="keyword">if</span> (recordListData?.<span class="property">status</span>?.<span class="property">code</span> + <span class="string">&#x27;&#x27;</span> === <span class="string">&#x27;10&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(&#123;</span><br><span class="line">      <span class="attr">empty</span>: <span class="literal">true</span>,</span><br><span class="line">      <span class="attr">length</span>: <span class="number">0</span>,</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> records = recordListData?.<span class="property">records</span>;</span><br><span class="line">  <span class="keyword">if</span> (records.<span class="property">length</span>) &#123;</span><br><span class="line">    <span class="title function_">log</span>(<span class="string">&#x27;提示：检测到有旧的 dns 记录，尝试全部删除&#x27;</span>);</span><br><span class="line">    <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(records.<span class="title function_">map</span>(<span class="keyword">async</span> item =&gt; &#123;</span><br><span class="line">      <span class="keyword">const</span> res = <span class="keyword">await</span> dnspodApi.<span class="title function_">do</span>(&#123;</span><br><span class="line">        <span class="attr">action</span>: <span class="string">&#x27;Record.Remove&#x27;</span>,</span><br><span class="line">        <span class="attr">params</span>: &#123;</span><br><span class="line">          <span class="attr">domain</span>: config.<span class="property">domain</span>,</span><br><span class="line">          <span class="attr">sub_domain</span>: <span class="string">&#x27;_acme-challenge&#x27;</span>,</span><br><span class="line">          <span class="attr">record_line</span>: <span class="string">&#x27;默认&#x27;</span>,</span><br><span class="line">          <span class="attr">mx</span>: <span class="string">&#x27;1&#x27;</span>,</span><br><span class="line">          <span class="attr">record_id</span>: item.<span class="property">id</span>,</span><br><span class="line">          <span class="attr">record_type</span>: <span class="string">&#x27;TXT&#x27;</span>,</span><br><span class="line">          <span class="comment">// value: recordValue</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">      <span class="title function_">log</span>(<span class="string">`Record.Remove Success:<span class="subst">$&#123;item.id&#125;</span>`</span>, res.<span class="property">status</span>)</span><br><span class="line">    &#125;))</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">from</span> &amp;&amp; <span class="keyword">from</span> === <span class="string">&#x27;firstTime&#x27;</span>) &#123;</span><br><span class="line">      <span class="title function_">log</span>(<span class="string">&#x27;延迟 15s，预防 dns 缓存因素影响&#x27;</span>);</span><br><span class="line">      <span class="keyword">await</span> <span class="title function_">sleep</span>(<span class="number">15</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> &#123;&#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(&#123;</span><br><span class="line">    <span class="attr">empty</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">length</span>: <span class="number">0</span>,</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">sleep</span>(<span class="params">s</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> <span class="built_in">setTimeout</span>(resolve, s * <span class="number">1000</span>));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">uploadCert2QcloudSSL</span>(<span class="params">cert, key</span>) &#123;</span><br><span class="line">  <span class="comment">// 腾讯云 SDK</span></span><br><span class="line">  <span class="title function_">log</span>(<span class="string">&#x27;正在上传到腾讯云 SSL 管理...&#x27;</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 待删除旧的</span></span><br><span class="line">  <span class="keyword">const</span> &#123; <span class="title class_">TotalCount</span>, <span class="title class_">Certificates</span> &#125; = <span class="keyword">await</span> sslClient.<span class="title class_">DescribeCertificates</span>(</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="title class_">SearchKey</span>: config.<span class="property">domain</span></span><br><span class="line">    &#125;</span><br><span class="line">  ).<span class="title function_">catch</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (<span class="title class_">TotalCount</span> &amp;&amp; <span class="title class_">Certificates</span>.<span class="property">length</span>) &#123;</span><br><span class="line">    <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(<span class="title class_">Certificates</span>.<span class="title function_">map</span>(<span class="title function_">async</span> (item, index) =&gt; &#123;</span><br><span class="line">      <span class="keyword">await</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> <span class="built_in">setTimeout</span>(resolve, index * <span class="number">300</span>));</span><br><span class="line"></span><br><span class="line">      <span class="keyword">await</span> sslClient.<span class="title class_">DeleteCertificate</span>(&#123;</span><br><span class="line">        <span class="title class_">CertificateId</span>: item.<span class="property">CertificateId</span></span><br><span class="line">      &#125;);</span><br><span class="line">      <span class="title function_">log</span>(<span class="string">`正在删除<span class="subst">$&#123;item.CertificateId&#125;</span>, <span class="subst">$&#123;item.Domain&#125;</span> 证书`</span>);</span><br><span class="line">    &#125;));</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> uploadCertificateRes = <span class="keyword">await</span> sslClient.<span class="title class_">UploadCertificate</span>(&#123;</span><br><span class="line">    <span class="title class_">CertificatePublicKey</span>: cert.<span class="title function_">toString</span>(),</span><br><span class="line">    <span class="title class_">CertificatePrivateKey</span>: key.<span class="title function_">toString</span>(),</span><br><span class="line">    <span class="title class_">Alias</span>: config.<span class="property">domain</span></span><br><span class="line">  &#125;).<span class="title function_">catch</span>(<span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(e);</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">&#x27;上传本次产生的证书: &#x27;</span>, uploadCertificateRes);</span><br><span class="line">  <span class="keyword">return</span> uploadCertificateRes;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">initConfig</span>(<span class="params">config, env</span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> envFormat = &#123;&#125;;</span><br><span class="line">  <span class="keyword">if</span> (env &amp;&amp; <span class="keyword">typeof</span> env === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      envFormat = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(env)</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Object</span>.<span class="title function_">assign</span>(&#123;&#125;, config, envFormat)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">updateCDNDomains</span>(<span class="params">cert, key, CertificateId</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> nowStr = <span class="title function_">moment</span>(<span class="keyword">new</span> <span class="title class_">Date</span>()).<span class="title function_">utcOffset</span>(<span class="number">8</span>).<span class="title function_">format</span>(<span class="string">&#x27;YYYY-MM-DD HH:mm:ss&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> list = <span class="keyword">await</span> <span class="title function_">cdnList</span>();</span><br><span class="line">  <span class="keyword">if</span> (!list || !list.<span class="property">length</span>) <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(&#123;&#125;)</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(list.<span class="title function_">map</span>(<span class="keyword">async</span> item =&gt; &#123;</span><br><span class="line">      <span class="title function_">log</span>(<span class="string">`正在为如下 cdn 域名进行 https 证书绑定：<span class="subst">$&#123;item&#125;</span>, <span class="subst">$&#123;CertificateId&#125;</span>`</span>)</span><br><span class="line">      <span class="keyword">await</span> cdnClient.<span class="title class_">UpdateDomainConfig</span>(&#123;</span><br><span class="line">        <span class="title class_">Domain</span>: item,</span><br><span class="line">        <span class="title class_">Https</span>: &#123;</span><br><span class="line">          <span class="title class_">Switch</span>: <span class="string">&#x27;on&#x27;</span>,</span><br><span class="line">          <span class="title class_">Http2</span>: <span class="string">&#x27;on&#x27;</span>,</span><br><span class="line">          <span class="title class_">CertInfo</span>: &#123;</span><br><span class="line">            <span class="title class_">CertId</span>: <span class="title class_">CertificateId</span>,</span><br><span class="line">            <span class="title class_">Message</span>: <span class="string">`<span class="subst">$&#123;appName&#125;</span><span class="subst">$&#123;nowStr&#125;</span>`</span>,</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;).<span class="title function_">then</span>(</span><br><span class="line">        <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="title function_">log</span>(data);</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&quot;error&quot;</span>, err);</span><br><span class="line">        &#125;</span><br><span class="line">      );</span><br><span class="line">    &#125;))</span><br><span class="line">    <span class="keyword">return</span> list</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&quot;error&quot;</span>, 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="keyword">async</span> <span class="keyword">function</span> <span class="title function_">postWeComRobotMsg</span>(<span class="params">options</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> content = options?.<span class="property">content</span> || <span class="string">&#x27;&#x27;</span></span><br><span class="line">  <span class="keyword">if</span> (!content) <span class="keyword">return</span> <span class="string">&#x27;没有消息要发送&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> postData = &#123;</span><br><span class="line">    <span class="string">&quot;msgtype&quot;</span>: <span class="string">&quot;text&quot;</span>,</span><br><span class="line">    <span class="string">&quot;text&quot;</span>: &#123;</span><br><span class="line">      <span class="attr">content</span>: (!isScfEnv ? <span class="string">&#x27;[本地调试发送]&#x27;</span> : <span class="string">&#x27;&#x27;</span>) + content</span><br><span class="line">    &#125;, <span class="string">&quot;mentioned_list&quot;</span>: [<span class="string">&quot;@all&quot;</span>]</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="keyword">return</span> axios.<span class="title function_">post</span>(config.<span class="property">wecomWebHook</span>, postData)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">res</span>) &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(res.<span class="property">data</span>);</span><br><span class="line">      <span class="keyword">return</span> res.<span class="property">data</span>;</span><br><span class="line">    &#125;)</span><br><span class="line">    .<span class="title function_">catch</span>(<span class="keyword">function</span> (<span class="params">error</span>) &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(error);</span><br><span class="line">      <span class="keyword">return</span> <span class="string">&#x27;st wrong when post qywx robot api&#x27;</span>;</span><br><span class="line">    &#125;)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">result</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">&#x27;发送企业微信机器人成功:&#x27;</span> + <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(result) + <span class="string">&#x27;H:&#x27;</span> + <span class="title function_">moment</span>().<span class="title function_">utcOffset</span>(<span class="number">8</span>).<span class="title function_">format</span>(<span class="string">&#x27;kk&#x27;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">main_handler</span> = <span class="keyword">async</span> (<span class="params">event = &#123;&#125;, context = &#123;&#125;, callback</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> environment = context?.<span class="property">environment</span> || &#123;&#125;</span><br><span class="line">  config = <span class="keyword">await</span> <span class="title function_">initConfig</span>(config, environment);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 云函数环境特有</span></span><br><span class="line">  <span class="keyword">if</span> (config[<span class="string">&#x27;SCF_NAMESPACE&#x27;</span>]) &#123;</span><br><span class="line">    isScfEnv = <span class="literal">true</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">log</span>(<span class="string">&#x27;isScfEnv&#x27;</span>, isScfEnv)</span><br><span class="line"></span><br><span class="line">  <span class="comment">/* Init client */</span></span><br><span class="line">  <span class="keyword">const</span> client = <span class="keyword">new</span> acme.<span class="title class_">Client</span>(&#123;</span><br><span class="line">    <span class="attr">directoryUrl</span>: (!isScfEnv || +(config.<span class="property">isDebug</span>)) ? acme.<span class="property">directory</span>.<span class="property">letsencrypt</span>.<span class="property">staging</span> : acme.<span class="property">directory</span>.<span class="property">letsencrypt</span>.<span class="property">production</span>,</span><br><span class="line">    <span class="attr">accountKey</span>: <span class="keyword">await</span> acme.<span class="property">forge</span>.<span class="title function_">createPrivateKey</span>(),</span><br><span class="line">    <span class="attr">termsOfServiceAgreed</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">challengePriority</span>: [<span class="string">&#x27;dns-01&#x27;</span>],</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">/* Register account */</span></span><br><span class="line">  <span class="keyword">await</span> client.<span class="title function_">createAccount</span>(&#123;</span><br><span class="line">    <span class="attr">termsOfServiceAgreed</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">contact</span>: [<span class="string">`mailto:<span class="subst">$&#123;config.email&#125;</span>`</span>]</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">/* Place new order */</span></span><br><span class="line">  <span class="keyword">const</span> order = <span class="keyword">await</span> client.<span class="title function_">createOrder</span>(&#123;</span><br><span class="line">    <span class="attr">wildcard</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">identifiers</span>: [</span><br><span class="line">      &#123; <span class="attr">type</span>: <span class="string">&#x27;dns&#x27;</span>, <span class="attr">value</span>: <span class="string">`<span class="subst">$&#123;config.domain&#125;</span>`</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">type</span>: <span class="string">&#x27;dns&#x27;</span>, <span class="attr">value</span>: <span class="string">`*.<span class="subst">$&#123;config.domain&#125;</span>`</span> &#125;</span><br><span class="line">    ]</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="comment">   * authorizations / client.getAuthorizations(order);</span></span><br><span class="line"><span class="comment">   * An array with one item per DNS name in the certificate order.</span></span><br><span class="line"><span class="comment">   * All items require at least one satisfied challenge before order can be completed.</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> authorizations = <span class="keyword">await</span> client.<span class="title function_">getAuthorizations</span>(order);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> promises = authorizations.<span class="title function_">map</span>(<span class="title function_">async</span> (authz) =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> challengeCompleted = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="comment">/**</span></span><br><span class="line"><span class="comment">       * challenges / authz.challenges</span></span><br><span class="line"><span class="comment">       * An array of all available challenge types for a single DNS name.</span></span><br><span class="line"><span class="comment">       * One of these challenges needs to be satisfied.</span></span><br><span class="line"><span class="comment">       */</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">const</span> &#123; challenges &#125; = authz;</span><br><span class="line"></span><br><span class="line">      <span class="comment">/* Just select Dns Way */</span></span><br><span class="line">      <span class="keyword">const</span> challenge = challenges.<span class="title function_">find</span>(<span class="function"><span class="params">c</span> =&gt;</span> c.<span class="property">type</span> === <span class="string">&#x27;dns-01&#x27;</span>);</span><br><span class="line"></span><br><span class="line">      <span class="keyword">const</span> keyAuthorization = <span class="keyword">await</span> client.<span class="title function_">getChallengeKeyAuthorization</span>(challenge);</span><br><span class="line"></span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">/* Satisfy challenge */</span></span><br><span class="line">        <span class="keyword">await</span> <span class="title function_">challengeCreateFn</span>(authz, challenge, keyAuthorization);</span><br><span class="line"></span><br><span class="line">        <span class="title function_">log</span>(<span class="string">&#x27;延迟 15s，预防 dns 缓存因素影响&#x27;</span>);</span><br><span class="line">        <span class="keyword">await</span> <span class="title function_">sleep</span>(<span class="number">15</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">/* Verify that challenge is satisfied */</span></span><br><span class="line">        <span class="keyword">await</span> client.<span class="title function_">verifyChallenge</span>(authz, challenge);</span><br><span class="line"></span><br><span class="line">        <span class="comment">/* Notify ACME provider that challenge is satisfied */</span></span><br><span class="line">        <span class="keyword">await</span> client.<span class="title function_">completeChallenge</span>(challenge);</span><br><span class="line">        challengeCompleted = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">/* Wait for ACME provider to respond with valid status */</span></span><br><span class="line">        <span class="keyword">await</span> client.<span class="title function_">waitForValidStatus</span>(challenge);</span><br><span class="line">      &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="comment">/* Clean up challenge response */</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="comment">// await challengeRemoveFn(authz, challenge, keyAuthorization);</span></span><br><span class="line">        &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">          <span class="comment">/**</span></span><br><span class="line"><span class="comment">           * Catch errors thrown by challengeRemoveFn() so the order can</span></span><br><span class="line"><span class="comment">           * be finalized, even though something went wrong during cleanup</span></span><br><span class="line"><span class="comment">           */</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">      <span class="comment">/* Deactivate pending authz when unable to complete challenge */</span></span><br><span class="line">      <span class="keyword">if</span> (!challengeCompleted) &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="keyword">await</span> client.<span class="title function_">deactivateAuthorization</span>(authz);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (f) &#123;</span><br><span class="line">          <span class="comment">/* Catch and suppress deactivateAuthorization() errors */</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">throw</span> e;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">/* Wait for challenges to complete */</span></span><br><span class="line">  <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(promises);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="comment">/* Finalize order */</span></span><br><span class="line">    <span class="keyword">const</span> [key, csr] = <span class="keyword">await</span> acme.<span class="property">forge</span>.<span class="title function_">createCsr</span>(&#123;</span><br><span class="line">      <span class="attr">commonName</span>: <span class="string">`*.<span class="subst">$&#123;config.domain&#125;</span>`</span>,</span><br><span class="line">      <span class="attr">altNames</span>: [<span class="string">`<span class="subst">$&#123;config.domain&#125;</span>`</span>]</span><br><span class="line">      <span class="comment">// commonName: `$&#123;config.domain&#125;`,//  建议用根域名</span></span><br><span class="line">      <span class="comment">// altNames: [`$&#123;config.domain&#125;`, `*.$&#123;config.domain&#125;`]</span></span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> finalized = <span class="keyword">await</span> client.<span class="title function_">finalizeOrder</span>(order, csr);</span><br><span class="line">    <span class="keyword">const</span> cert = <span class="keyword">await</span> client.<span class="title function_">getCertificate</span>(finalized);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* 完成 */</span></span><br><span class="line">    <span class="title function_">log</span>(<span class="string">`CSR:\n<span class="subst">$&#123;csr.toString()&#125;</span>`</span>);</span><br><span class="line">    <span class="title function_">log</span>(<span class="string">`Private key:\n<span class="subst">$&#123;key.toString()&#125;</span>`</span>);</span><br><span class="line">    <span class="title function_">log</span>(<span class="string">`Certificate:\n<span class="subst">$&#123;cert.toString()&#125;</span>`</span>);</span><br><span class="line">    <span class="keyword">const</span> &#123; <span class="title class_">CertificateId</span> &#125; = <span class="keyword">await</span> <span class="title function_">uploadCert2QcloudSSL</span>(cert, key);</span><br><span class="line">    <span class="keyword">const</span> list = <span class="keyword">await</span> <span class="title function_">updateCDNDomains</span>(cert, key, <span class="title class_">CertificateId</span>);</span><br><span class="line">    <span class="keyword">const</span> formattedList = list.<span class="title function_">join</span>(<span class="string">&#x27;\n&#x27;</span>);</span><br><span class="line">    <span class="keyword">await</span> <span class="title function_">postWeComRobotMsg</span>(&#123;</span><br><span class="line">      <span class="attr">content</span>: <span class="string">`SSL 证书已更新！\n\n证书ID：<span class="subst">$&#123;CertificateId&#125;</span>\n更新域名：\n<span class="subst">$&#123;formattedList&#125;</span>`</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">    <span class="title function_">log</span>(<span class="string">&#x27;Finalize order error: &#x27;</span>, e)</span><br><span class="line">    <span class="keyword">await</span> <span class="title function_">postWeComRobotMsg</span>(&#123;</span><br><span class="line">      <span class="attr">content</span>: <span class="string">`生成证书失败<span class="subst">$&#123;<span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(e))&#125;</span>`</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 清空多余的 dnsPod 记录</span></span><br><span class="line">  <span class="keyword">await</span> <span class="title function_">removeOldDNSRecords</span>()</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">const</span> <span class="title function_">main_handler_bak</span> = <span class="keyword">async</span> (<span class="params">event = &#123;&#125;, context = &#123;&#125;, callback</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> params = &#123;&#125;;</span><br><span class="line">    <span class="keyword">const</span> data = <span class="keyword">await</span> cdnClient.<span class="title class_">DescribeDomains</span>(params);</span><br><span class="line">    <span class="keyword">const</span> domainArray = data.<span class="property">Domains</span>.<span class="title function_">map</span>(<span class="function">(<span class="params">domainInfo</span>) =&gt;</span> domainInfo.<span class="property">Domain</span>);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(domainArray);</span><br><span class="line">    <span class="keyword">return</span> domainArray;</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&quot;error&quot;</span>, err);</span><br><span class="line">    <span class="keyword">return</span> 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="built_in">exports</span>.<span class="property">main_handler</span> = main_handler</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight js"><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="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">    <span class="attr">isDebug</span>: <span class="literal">true</span>, <span class="comment">// 验证完成后，此项必须配置为 false，否则申请的是测试证书，浏览器会报错“无效证书”</span></span><br><span class="line">    <span class="attr">email</span>: process.<span class="property">env</span>.<span class="property">Email</span>,  <span class="comment">// 你的邮箱</span></span><br><span class="line">    <span class="attr">domain</span>: process.<span class="property">env</span>.<span class="property">Domain</span>, <span class="comment">// 需要生成证书的根域名，最终生成通配符证书</span></span><br><span class="line">    <span class="attr">qcloudSecretId</span>: process.<span class="property">env</span>.<span class="property">Tcb_SecretId</span>, <span class="comment">// 腾讯云 SecretId, https://console.cloud.tencent.com/cam/capi</span></span><br><span class="line">    <span class="attr">qcloudSecretKey</span>: process.<span class="property">env</span>.<span class="property">Tcb_SecretKey</span>, <span class="comment">// 腾讯云 SecretKey</span></span><br><span class="line">    <span class="attr">dnspodServer</span>: <span class="string">&#x27;dnspod.cn&#x27;</span>, <span class="comment">// 国内版用 dnspod.cn（默认），国际版用 dnspod.com</span></span><br><span class="line">    <span class="attr">dnspodToken</span>: process.<span class="property">env</span>.<span class="property">Tcb_DnspodToken</span>, <span class="comment">// 在 https://console.dnspod.cn/account/token/token 生成，合在一块用, 隔开</span></span><br><span class="line">    <span class="attr">wecomWebHook</span>: process.<span class="property">env</span>.<span class="property">WeComWebHook</span>, <span class="comment">// 企业微信机器人通知 webhook</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>日志配置，建议开启（虽然说要钱，但是也没多少……）。高级配置中，其他不要动，把“执行超时时间”设置为最大 900m，环境变量配置：  </p><table><thead><tr><th>字段名</th><th>来源</th><th>说明</th></tr></thead><tbody><tr><td>Email</td><td>自定义输入</td><td>你的邮箱地址，用来申请证书</td></tr><tr><td>Tcb_DnspodToken</td><td>腾讯云获取</td><td>腾讯云 dnspod Token，获取见下文</td></tr><tr><td>Tcb_SecretId</td><td>腾讯云获取</td><td>腾讯云 API SecretId，获取见下文</td></tr><tr><td>Tcb_SecretKey</td><td>腾讯云获取</td><td>腾讯云 API SecretKey，获取见下文</td></tr><tr><td>WeComWebHook</td><td>企业微信获取</td><td>企业微信群机器人的 WebHook 地址，不了解可以 Google 下</td></tr><tr><td>domain</td><td>自定义输入</td><td>你的根域名，比如本站是 guole.fun</td></tr></tbody></table><p>上述相关密钥获取方法：  </p><ul><li>Tcb_DnspodToken：访问 <a href="https://console.dnspod.cn/account/token/token">DNSPod - DNSPod Token</a> 手动创建一个；</li><li>Tcb_SecretId &#x2F; Tcb_SecretKey：访问 <a href="https://console.dnspod.cn/account/token/apikey">DNSPod - 腾讯云 API 密钥</a> 手动创建一个，获得 SecretId 和 SecretKey；建议在 <a href="https://console.cloud.tencent.com/cam">腾讯云 - 访问管理 - 用户列表</a> 中，创建一个子用户，添加 QcloudDNSPodFullAccess &#x2F; QcloudCDNFullAccess &#x2F; QcloudSSLFullAccess 三个策略组权限，更安全。</li></ul><p><img src="https://cdn.guole.fun/img/202310/%E5%88%9B%E5%BB%BA%E4%BA%91%E5%87%BD%E6%95%B0.png" alt="创建云函数"></p><p>点击确定，部署云函数。  </p><h3 id="第五步：触发器"><a href="#第五步：触发器" class="headerlink" title="第五步：触发器"></a>第五步：触发器</h3><p>在云函数触发管理中，配置一个<code>定时触发器</code>，选择“自定义触发周期”，这个是<code>cron表达式</code>，我设置的是：  </p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">0 0 8 1 1,4,7,10 ? *</span><br></pre></td></tr></table></figure><p>表示在每年第 1 &#x2F; 4 &#x2F; 7 &#x2F; 10 月份的第一天早上 08:00 执行。（因为证书有效期 3 个月，我这次是在 10 月份创建的，过期时间是 2023.1.25，那下次自动更新可以在 1.1 ，其他月类推）  </p><p>接着，创建一个<code>API网关触发</code>触发器，这个方便你调试，浏览器访问就能触发云函数。选择“API网关触发”，其他配置项都默认即可。  </p><p><img src="https://cdn.guole.fun/img/202310/%E8%A7%A6%E5%8F%91%E5%99%A8.png" alt="触发器"></p><h3 id="第六步：绑定层并调试"><a href="#第六步：绑定层并调试" class="headerlink" title="第六步：绑定层并调试"></a>第六步：绑定层并调试</h3><p>这里还没完成，再去云函数“函数管理 - 层管理”中，绑定上述创建的层。然后浏览器访问上面的 API 网关触发器地址，试试行不行。如果说没有依赖，找不到 xx 模块，就去函数管理中，重新部署一次，因为上面层绑定是在部署完云函数进行的，不确定有没有问题。  </p><p><img src="https://cdn.guole.fun/img/202310/%E5%B1%82%E7%AE%A1%E7%90%86.png" alt="绑定层"></p><p>正式使用时，记得在云函数 <code>config.js</code> 中，将 <code>isDebug</code> 配置为 <code>false</code>，不然申请的是 Let’s Encrypt 测试证书，浏览器会报“无效证书”无法使用。（折磨了我好几个小时才找到原因，谁懂啊……）  </p><p>最后，享受一切自动化的服务吧！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;早在今日之前，本站一直使用&lt;code&gt;OHTTPS&lt;/code&gt;来申请、部署 CDN 加速域名的 SSL 证书，以便开启&lt;code&gt;HTTPS&lt;/code&gt;支持。  &lt;/p&gt;
&lt;div class=&quot;tag link&quot;&gt;&lt;a class=&quot;link-card&quot; title=</summary>
      
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="踩坑笔记" scheme="https://blog.guole.fun/tags/%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>2023 国庆游记 | 音乐节心潮澎湃，长沙值得再来</title>
    <link href="https://blog.guole.fun/posts/37863/"/>
    <id>https://blog.guole.fun/posts/37863/</id>
    <published>2023-10-13T22:45:20.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>经过 7 天的搬砖折磨，终于有空记录下我的 2023 国庆游记。  </p><h1 id="行程-Ⅰ-佛山国潮音乐节：动次打次过足瘾"><a href="#行程-Ⅰ-佛山国潮音乐节：动次打次过足瘾" class="headerlink" title="行程 Ⅰ | 佛山国潮音乐节：动次打次过足瘾"></a>行程 Ⅰ | 佛山国潮音乐节：动次打次过足瘾</h1><p>冲着<code>麻园诗人</code>，<code>二手玫瑰</code>，<code>许巍</code>去的，现场依然令人动容，但谁懂社恐 i 人那种想嗨又放不开，只敢抖抖腿、晃晃头的感觉啊！！  </p><p><img src="https://cdn.guole.fun/img/202310/20231001-07.jpg" alt="佛山国潮音乐节">  </p><div class="note danger no-icon flat"><ol><li>吐槽「国潮」主办方。我都走到检票口了，告诉我电子票一定要换实体票。ok，那我换，但你告诉我要走到最外面入口？大桥底下？走过去一看，很小的一个换票口，也没什么横幅指引，鬼知道要来这里换票？  </li><li>检票贼慢，一直卡者人不让进，遮阳伞不让带，你还广播提醒“谨防中暑”？我用啥防啊……</li></ol></div><h2 id="麻园现场还原度竟然没让人失望"><a href="#麻园现场还原度竟然没让人失望" class="headerlink" title="麻园现场还原度竟然没让人失望"></a>麻园现场还原度竟然没让人失望</h2><div class="video"><video controls preload><source src='https://cdn.guole.fun/media/20231001-%E7%8E%B0%E5%9C%A8%E7%8E%B0%E5%9C%A8.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><h2 id="二手玫瑰，一群花裤衩的狂欢"><a href="#二手玫瑰，一群花裤衩的狂欢" class="headerlink" title="二手玫瑰，一群花裤衩的狂欢"></a>二手玫瑰，一群花裤衩的狂欢</h2><div class="video"><video controls preload><source src='https://cdn.guole.fun/media/20231001-%E5%85%81%E8%AE%B8%E9%83%A8%E5%88%86%E8%89%BA%E6%9C%AF%E5%AE%B6%E5%85%88%E5%AF%8C%E8%B5%B7%E6%9D%A5.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div><h2 id="许巍连唱了六七首，赚了赚了"><a href="#许巍连唱了六七首，赚了赚了" class="headerlink" title="许巍连唱了六七首，赚了赚了"></a>许巍连唱了六七首，赚了赚了</h2><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">《第三极》</button><button type="button" class="tab">《无尽光芒》</button></div><div class="tab-contents"><div class="tab-item-content active"><div class="video"><video controls preload><source src='https://cdn.guole.fun/media/20231001-%E7%AC%AC%E4%B8%89%E6%9E%81.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div></div><div class="tab-item-content"><div class="video"><video controls preload><source src='https://cdn.guole.fun/media/20231001-%E6%97%A0%E5%B0%BD%E5%85%89%E8%8A%92.mp4' type='video/mp4'>Your browser does not support the video tag.</video></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h1 id="行程-Ⅱ-夜爬衡山是个冲动的决定"><a href="#行程-Ⅱ-夜爬衡山是个冲动的决定" class="headerlink" title="行程 Ⅱ | 夜爬衡山是个冲动的决定"></a>行程 Ⅱ | 夜爬衡山是个冲动的决定</h1><p>10.1 听完音乐节，10.2 一大早赶到衡阳，到了已经是 19:00 左右了。无他，一个堵字罢了。  </p><p>与另外几个伙伴，冲动的决定了夜！爬！衡！山！提到“冲动”倒不是腿废了，难度还好。主要是赶着看日出，山顶又冷又挤（日出平台），大雾天啥也没看着。</p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202310/20231001-05.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-09.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-10.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-11.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-12.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-13.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-14.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-17.jpg","alt":"夜访衡山","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-19.jpg","alt":"夜访衡山","title":""}]</div>  </div><h1 id="行程-Ⅲ-长沙真不赖！湖南加大分"><a href="#行程-Ⅲ-长沙真不赖！湖南加大分" class="headerlink" title="行程 Ⅲ | 长沙真不赖！湖南加大分"></a>行程 Ⅲ | 长沙真不赖！湖南加大分</h1><h2 id="橘子洲头，与伟人来张合影"><a href="#橘子洲头，与伟人来张合影" class="headerlink" title="橘子洲头，与伟人来张合影"></a>橘子洲头，与伟人来张合影</h2><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202310/20231001-28.jpg","alt":"雕塑（拍照还排队…）","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-29.jpg","alt":"夜色下的五一广场路口","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-18.jpg","alt":"橘子洲头","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-30.jpg","alt":"杜甫江阁夜景","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-32.jpg","alt":"夜色下的雕塑","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-31.jpg","alt":"夜色下的招牌","title":""}]</div>  </div><h3 id="长沙味道"><a href="#长沙味道" class="headerlink" title="长沙味道"></a>长沙味道</h3><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202310/20231001-15.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 茶油炒鸡 @衡阳","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-16.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 酸辣脆肚 @衡阳","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-21.jpg","alt":"⭐️⭐️⭐️⭐️ 咸蛋黄茄子 @彭耕记 · 九龙仓店","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-22.jpg","alt":"⭐️⭐️⭐️ 鬼手卤牛肉 @彭耕记 · 九龙仓店","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-02.jpg","alt":"⭐️⭐️⭐️ 忘了叫什么虾 @衡阳","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-03.jpg","alt":"⭐️⭐️ 忘了叫什么手撕鸭 @衡阳","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-04.jpg","alt":"⭐️⭐️⭐️ 忘了叫什么豆腐 @衡阳","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-23.jpg","alt":"⭐️⭐️⭐️⭐️ 猪油炒饭 @彭耕记 · 九龙仓店","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-24.jpg","alt":"⭐️⭐️ 酸包菜粉皮 @彭耕记 · 九龙仓店","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-25.jpg","alt":"⭐️⭐️⭐️ 贵妃醉鸡 @彭耕记 · 九龙仓店","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-26.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 酸萝卜牛百叶 @彭耕记 · 九龙仓店","title":""}]</div>  </div><h3 id="李子健美术展"><a href="#李子健美术展" class="headerlink" title="李子健美术展"></a>李子健美术展</h3><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202310/20231001-33.jpg","alt":"《乡村姑娘》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-37.jpg","alt":"《雨天》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-38.jpg","alt":"《小姑娘》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-39.jpg","alt":"《静静的小河》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-42.jpg","alt":"《小平》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-40.jpg","alt":"《春》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-43.jpg","alt":"《夏》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-44.jpg","alt":"《秋》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-45.jpg","alt":"《冬》","title":""},{"url":"https://cdn.guole.fun/img/202310/20231001-36.jpg","alt":"《丰收的喜悦》","title":""}]</div>  </div><h2 id="返程：“不知东方之既白”"><a href="#返程：“不知东方之既白”" class="headerlink" title="返程：“不知东方之既白”"></a>返程：“不知东方之既白”</h2><p><img src="https://cdn.guole.fun/img/202310/20231001-00.jpg" alt="10.6 某服务区">  </p>]]></content>
    
    
    <summary type="html">祝福祖国永远繁荣富强，人民自强不息！</summary>
    
    
    
    <category term="我的游记" scheme="https://blog.guole.fun/categories/%E6%88%91%E7%9A%84%E6%B8%B8%E8%AE%B0/"/>
    
    
    <category term="找点儿乐子" scheme="https://blog.guole.fun/tags/%E6%89%BE%E7%82%B9%E5%84%BF%E4%B9%90%E5%AD%90/"/>
    
    <category term="镜头下的风光" scheme="https://blog.guole.fun/tags/%E9%95%9C%E5%A4%B4%E4%B8%8B%E7%9A%84%E9%A3%8E%E5%85%89/"/>
    
    <category term="美食" scheme="https://blog.guole.fun/tags/%E7%BE%8E%E9%A3%9F/"/>
    
  </entry>
  
  <entry>
    <title>脚本分享 | 车载 U 盘音乐自动整理工具</title>
    <link href="https://blog.guole.fun/posts/10915/"/>
    <id>https://blog.guole.fun/posts/10915/</id>
    <published>2023-09-24T20:38:16.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>认识我的朋友都知道，我是个热爱音乐的博主，值此国庆小长假来临之际，自当整理一下我的<code>Car Music</code>，确保旅途中动次打次不停歇。  </p><p>以前都是手动整理，从网易云、QQ 音乐下载歌曲，手动解密，然后拷贝到 U 盘。于是，我面临以下重复工作：  </p><ol><li>下载歌曲，下载歌词；</li><li>拷贝到 U 盘；</li><li>痛苦的肉眼翻一遍 U 盘里的歌曲，确保“过时”（emm……就是突然不喜欢听的歌，懂得都懂）歌曲被手动移除；</li></ol><p>尤其在第三步，很繁琐。于是就有了本篇分享。  </p><h2 id="我为什么建议你在电脑另存一份-Car-Music"><a href="#我为什么建议你在电脑另存一份-Car-Music" class="headerlink" title="我为什么建议你在电脑另存一份 Car Music"></a>我为什么建议你在电脑另存一份 Car Music</h2><p>诚然，现在车联网很方便，在线听歌很便捷。当仍然无法解决付费歌曲、隧道网络差、自由歌单这些痛点。同时，一般车机上，偶尔会蹦一个“热插拔”异常，导致 U 盘歌曲丢失。（我那尊贵的 <code>CoffeeOS</code> 车机，已经让我体验过 2 次了，真好）  </p><p>所以我真诚建议你，在电脑备份一份文件。尤其是现在固态硬盘白菜价的时候，别犹豫了！  </p><h2 id="教程开始"><a href="#教程开始" class="headerlink" title="教程开始"></a>教程开始</h2><p>本篇分享脚本基于<code>node.js</code>实现，歌词下载使用开源工具<code>ZonyLrcToolsX</code>。因此开始之前，请先下载安装<code>node.js</code>（过于简单，直接放个链接吧（记得添加到环境变量，不懂 Google 下）：<a href="https://www.runoob.com/nodejs/nodejs-install-setup.html">Node.js 安装配置</a>）  </p><p>ZonyLrcToolsX 下载地址：<a href="https://github.com/real-zony/ZonyLrcToolsX/releases">ZonyLrcToolsX&#x2F;releases</a>  </p><p>将 ZonyLrcToolsX 包解压到电脑本地某个目录，记下这个目录地址。在电脑一个你记得住的位置，创建一个 <code>car_music.txt</code> 文件，内容是下面这些：  </p><figure class="highlight js"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>).<span class="property">promises</span>; <span class="comment">// 使用 fs.promises 版本</span></span><br><span class="line"><span class="keyword">const</span> readline = <span class="built_in">require</span>(<span class="string">&#x27;readline&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> sourceDirectory = <span class="string">&#x27;E:/car music&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> targetDirectory = <span class="string">&#x27;F:/car music&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> addedList = [];</span><br><span class="line"><span class="keyword">const</span> deleteList = [];</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">printSeparator</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;---------------------------&#x27;</span>);</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">function</span> <span class="title function_">getFormattedTimestamp</span>(<span class="params">info</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> now = <span class="keyword">new</span> <span class="title class_">Date</span>();</span><br><span class="line">    <span class="keyword">const</span> hours = now.<span class="title function_">getHours</span>().<span class="title function_">toString</span>().<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> minutes = now.<span class="title function_">getMinutes</span>().<span class="title function_">toString</span>().<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> seconds = now.<span class="title function_">getSeconds</span>().<span class="title function_">toString</span>().<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">    <span class="keyword">if</span> (info) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">`[<span class="subst">$&#123;hours&#125;</span>:<span class="subst">$&#123;minutes&#125;</span>:<span class="subst">$&#123;seconds&#125;</span> INF]`</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">`[<span class="subst">$&#123;hours&#125;</span>:<span class="subst">$&#123;minutes&#125;</span>:<span class="subst">$&#123;seconds&#125;</span> WRN]`</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">copyFiles</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> file <span class="keyword">of</span> addedList) &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">await</span> fs.<span class="title function_">copyFile</span>(file, <span class="string">`<span class="subst">$&#123;targetDirectory&#125;</span>/<span class="subst">$&#123;path.basename(file)&#125;</span>`</span>);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 拷贝成功：<span class="subst">$&#123;file&#125;</span>`</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">0</span>)&#125;</span> 拷贝失败：<span class="subst">$&#123;file&#125;</span>`</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">deleteFiles</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> file <span class="keyword">of</span> deleteList) &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">await</span> fs.<span class="title function_">unlink</span>(file);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 删除成功：<span class="subst">$&#123;file&#125;</span>`</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">0</span>)&#125;</span> 删除失败：<span class="subst">$&#123;file&#125;</span>`</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">confirmCopy</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="title function_">printSeparator</span>();</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 扫描完成，待添加文件列表如下：`</span>);</span><br><span class="line">    addedList.<span class="title function_">forEach</span>(<span class="function">(<span class="params">file</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(file);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="title function_">printSeparator</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> rl1 = readline.<span class="title function_">createInterface</span>(&#123;</span><br><span class="line">        <span class="attr">input</span>: process.<span class="property">stdin</span>,</span><br><span class="line">        <span class="attr">output</span>: process.<span class="property">stdout</span>,</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span><br><span class="line">        rl1.<span class="title function_">question</span>(<span class="string">&#x27;确认帮您拷贝添加到 U 盘吗？ (no/yes): &#x27;</span>, <span class="title function_">async</span> (confirmAdd) =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span> (confirmAdd.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;n&#x27;</span> || confirmAdd.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;no&#x27;</span>) &#123;</span><br><span class="line">                <span class="title function_">printSeparator</span>();</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 您拒绝了添加文件。`</span>);</span><br><span class="line">                <span class="title function_">resolve</span>();</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (confirmAdd.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;y&#x27;</span> || confirmAdd.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;yes&#x27;</span>) &#123;</span><br><span class="line">                <span class="title function_">printSeparator</span>();</span><br><span class="line">                <span class="keyword">await</span> <span class="title function_">copyFiles</span>();</span><br><span class="line">                <span class="title function_">resolve</span>();</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="title function_">printSeparator</span>();</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">0</span>)&#125;</span> 您键入的指令不正确，已跳过本次操作。`</span>);</span><br><span class="line">                <span class="title function_">resolve</span>();</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">            rl1.<span class="title function_">close</span>();</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">confirmDelete</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 打印 deleteList 并请求确认</span></span><br><span class="line">    <span class="keyword">if</span> (deleteList.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="title function_">printSeparator</span>();</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 待删除文件列表如下：`</span>);</span><br><span class="line">        deleteList.<span class="title function_">forEach</span>(<span class="function">(<span class="params">file</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(file);</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> rl2 = readline.<span class="title function_">createInterface</span>(&#123;</span><br><span class="line">            <span class="attr">input</span>: process.<span class="property">stdin</span>,</span><br><span class="line">            <span class="attr">output</span>: process.<span class="property">stdout</span>,</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="title function_">printSeparator</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span><br><span class="line">            rl2.<span class="title function_">question</span>(<span class="string">&#x27;确认帮您删除 U 盘上述文件吗？ (no/yes): &#x27;</span>, <span class="title function_">async</span> (confirmDelete) =&gt; &#123;</span><br><span class="line">                <span class="keyword">if</span> (confirmDelete.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;n&#x27;</span> || confirmDelete.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;no&#x27;</span>) &#123;</span><br><span class="line">                    <span class="title function_">printSeparator</span>();</span><br><span class="line">                    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 您拒绝了删除文件。`</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (confirmDelete.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;y&#x27;</span> || confirmDelete.<span class="title function_">toLowerCase</span>() === <span class="string">&#x27;yes&#x27;</span>) &#123;</span><br><span class="line">                    <span class="title function_">printSeparator</span>();</span><br><span class="line">                    <span class="keyword">await</span> <span class="title function_">deleteFiles</span>();</span><br><span class="line">                    <span class="title function_">printSeparator</span>();</span><br><span class="line">                    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 删除操作已完成。`</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="title function_">printSeparator</span>();</span><br><span class="line">                    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">0</span>)&#125;</span> 您键入的指令不正确，已跳过本次操作。`</span>);</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">                rl2.<span class="title function_">close</span>();</span><br><span class="line">                <span class="title function_">resolve</span>();</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="title function_">printSeparator</span>();</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 没有待删除的文件。`</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">main</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> sourceFiles = <span class="keyword">await</span> fs.<span class="title function_">readdir</span>(sourceDirectory);</span><br><span class="line">        <span class="keyword">const</span> targetFiles = <span class="keyword">await</span> fs.<span class="title function_">readdir</span>(targetDirectory);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">const</span> fileName <span class="keyword">of</span> sourceFiles) &#123;</span><br><span class="line">            <span class="keyword">const</span> sourceFilePath = <span class="string">`<span class="subst">$&#123;sourceDirectory&#125;</span>/<span class="subst">$&#123;fileName&#125;</span>`</span>;</span><br><span class="line">            <span class="keyword">const</span> targetFilePath = <span class="string">`<span class="subst">$&#123;targetDirectory&#125;</span>/<span class="subst">$&#123;fileName&#125;</span>`</span>;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (!targetFiles.<span class="title function_">includes</span>(fileName)) &#123;</span><br><span class="line">                <span class="comment">// 文件不存在于 targetDirectory，将其添加到 addedList</span></span><br><span class="line">                addedList.<span class="title function_">push</span>(sourceFilePath);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">const</span> fileName <span class="keyword">of</span> targetFiles) &#123;</span><br><span class="line">            <span class="keyword">const</span> sourceFilePath = <span class="string">`<span class="subst">$&#123;sourceDirectory&#125;</span>/<span class="subst">$&#123;fileName&#125;</span>`</span>;</span><br><span class="line">            <span class="keyword">const</span> targetFilePath = <span class="string">`<span class="subst">$&#123;targetDirectory&#125;</span>/<span class="subst">$&#123;fileName&#125;</span>`</span>;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (!sourceFiles.<span class="title function_">includes</span>(fileName)) &#123;</span><br><span class="line">                <span class="comment">// 文件不存在于 sourceDirectory，将其添加到 deleteList</span></span><br><span class="line">                deleteList.<span class="title function_">push</span>(targetFilePath);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">await</span> <span class="title function_">confirmDelete</span>();</span><br><span class="line">        <span class="comment">// 检查是否有文件需要拷贝</span></span><br><span class="line">        <span class="keyword">if</span> (addedList.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// 开始确认拷贝</span></span><br><span class="line">            <span class="keyword">await</span> <span class="title function_">confirmCopy</span>();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="title function_">printSeparator</span>();</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getFormattedTimestamp(<span class="number">1</span>)&#125;</span> 没有待添加的文件。`</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">error</span>(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="comment">// 启动主程序</span></span><br><span class="line"><span class="title function_">main</span>();</span><br></pre></td></tr></table></figure><p>将其中开头的这两行路径，修改为你自己的。第一个“E:&#x2F;car music”为“电脑本地备份的音乐目录”，第二个“F:&#x2F;car music”为“U盘上的音乐目录，注意盘符”：  </p><figure class="highlight js"><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 class="keyword">const</span> sourceDirectory = <span class="string">&#x27;E:/car music&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> targetDirectory = <span class="string">&#x27;F:/car music&#x27;</span>;</span><br></pre></td></tr></table></figure><p>将 <code>car_music.txt</code> 文件，重命名为 <code>car_music.js</code> 文件。再创建一个 <code>music_processor.txt</code> 文件，实现鼠标双击执行的功能，可以放在任何位置，比如桌面方便找也可以。内容为：  </p><figure class="highlight sh"><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">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> d:/home/tools/zonyLrcTools</span><br><span class="line">./ZonyLrcTools.Cli.exe download -d <span class="string">&quot;e:\car music&quot;</span> -l -n 2</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> e:/</span><br><span class="line">node ./car_music.js</span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;---------------------------&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;脚本执行完成，按 Enter 键退出&quot;</span></span><br><span class="line"><span class="built_in">read</span></span><br></pre></td></tr></table></figure><p>将其中的 <code>d:/home/tools/zonyLrcTools</code> 修改为你刚才下载的 zonyLrcToolsX 解压缩的目录。同样的，将其中的<code>e:\car music</code> 改为你电脑本地备份的歌曲目录。保存后，将 <code>music_processor.txt</code> 文件重命名为 <code>music_processor.sh</code> 文件。  </p><figure class="highlight sh"><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 class="built_in">cd</span> e:/</span><br><span class="line">node ./car_music.js</span><br></pre></td></tr></table></figure><p>这两部分是进入你刚才保存 <code>car_music.js</code> 的目录，并执行它。因此地址请按你保存的目录修改，我这里放在了 E 盘根目录。  </p><h2 id="歌曲解密"><a href="#歌曲解密" class="headerlink" title="歌曲解密"></a>歌曲解密</h2><p>在网易云、QQ 音乐下载的歌曲，有些是加密的（.ncm &#x2F; .mflac 之类的格式），可以来这里解密（原作者牛皮）：  </p><div class="tag link"><a class="link-card" title="音乐解密" href="https://unlock-music.guole.fun/"><div class="left"><img class="no-lightbox" src="https://unlock-music.guole.fun/img/icons/apple-touch-icon-152x152.png"/></div><div class="right"><p class="text">音乐解密</p><p class="url">https://unlock-music.guole.fun/</p></div></a></div><h2 id="大功告成"><a href="#大功告成" class="headerlink" title="大功告成"></a>大功告成</h2><p>现在插上 U 盘，鼠标双击 <code>music_processor.sh</code> 文件，试试看吧。没插入 U 盘执行会报错，因为找不到对应地址。也可以本地弄两个文件夹，自己测试。<br><img src="/posts/10915/11.png" alt="车载 U 盘音乐自动整理工具"><br>推荐下<code>寸铁 《近人可读》</code>专辑，最近好上头。最后，预祝大家假期愉快，下次见~~</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;认识我的朋友都知道，我是个热爱音乐的博主，值此国庆小长假来临之际，自当整理一下我的&lt;code&gt;Car Music&lt;/code&gt;，确保旅途中动次打次不停歇。  &lt;/p&gt;
&lt;p&gt;以前都是手动整理，从网易云、QQ 音乐下载歌曲，手动解密，然后拷贝到 U 盘。于是，我面临以下重复工</summary>
      
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>海南岛自驾游记「下」| 大美海南风光 / 美食篇</title>
    <link href="https://blog.guole.fun/posts/17314/"/>
    <id>https://blog.guole.fun/posts/17314/</id>
    <published>2023-07-24T16:02:54.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="风光：满足我对大海的一切想象"><a href="#风光：满足我对大海的一切想象" class="headerlink" title="风光：满足我对大海的一切想象"></a>风光：满足我对大海的一切想象</h2><p>接上篇。  </p><p>海口骑楼老街令人目不暇接，沿着外围绿道向前走，绿道左侧是小店，是酒馆，时有乐器声绕耳。入眼四处皆是行人，三三两两微笑着，步子轻缓，每个人都从容极了。绿道右侧则是平静宽广的湖面？又或者海面？在这个地方，我竟突然萌发了想要定居于此的念头。  </p><p>万宁神州半岛，石梅湾，日月湾，是绝佳的海滩圣地。日月湾教堂，在我眼里是位独身者，矗立在海边有种独特的浪漫。  </p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-26.jpg","alt":"琼州海峡轮渡 - 远眺货轮","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-25.jpg","alt":"琼州海峡轮渡 - 海南岛","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-24.jpg","alt":"琼州海峡轮渡下海面","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-04.jpg","alt":"万宁日月湾网红教堂 - 远景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-03.jpg","alt":"万宁日月湾网红教堂 - 中景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-02.jpg","alt":"万宁日月湾网红教堂","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-01.jpg","alt":"万宁日月湾网红教堂 - 近景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-28.jpg","alt":"万宁日月湾网红教堂 - 侧景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-08.jpg","alt":"去往万宁石梅湾的路上","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-07.jpg","alt":"万宁神州半岛海滩 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-06.jpg","alt":"万宁石梅湾海滩 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-05.jpg","alt":"万宁石梅湾海滩 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-10.jpg","alt":"万宁神州半岛海滩 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-19.jpg","alt":"海口骑楼老街","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-21.jpg","alt":"海口骑楼老街 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-20.jpg","alt":"海口骑楼老街 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-16.jpg","alt":"海口骑楼老街 - 外景 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-14.jpg","alt":"海口骑楼老街 - 外景 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-22.jpg","alt":"海口骑楼老街 - 童年杂货店","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-18.jpg","alt":"海口骑楼老街 - 从前慢小邮局","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-15.jpg","alt":"海口骑楼老街 - 晚霞","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-13.jpg","alt":"海口骑楼老街 - 某公园下仰视","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-12.jpg","alt":"海口骑楼老街 - 海甸河夜景","title":""}]</div>  </div><br><h2 id="美食：给我狠狠一记耳光"><a href="#美食：给我狠狠一记耳光" class="headerlink" title="美食：给我狠狠一记耳光"></a>美食：给我狠狠一记耳光</h2><p>好像 20 岁起，我就几乎不吃甜食了，仿佛丧失了作为人类面对“甜点”的所有原始欲望。当然本身也想借此坚持下来，控制体脂上涨。但这趟海南自由行，椰子糕，清补凉，榴莲炒冰，椰子冻……给了我狠狠一记耳光！</p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-01.jpg","alt":"⭐️⭐️⭐️ 顺德鱼生","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-12.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 顺德桂虾","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-13.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 顺德烤乳鸽","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-10.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 湛江烤生蚝","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-11.jpg","alt":"⭐️⭐️⭐️⭐️ 湛江海鲜粥","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-03.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁 - 农家椰子鸡 - 椰子糕","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-02.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁 - 农家椰子鸡 - 椰子鸡","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-09.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁兴隆镇 - 南洋风味 - 清补凉","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-14.jpg","alt":"⭐️⭐️⭐️ 万宁兴隆镇 - 南洋风味 - 秘制凤爪","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-15.jpg","alt":"⭐️⭐️ 万宁兴隆镇 - 南洋风味 - 网红鱼丸","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-16.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁兴隆镇 - 南洋风味 - 榴莲炒冰","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-17.jpg","alt":"⭐️⭐️⭐️ 万宁兴隆镇 - 后安粉","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-05.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 海口骑楼老街 - 椰子冻","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-06.jpg","alt":"⭐️⭐️海口骑楼老街 - 生腌","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-08.jpg","alt":"⭐️⭐️⭐️ 海口骑楼老街 - 网红虾饼","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-07.jpg","alt":"⭐️⭐️⭐️⭐️海口骑楼老街 - 网红炸排骨","title":""}]</div>  </div><h2 id="关联阅读"><a href="#关联阅读" class="headerlink" title="关联阅读"></a>关联阅读</h2><div class="tag link"><a class="link-card" title="「海南岛自驾游记「上」| 别挤去三亚！海口和万宁满足你一切期望」" href="/posts/14851/"><div class="left"><img class="no-lightbox" src="/img/posts/14851-1.jpg"/></div><div class="right"><p class="text">「海南岛自驾游记「上」| 别挤去三亚！海口和万宁满足你一切期望」</p><p class="url">/posts/14851/</p></div></a></div><div class="tag link"><a class="link-card" title="「石门国家森林公园游记」" href="/posts/23424/"><div class="left"><img class="no-lightbox" src="/img/posts/23424-2.jpg"/></div><div class="right"><p class="text">「石门国家森林公园游记」</p><p class="url">/posts/23424/</p></div></a></div>]]></content>
    
    
    <summary type="html">听我说朋友，趁年轻一定要多领略祖国的大好河山！&lt;br&gt;迟来的分享：海南岛一游，风光美食集合！</summary>
    
    
    
    <category term="我的游记" scheme="https://blog.guole.fun/categories/%E6%88%91%E7%9A%84%E6%B8%B8%E8%AE%B0/"/>
    
    
    <category term="找点儿乐子" scheme="https://blog.guole.fun/tags/%E6%89%BE%E7%82%B9%E5%84%BF%E4%B9%90%E5%AD%90/"/>
    
    <category term="镜头下的风光" scheme="https://blog.guole.fun/tags/%E9%95%9C%E5%A4%B4%E4%B8%8B%E7%9A%84%E9%A3%8E%E5%85%89/"/>
    
  </entry>
  
  <entry>
    <title>海南岛自驾游记「上」| 别挤去三亚！海口和万宁满足你一切期望</title>
    <link href="https://blog.guole.fun/posts/14851/"/>
    <id>https://blog.guole.fun/posts/14851/</id>
    <published>2023-07-24T16:02:50.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>2023 五一假期，我原定是深圳出发，途经顺德、湛江，一路向西直达北海，去瞧瞧这个光听名字就充满诗意的城市。可到了湛江，仿佛海南岛就在脚下，不上岛终有一日悔之晚矣！于是顺势南下，说走就走，便有了此篇海南岛游记。  </p><p>emm，有些汗颜，时隔 2 个月才记此篇……</p><h2 id="已打卡：顺德「美未居」"><a href="#已打卡：顺德「美未居」" class="headerlink" title="已打卡：顺德「美未居」"></a>已打卡：顺德「美未居」</h2><p>从深圳出发，上午 11:00 许到顺德，尝了下同事推荐的「顺德菜」。由于孤身一人，所以只能对菜单上多个眼馋的菜品致以歉意，以待择日再尝。去的是这家「美未居」，桂虾与乳鸽很满意，鱼生倒有点吃不惯。  </p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-01.jpg","alt":"⭐️⭐️⭐️ 顺德鱼生","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-12.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 顺德桂虾","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-13.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 顺德烤乳鸽","title":""}]</div>  </div><br><h2 id="已打卡：湛江市"><a href="#已打卡：湛江市" class="headerlink" title="已打卡：湛江市"></a>已打卡：湛江市</h2><p>草草用过午餐，继续启程湛江。行至阳江段，突遇大暴雨，前后车辆的灯光也模糊起来，有些车主打起了双闪，有些开着远光，还有些竟然示廓灯也不开？？似乎正确做法是<strong>打开前后雾灯</strong>。  </p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/wudeng.webp","alt":"雾灯开启方法","title":""}]</div>  </div><p>下午 18:00 左右终于到了湛江，简单休整一晚，宵夜简单品尝了下正宗的「湛江烤生蚝」，不赖。  </p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-10.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 湛江烤生蚝","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-11.jpg","alt":"⭐️⭐️⭐️⭐️ 湛江海鲜粥","title":""}]</div>  </div><p>第二日一早加满油，冲向海南岛！</p><blockquote><p>海南省的高速公路不设收费站，统一征收燃油附加费，附加费主要体现在油价中，故岛上油价略高（#92 近 9 元 &#x2F; L）。因此上岛前<code>加满油</code>呀~~</p></blockquote><h3 id="轮渡船票"><a href="#轮渡船票" class="headerlink" title="轮渡船票"></a>轮渡船票</h3><p>自驾前往海南岛需要购买船票，通过轮渡跨越琼州海峡。微信搜索<code>琼州海峡轮渡管家</code>，即可随时购票。  </p><blockquote><ul><li>客船票价格为 41.5 元 &#x2F; 人  </li><li>小车轮渡票价为 374 元 &#x2F; 车  </li><li>合计：415.5 元 &#x2F; 人 * 车 * 单程</li></ul></blockquote><p>从湛江市区驱车约 150 公里，需特别注意<code>开船时间</code>。到达港口若赶不上购买的班次，工作人员会指导排队搭乘下一班次轮渡。从海南岛离岛时，新能源车辆必须最后上船，但从徐闻港上船时似乎无此规定。  </p><p>去程票据没图了，以下是我返程的船票。  </p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-17.jpg","alt":"轮渡船票 - 单程","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-27.jpg","alt":"轮渡内部","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-23.jpg","alt":"轮渡 - 准备下船","title":""}]</div>  </div><br><h2 id="已打卡：海口市"><a href="#已打卡：海口市" class="headerlink" title="已打卡：海口市"></a>已打卡：海口市</h2><p>经过 2h 航行，终于到了海南岛！  </p><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-26.jpg","alt":"琼州海峡轮渡 - 远眺货轮","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-25.jpg","alt":"琼州海峡轮渡 - 海南岛","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-24.jpg","alt":"琼州海峡轮渡下海面","title":""}]</div>  </div><p>第一站：海口！  </p><p>推荐下我入住的这家店「蓝庭城市度假酒店（海口日月广场店）」，干净卫生还不贵。社畜时间有限，在海口就主要逛了骑楼老街那一圈。总结以下几点：  </p><blockquote><ol><li>行：骑楼老街贼堵，停车多有不便  </li><li>行：骑楼老街外围绿道，很适合傍晚散步。一直往下走，有很多酒馆，有驻唱  </li><li>吃：骑楼老街“网红炸排骨”，小心品尝，容易口腔溃疡不可贪吃</li></ol></blockquote><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-19.jpg","alt":"海口骑楼老街","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-21.jpg","alt":"海口骑楼老街 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-20.jpg","alt":"海口骑楼老街 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-05.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 海口骑楼老街 - 椰子冻","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-06.jpg","alt":"⭐️⭐️海口骑楼老街 - 生腌","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-08.jpg","alt":"⭐️⭐️⭐️ 海口骑楼老街 - 网红虾饼","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-07.jpg","alt":"⭐️⭐️⭐️⭐️海口骑楼老街 - 网红炸排骨","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-16.jpg","alt":"海口骑楼老街 - 外景 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-14.jpg","alt":"海口骑楼老街 - 外景 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-22.jpg","alt":"海口骑楼老街 - 童年杂货店","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-18.jpg","alt":"海口骑楼老街 - 从前慢小邮局","title":""}]</div>  </div><br><h2 id="已打卡：万宁市"><a href="#已打卡：万宁市" class="headerlink" title="已打卡：万宁市"></a>已打卡：万宁市</h2><p>接着便是海口 ——&gt; 万宁的行程。  </p><blockquote><p>吃：<strong>农家椰子鸡（神州半岛店）</strong> ⭐️⭐️⭐️⭐️⭐️<br>吃：<strong>南洋风味（兴隆镇）</strong> ⭐️⭐️⭐️⭐️⭐️<br>玩：<strong>神州半岛</strong>，力荐！无门票，灯塔可租电动车前往<br>玩：<strong>石梅湾</strong>，力荐！无门票，树林中有吊床、桌子、椅子，消费 38 元 &#x2F; 位可使用<br>玩：<strong>日月湾</strong>，无门票，堵车严重，商铺较贵。但海边教堂就在此处，值得一来<br>玩：热带植物园，蚊虫叮咬警告，门票 40 元 &#x2F; 人，不推荐<br>玩：仙女潭，似乎没啥可玩的？还是我没找到？不推荐</p></blockquote><p>若时间宽裕，海口和万宁都是值得慢慢品味的城市。期待再会！  </p><h3 id="日月湾海边教堂"><a href="#日月湾海边教堂" class="headerlink" title="日月湾海边教堂"></a>日月湾海边教堂</h3><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-04.jpg","alt":"万宁日月湾网红教堂 - 远景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-03.jpg","alt":"万宁日月湾网红教堂 - 中景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-02.jpg","alt":"万宁日月湾网红教堂","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-01.jpg","alt":"万宁日月湾网红教堂 - 近景","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-28.jpg","alt":"万宁日月湾网红教堂 - 侧景","title":""}]</div>  </div><h3 id="石梅湾与神州半岛海滩"><a href="#石梅湾与神州半岛海滩" class="headerlink" title="石梅湾与神州半岛海滩"></a>石梅湾与神州半岛海滩</h3><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-10.jpg","alt":"万宁神州半岛海滩 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-07.jpg","alt":"万宁神州半岛海滩 - 2","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-06.jpg","alt":"万宁石梅湾海滩 - 1","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-fengguang-05.jpg","alt":"万宁石梅湾海滩 - 2","title":""}]</div>  </div><h3 id="食在万宁"><a href="#食在万宁" class="headerlink" title="食在万宁"></a>食在万宁</h3><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-03.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁 - 农家椰子鸡 - 椰子糕","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-02.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁 - 农家椰子鸡 - 椰子鸡","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-09.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁兴隆镇 - 南洋风味 - 清补凉","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-16.jpg","alt":"⭐️⭐️⭐️⭐️⭐️ 万宁兴隆镇 - 南洋风味 - 榴莲炒冰","title":""},{"url":"https://cdn.guole.fun/img/posts/hainandao-meishi-17.jpg","alt":"⭐️⭐️⭐️ 万宁兴隆镇 - 后安粉","title":""}]</div>  </div><br><h2 id="规划未实现"><a href="#规划未实现" class="headerlink" title="规划未实现"></a>规划未实现</h2><p>除了上述景点，还想去看看南极村，海口也有几处未去，留记下次实现！  </p><div class="note default flat"><div class='checkbox'><input type="checkbox" />            <p>湛江：南极村，祖国大陆的最南端，与海南岛隔海相望</p>            </div><div class='checkbox'><input type="checkbox" />            <p>阳江：海陵岛，大角湾、马尾岛、十里银滩等 10 个小景点</p>            </div><div class='checkbox'><input type="checkbox" />            <p>海口：南三岛</p>            </div><div class='checkbox'><input type="checkbox" />            <p>海口：角头沙滩</p>            </div><div class='checkbox'><input type="checkbox" />            <p>海口：金沙湾</p>            </div><div class='checkbox'><input type="checkbox" />            <p>万宁：山倾湾（野海滩）</p>            </div></div><h2 id="关联阅读"><a href="#关联阅读" class="headerlink" title="关联阅读"></a>关联阅读</h2><div class="tag link"><a class="link-card" title="「海南岛自驾游记「下」| 大美海南风光 / 美食篇」" href="/posts/17314/"><div class="left"><img class="no-lightbox" src="/img/posts/17314-1.jpg"/></div><div class="right"><p class="text">「海南岛自驾游记「下」| 大美海南风光 / 美食篇」</p><p class="url">/posts/17314/</p></div></a></div><div class="tag link"><a class="link-card" title="「石门国家森林公园游记」" href="/posts/23424/"><div class="left"><img class="no-lightbox" src="/img/posts/23424-2.jpg"/></div><div class="right"><p class="text">「石门国家森林公园游记」</p><p class="url">/posts/23424/</p></div></a></div>]]></content>
    
    
    <summary type="html">听我说朋友，趁年轻一定要多领略祖国的大好河山！&lt;br&gt;迟来的游记：2023 五一假期海南岛自驾分享。</summary>
    
    
    
    <category term="我的游记" scheme="https://blog.guole.fun/categories/%E6%88%91%E7%9A%84%E6%B8%B8%E8%AE%B0/"/>
    
    
    <category term="找点儿乐子" scheme="https://blog.guole.fun/tags/%E6%89%BE%E7%82%B9%E5%84%BF%E4%B9%90%E5%AD%90/"/>
    
    <category term="镜头下的风光" scheme="https://blog.guole.fun/tags/%E9%95%9C%E5%A4%B4%E4%B8%8B%E7%9A%84%E9%A3%8E%E5%85%89/"/>
    
  </entry>
  
  <entry>
    <title>石门国家森林公园游记 | 乌漆嘛黑中被保安赶下山 😮‍💨</title>
    <link href="https://blog.guole.fun/posts/23424/"/>
    <id>https://blog.guole.fun/posts/23424/</id>
    <published>2023-07-24T09:50:34.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言：山美，景美，心旷神怡"><a href="#前言：山美，景美，心旷神怡" class="headerlink" title="前言：山美，景美，心旷神怡"></a>前言：山美，景美，心旷神怡</h2><p>在深圳工作，从来不缺少看海的机会。深圳湾公园适合独自漫步，海滨栈道适合骑行，东西涌 &#x2F; 鹿嘴山庄 &#x2F; 桔钓沙…… 更远一点的南澳岛，则更适合为生活减负。  </p><p>上周就想，不然也去山里逛逛吧。周六便说走就走，驱车 160km 探访<a href="https://www.shimenpark.cn/">「石门国家森林公园」</a>。  </p><p>吸引我的点在于：这可能是不多的可全程自驾、可随处停车眺望、且有山有水的好去处。交通很便利，下高速出了收费站不过十数公里，沿县道盘旋就到景区门口。已经逛完了，概括就是“山美，景美，心旷神怡”，故留此记。  </p><ul><li>景区费用：停车费 10 元  </li><li>门票：36 元 &#x2F; 人</li></ul><link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div class="map-box" style="margin: 0.8rem 0 1.6rem 0;"><div id="gaodeMap-113.788833-23.627346" 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:'高德地图'});var imgm=L.tileLayer.chinaProvider('GaoDe.Satellite.Map',{maxZoom:20,minZoom:1,attribution:'高德地图'});var imga=L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion',{maxZoom:20,minZoom:1,attribution:'高德地图'});var normal=L.layerGroup([normalm]),image=L.layerGroup([imgm,imga]);var baseLayers={"高德地图":normal,"高德卫星地图":imgm,"高德卫星标注":image};var mymap=L.map('gaodeMap-113.788833-23.627346',{center:[23.627346,113.788833],zoom:12,layers:[normal],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['23.627346','113.788833']).addTo(mymap);marker.bindPopup("石门国家森林公园").openPopup();</script><h2 id="独自访山好去处"><a href="#独自访山好去处" class="headerlink" title="独自访山好去处"></a>独自访山好去处</h2><blockquote><p>「广州石门国家森林公园」平均海拔 800 多米，以森林观光、森林养生为主题，拥有天池花海景点和天然森林&#x2F;国际森林浴场等众多景点，是不可多得世外桃源和避暑胜地。</p></blockquote><p>这是景区官网介绍，“世外桃源”可能有点夸张，但“避暑胜地”不假。2023.7.22 日深圳 <code>27°C~31°C</code>，公园里我看到天气预报是 <code>20°C~28°C</code>，体感也很凉爽，至少不会闷热。  </p><p>景区分为<code>石灶景区</code>与<code>石门景区</code>，我是先逛石门，再去石灶的，反正交通很便利。<br><img src="https://cdn.guole.fun/img/posts/shimen9.jpg"></p><h3 id="石门景区"><a href="#石门景区" class="headerlink" title="石门景区"></a>石门景区</h3><p>这里走下去有个山谷，有水车，有小溪，有很多遛娃家长带着孩子玩水。有个“石门”景点，我从山里眺望了两眼，没到跟前。路边全程有很多果园，大多是龙眼与荔枝，很诱人。<br><video src="https://cdn.guole.fun/media/344.mp4" controls></video></p><h3 id="石灶景区"><a href="#石灶景区" class="headerlink" title="石灶景区"></a>石灶景区</h3><p>主要景点都在石灶景区了。首先沿着盘山公路徐徐爬升，路边有多个红叶观赏点，可惜季节不对，枫树正绿。不过停在路边，人在林中散步，头顶着枫叶，听着蝉鸣，感受也不错。  </p><p>继续往上，有个“天池”，简单用根甜筒致敬了下，绕湖一圈。在湖对面，可以远眺景区的一个瀑布，不过好像是人工的。人多的话，山林中徒步几程应该也不错。<br><img src="https://cdn.guole.fun/img/posts/shimen13.jpg"></p><h2 id="山的尽头是石门花海"><a href="#山的尽头是石门花海" class="headerlink" title="山的尽头是石门花海"></a>山的尽头是石门花海</h2><p>看完“天池”继续爬升，会来到本次行程最佳观景点<code>石门花海</code>。途中经过了一片竹林，耳边仿佛立即响起了那句“莫听穿林打叶声 何妨吟啸且徐行”，这该死的刻进骨子里的 DNA。等下，下句是啥来着？  </p><blockquote><p>《定风波·莫听穿林打叶声》<br>苏轼</p><p>莫听穿林打叶声，何妨吟啸且徐行。<br>竹杖芒鞋轻胜马，谁怕？一蓑烟雨任平生。<br>料峭春风吹酒醒，微冷，山头斜照却相迎。<br>回首向来萧瑟处，归去，也无风雨也无晴。</p></blockquote><p><video src="https://cdn.guole.fun/media/38854.mp4" controls></video></p><h3 id="花海树下一张琴"><a href="#花海树下一张琴" class="headerlink" title="花海树下一张琴"></a>花海树下一张琴</h3><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/shimen8.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen10.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen7.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen6.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen4.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen3.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen5.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen2.jpg","alt":"","title":""},{"url":"https://cdn.guole.fun/img/posts/shimen11.jpg","alt":"","title":""}]</div>  </div><h3 id="偶遇一只孔雀？野生的？"><a href="#偶遇一只孔雀？野生的？" class="headerlink" title="偶遇一只孔雀？野生的？"></a>偶遇一只孔雀？野生的？</h3><p><video src="https://cdn.guole.fun/media/38868.mp4" controls></video></p><h2 id="原定“花海”露营，最后睡到了服务区"><a href="#原定“花海”露营，最后睡到了服务区" class="headerlink" title="原定“花海”露营，最后睡到了服务区"></a>原定“花海”露营，最后睡到了服务区</h2><p>等到傍晚时分，其他人陆陆续续下山了，我就开始捣腾我新买的气垫床。刚铺好躺了躺，来俩保安让我下山……  </p><p><img src="https://cdn.guole.fun/img/posts/shimen1.jpg">  </p><p>原来，景区开放时间：09:00~19:00，不能露营……于是，谁懂啊，天将黑不黑那个样子，路上一辆车都没有了，我就孤身一人驾车下山。越走越黑，越走树林越密，越下弯道越多……  </p><p><video src="https://cdn.guole.fun/media/sd1690025581_2.mp4" controls></video></p><p>但是，我床都铺好了，今晚让我回家是不可能的，住酒店也不可能。<strong>90后，谁还没点反骨了</strong>。  </p><p>最后开上高速，在服务区充上电，睡了一晚。总结：床垫很软，早晨阳光照进来很放松。  </p><p><img src="/img/posts/23424-1.jpg">  </p><p>最后，提醒：吃饭不方便，最好自备干粮。景区门口的农家乐，贵还不好吃。石门花海有个炒粉，也不好吃……  </p><h2 id="关联阅读"><a href="#关联阅读" class="headerlink" title="关联阅读"></a>关联阅读</h2><div class="tag link"><a class="link-card" title="「海南岛自驾游记「上」| 别挤去三亚！海口和万宁满足你一切期望」" href="/posts/14851/"><div class="left"><img class="no-lightbox" src="/img/posts/14851-1.jpg"/></div><div class="right"><p class="text">「海南岛自驾游记「上」| 别挤去三亚！海口和万宁满足你一切期望」</p><p class="url">/posts/14851/</p></div></a></div><div class="tag link"><a class="link-card" title="「海南岛自驾游记「下」| 大美海南风光 / 美食篇」" href="/posts/17314/"><div class="left"><img class="no-lightbox" src="/img/posts/17314-1.jpg"/></div><div class="right"><p class="text">「海南岛自驾游记「下」| 大美海南风光 / 美食篇」</p><p class="url">/posts/17314/</p></div></a></div>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;前言：山美，景美，心旷神怡&quot;&gt;&lt;a href=&quot;#前言：山美，景美，心旷神怡&quot; class=&quot;headerlink&quot; title=&quot;前言：山美，景美，心旷神怡&quot;&gt;&lt;/a&gt;前言：山美，景美，心旷神怡&lt;/h2&gt;&lt;p&gt;在深圳工作，从来不缺少看海的机会。深圳湾公园适合独自</summary>
      
    
    
    
    <category term="我的游记" scheme="https://blog.guole.fun/categories/%E6%88%91%E7%9A%84%E6%B8%B8%E8%AE%B0/"/>
    
    
    <category term="找点儿乐子" scheme="https://blog.guole.fun/tags/%E6%89%BE%E7%82%B9%E5%84%BF%E4%B9%90%E5%AD%90/"/>
    
    <category term="镜头下的风光" scheme="https://blog.guole.fun/tags/%E9%95%9C%E5%A4%B4%E4%B8%8B%E7%9A%84%E9%A3%8E%E5%85%89/"/>
    
  </entry>
  
  <entry>
    <title>哔哔闪念[2.0] | 新增微信发位置、发视频、发链接功能</title>
    <link href="https://blog.guole.fun/posts/17745/"/>
    <id>https://blog.guole.fun/posts/17745/</id>
    <published>2023-06-24T17:26:35.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="2025-01-03-更新"><a href="#2025-01-03-更新" class="headerlink" title="2025.01.03 更新"></a>2025.01.03 更新</h1><ul><li><strong>增强：</strong> 完成云函数项目重构，代码逻辑更清晰、高效。由 <a href="https://www.cursor.com/">Cursor</a> 提供技术支持</li></ul><h1 id="9-27-更新"><a href="#9-27-更新" class="headerlink" title="9.27 更新"></a>9.27 更新</h1><p>优化 bbtalk.js 方法，解决 pjax 兼容问题</p><h1 id="6-28-更新：Safari-无法播放-mp4-问题已破案"><a href="#6-28-更新：Safari-无法播放-mp4-问题已破案" class="headerlink" title="6.28 更新：Safari 无法播放 mp4 问题已破案"></a>6.28 更新：Safari 无法播放 mp4 问题已破案</h1><p>下文提到哔哔闪念发送视频后，存储在我的<code>cdn.guole.fun</code>上，结果发现 Safari 无法播放。一顿操作猛如虎，各种排查最终确认问题如下，且已根本解决。  </p><p><strong>原因：</strong>  </p><p>罪魁祸首：<code>workbox</code> ，我早前通过正则给 <code>cdn.guole.fun</code> 域名加了 workbox 缓存，结果发现如果不特殊配置，workbox 缓存的视频无法正常响应 Safari 的 range 请求。甚至 Chrome 也偶现无法播放，不光 Safari。我原来是这样用的，简单粗暴：  </p><figure class="highlight js"><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">workbox.<span class="property">routing</span>.<span class="title function_">registerRoute</span>(</span><br><span class="line">    <span class="regexp">/^https:\/\/cdn\.guole\.fun/</span>,</span><br><span class="line">    <span class="keyword">new</span> workbox.<span class="property">strategies</span>.<span class="title class_">CacheFirst</span>(&#123;</span><br><span class="line">        <span class="attr">cacheName</span>: <span class="string">&quot;cdn-static-libs&quot;</span>,</span><br><span class="line">        <span class="attr">plugins</span>: [</span><br><span class="line">            <span class="keyword">new</span> workbox.<span class="property">expiration</span>.<span class="title class_">ExpirationPlugin</span>(&#123;</span><br><span class="line">                <span class="attr">maxEntries</span>: <span class="number">1000</span>,</span><br><span class="line">                <span class="attr">maxAgeSeconds</span>: <span class="number">60</span> * <span class="number">60</span> * <span class="number">24</span> * <span class="number">30</span> <span class="comment">//30day</span></span><br><span class="line">            &#125;),</span><br><span class="line">            <span class="keyword">new</span> workbox.<span class="property">cacheableResponse</span>.<span class="title class_">CacheableResponsePlugin</span>(&#123;</span><br><span class="line">                <span class="attr">statuses</span>: [<span class="number">0</span>, <span class="number">200</span>]</span><br><span class="line">            &#125;)</span><br><span class="line">        ]</span><br><span class="line">    &#125;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p><strong>解决方案：</strong>  </p><p>只需改为如下即可。压根不用 workbox 缓存 JSON 、mp4 资源了（workbox缓存音频后，也会影响其正常响应）。Chrome 官方给了说明，该日再研究折腾：<a href="https://developer.chrome.com/docs/workbox/serving-cached-audio-and-video/">提供缓存的音频和视频</a>：</p><figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line">workbox.<span class="property">routing</span>.<span class="title function_">registerRoute</span>(</span><br><span class="line">    <span class="function">(<span class="params">&#123;url&#125;</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> url.<span class="property">href</span>.<span class="title function_">match</span>(<span class="regexp">/^https:\/\/cdn\.guole\.fun/</span>) &amp;&amp; !url.<span class="property">pathname</span>.<span class="title function_">includes</span>(<span class="string">&#x27;/json/bb-json/&#x27;</span>) &amp;&amp; !url.<span class="property">pathname</span>.<span class="title function_">includes</span>(<span class="string">&#x27;/media/bb-media/&#x27;</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">new</span> workbox.<span class="property">strategies</span>.<span class="title class_">CacheFirst</span>(&#123;</span><br><span class="line">        <span class="attr">cacheName</span>: <span class="string">&quot;cdn-static-libs&quot;</span>,</span><br><span class="line">        <span class="attr">plugins</span>: [</span><br><span class="line">            <span class="keyword">new</span> workbox.<span class="property">expiration</span>.<span class="title class_">ExpirationPlugin</span>(&#123;</span><br><span class="line">                <span class="attr">maxEntries</span>: <span class="number">1000</span>,</span><br><span class="line">                <span class="attr">maxAgeSeconds</span>: <span class="number">60</span> * <span class="number">60</span> * <span class="number">24</span> * <span class="number">30</span> <span class="comment">//30day</span></span><br><span class="line">            &#125;),</span><br><span class="line">            <span class="keyword">new</span> workbox.<span class="property">cacheableResponse</span>.<span class="title class_">CacheableResponsePlugin</span>(&#123;</span><br><span class="line">                <span class="attr">statuses</span>: [<span class="number">0</span>, <span class="number">200</span>]</span><br><span class="line">            &#125;)</span><br><span class="line">        ]</span><br><span class="line">    &#125;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h1 id="6-26-再更新：新增说说转储-JSON-功能"><a href="#6-26-再更新：新增说说转储-JSON-功能" class="headerlink" title="6.26 再更新：新增说说转储 JSON 功能"></a>6.26 再更新：新增说说转储 JSON 功能</h1><p>如题，现在云函数可以在你新增 &#x2F; 删除 &#x2F; 修改 &#x2F; 插入 &#x2F; 追加说说内容后，自动拉取变动数据生成 JSON 文件，每个 JSON 文件的条数 &#x3D; 环境变量设置的<code>PageSize</code>值。也就是说，前端读 JSON 即可，不用直接请求 LeanCloud 了，提升哔哔闪念的加载速度！（JSON 自动上传腾讯云 COS ，配合 CDN 加持，老上头了）  </p><p>新的资源 URL 是下面这样，<code>json/bb-json</code> 这部分是你自己在环境变量中设置的上传路径 <code>Tcb_JsonPath</code> 值：  </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://cdn.guole.fun/json/bb-json/bbtalk_page$&#123;page&#125;.json</span><br></pre></td></tr></table></figure><p>生成的 JSON 暂时明明格式为：”bbtalk_page&#x3D;” + 页数 + “.json” 。前端读取时，只用递增这个页面即可。首页轮播哔哔，固定读取 <code>bbtalk_page1.json</code> 就完事儿了！配合上述功能，哔哔闪念独立页面的前端 JS 方法，调整 <code>fetch</code> 请求地址为如下类型即可（v1.0.1 以上版本）：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">fetch</span>(<span class="string">`https://cdn.guole.fun/json/bb-json/bbtalk_page<span class="subst">$&#123;page&#125;</span>.json`</span>)</span><br></pre></td></tr></table></figure><p>首页轮播哔哔，其中的 <code>jsonUrl</code> 变量值调整为如下这种写死即可：  </p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jsonUrl = <span class="string">&#x27;https://cdn.guole.fun/json/bb-json/bbtalk_page1.json&#x27;</span>;</span><br></pre></td></tr></table></figure><h1 id="更新：解决-Safari-无法播放视频问题"><a href="#更新：解决-Safari-无法播放视频问题" class="headerlink" title="更新：解决 Safari 无法播放视频问题"></a>更新：解决 Safari 无法播放视频问题</h1><ol><li>原因：Safari 处理<code>video</code>标签时，会先发一个获取视频 1 字节信息的请求，拿视频封面之类的。只有用户点击播放时，才会再发一个请求，获取后面的完整内容。这里需要 cos 正常响应<code>range</code>请求。但是我原本使用了本站的<code>cdn.guole.fun</code>来获取媒体资源，但这个 CDN 加速域名配置的加速类型是“CDN 网页小文件”，似乎会覆盖导致存储桶本身自动给 .mp4 文件设置的<code>Content-Type: video/mp4</code> 头部信息不生效，Chrome 中正常，但 iOS Safari 中就不行（iOS 里的 Chrome &#x2F; 微信内嵌浏览器都使用 Safari 内核……）  </li><li>解决：测试直接放存储桶的资源链接，是可以正常播放的。但是我这边重新设置<code>cdn.guole.fun</code>的加速类型为“音视频点播”时报错，设置不成功。我就曲线解决了，重新创建了个<code>media.guole.fun</code>加速域名（与<code>cdn.guole.fun</code>都关联同一个存储桶……），专门用来读取多媒体资源，<code>cdn.guole.fun</code>先保留用作它用，后续考虑要不要删除重新创建为“音视频点播”（2023.6.26 已删除重建解决）。  </li><li>创建好相关域名后，拆分成：顶级域名、二级域名、子域，在下面环境变量中配置既可。</li></ol><p>综上所述，如果你准备新建一个存储桶用来放说说多媒体资源，一定记得选加速类型为“音视频点播”。不建议直接暴露使用存储桶的原始域名（没有 CDN 加速）。同时，存储桶和加速域名设置好防盗链，免得被盗刷……</p><h1 id="原文"><a href="#原文" class="headerlink" title="原文"></a>原文</h1><p>分享下本站说说的发展历程。  </p><div class="tag link"><a class="link-card" title="演示：本站说说页面" href="/bb/"><div class="left"><img class="no-lightbox" src="https://blog.guole.fun/img/icon/blog.png"/></div><div class="right"><p class="text">演示：本站说说页面</p><p class="url">/bb/</p></div></a></div><p>早前，使用黑石哔哔、木木的 bber 、小康的 ispeak 等，后来腾讯云开发收费了，就陆续没法用了。  </p><p>目前本站哔哔存储在 <code>LeanCloud</code> (其他 MongoDB 啥的应该也没问题)，<code>/bb/</code> 和首页轮播是我写了个 <code>Vercel</code> 云函数接口，加了个缓存功能，同时避免 <code>LeanCloud</code> 的访问秘钥在前端被泄露。欢迎扫描关注，先行体验效果再决定要不要折腾。  </p><p><img src="/img/posts/bb.png" alt="哔哔闪念"> </p><p>这个端午竟然没出去玩！！就把之前用木木的 bber 复刻了出来，同时新增了发视频、发位置、发链接卡片等功能。微信其实还支持个语音消息，由于是 <code>amr</code> 格式音频，浏览器没法播放，服务端复用 <code>FFmpeg</code> 等插件转换格式，又一直环境不对……心态崩了，干脆摆烂……谁搞定了，欢迎 PR 或下面留言通知我啊！  </p><p>注：本文包含的微信发说说功能，部署在腾讯云 Serverless 里，其他 Vercel 、Railway 应该也没问题，我没折腾。之前域名备案，一定要有服务器之类的 IP ，就买了三年 Serverless 套餐，个人使用不超量的话也很便宜，所以 也不能闲着便宜了腾讯不是……  </p><h1 id="效果演示"><a href="#效果演示" class="headerlink" title="效果演示"></a>效果演示</h1><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/posts/bb-wechat1.jpg","alt":"帮助","title":""},{"url":"https://cdn.guole.fun/img/posts/bb-wechat2.jpg","alt":"发链接卡片","title":""},{"url":"https://cdn.guole.fun/img/posts/bb-wechat3.jpg","alt":"发视频/文本","title":""},{"url":"https://cdn.guole.fun/img/posts/bb-wechat4.jpg","alt":"搜索","title":""},{"url":"https://cdn.guole.fun/img/posts/bb-wechat5.jpg","alt":"发图片","title":""},{"url":"https://cdn.guole.fun/img/posts/bb-wechat6.jpg","alt":"发定位","title":""}]</div>  </div><h1 id="支持特性"><a href="#支持特性" class="headerlink" title="支持特性"></a>支持特性</h1><ul><li>包含<ul><li>部署在云函数上，无需服务器   </li><li>使用微信随时随地发布闪念瞬间（memos 很香，但是得有机器……）  </li><li>在原来 <a href="https://github.com/lmm214">@木木木</a> 的 <code>bber-weixin</code> 基础上升级而来，<strong>新增支持：发位置、发链接卡片、发视频功能</strong>；</li><li>发图片：直接拍照片或发本地图片给公众号既可（存在腾讯云 cos ，原有的去不图床逻辑没删，但我也没验证）；  </li><li>发视频：录视频、或本地视频直接发给公众号既可（存在腾讯云 cos，支持 .mp4 &#x2F; .flv &#x2F; .ts ，其他格式受腾讯 CDN 支持范围影响，不支持 Safari 播放）；  </li><li>发位置：需要在 &#x2F;bb&#x2F; 页面引入资源，详见使用指南；（其他页面嵌入地图，见另一个插件：<a href="https://github.com/kuole-o/hexo-tag-map">hexo-tag-map</a>）  </li><li>发链接卡片：直接分享卡片到公众号；  </li><li><del>发语音：本来想借用 FFmpeg 在服务端转换语音音频 amr 为 mp3，前端再调 aplayer 等播放，但是夭折了……云函数里一直搞不定 FFmpeg 的环境……</del></li></ul></li></ul><h1 id="部署到-LeanCloud"><a href="#部署到-LeanCloud" class="headerlink" title="部署到 LeanCloud"></a>部署到 LeanCloud</h1><p>这部分很简单，到 LeanCloud 注册个 <code>国际版</code> 账号，然后创建一个应用，比如就叫 <code>bb</code>，然后新建 2 个集合 <code>content</code>、<code>UserBindingStatus</code>。  </p><p><img src="https://cdn.guole.fun/img/posts/111.png" alt="LeanCloud"> 可以在 LeanCloud 导入导出功能里，把你原来的数据导进去（建议部署后，发布 1 条消息，数据库自动创建字段后，再导出到本地，按照字段映射手动修改后，再导入以前的数据进去。做好备份，大不了多试几次）。<code>content</code> 集合差不多有这几个字段：  </p><table><thead><tr><th>字段名</th><th>类型</th><th>说明</th></tr></thead><tbody><tr><td>objectId</td><td>String</td><td>唯一标识符，LeanCloud 自动创建，无视它；</td></tr><tr><td>ACL</td><td>ACL</td><td>读写权限，LeanCloud 自动创建，无视它</td></tr><tr><td>MsgType</td><td>String</td><td>微信消息类型，前端用来处理一些逻辑</td></tr><tr><td>content</td><td>String</td><td>说说内容</td></tr><tr><td>from</td><td>String</td><td>说说来源，自定义</td></tr><tr><td>other</td><td>String</td><td>一些特殊消息，比如位置消息，保存脚本，前端插入后渲染出地图</td></tr><tr><td>createdAt</td><td>Date</td><td>创建日期时间，LeanCloud 自动创建，无视它；若导入数据，得修改这个字段，ISO 格式的时间戳，比如 2023-06-24T07:20:55.650Z</td></tr><tr><td>updatedAt</td><td>Date</td><td>更新日期时间，LeanCloud 自动创建，无视它</td></tr></tbody></table><p><code>UserBindingStatus</code> 集合不用管，字段云函数会自动创建。（其实 <code>content</code> 集合应该也不用手动创建字段……只是我没试过）  </p><h1 id="获取-LeanCloud-凭证"><a href="#获取-LeanCloud-凭证" class="headerlink" title="获取 LeanCloud 凭证"></a>获取 LeanCloud 凭证</h1><ol><li>上述 content 和 UserBindingStatus 集合需要在同一个应用里，这样 appid 才一样；  </li><li>在 <a href="https://console.leancloud.app/apps">LeanCloud 应用凭证</a> 界面（设置——应用凭证），找到 <code>AppID</code> &#x2F; <code>AppKey</code> &#x2F; <code>MasterKey</code> 信息，记录下来下文使用。</li></ol><p><img src="https://cdn.guole.fun/img/posts/112.jpg" alt="获取 LeanCloud 凭证"></p><h1 id="获取腾讯云-API-访问密钥"><a href="#获取腾讯云-API-访问密钥" class="headerlink" title="获取腾讯云 API 访问密钥"></a>获取腾讯云 API 访问密钥</h1><ol><li>注册并认证腾讯云开发者；  </li><li>在腾讯云 <a href="https://console.cloud.tencent.com/cam/capi">访问管理</a> 界面新建 1 个密钥。（建议创建一个子用户，可以更小颗粒度限制权限范围，更安全）；  </li><li>如果使用子用户（访问方式选择“编程访问”），在关联策略中，搜索 <code>cos</code> ，选择<code>QcloudCOSDataFullControl 对象存储（COS）数据读、写、删除、列出的访问权限</code> 这一项既可；（为啥要删除权限，因为你发指令删除说说时，如果包含了视频图片等资源，是同步删了存储桶文件的）</li></ol><p><img src="https://cdn.guole.fun/img/posts/118.png" alt="QcloudCOSDataFullControl"><br>4. 记录下 <code>SecretId</code> &#x2F; <code>SecretKey</code>；  </p><p><img src="https://cdn.guole.fun/img/posts/113.jpg" alt="腾讯云 API 访问密钥"></p><h1 id="获取微信公众号凭证"><a href="#获取微信公众号凭证" class="headerlink" title="获取微信公众号凭证"></a>获取微信公众号凭证</h1><ol><li>注册一个微信公众号，个人只能注册订阅号 <a href="https://mp.weixin.qq.com/?token=&lang=zh_CN">微信公众平台</a>；  </li><li>在公众平台 —— 设置与开发 —— 基本设置界面，记录下 <code>AppID</code> &#x2F; <code>AppSecret</code>；  </li><li>在服务器配置中，选择兼容模式，自定义<code>Token</code>，随机生成 <code>EncodingAESKey</code>都记录下来；  </li><li>不要关闭这个页面，等下回来配置服务器地址；</li></ol><p><img src="https://cdn.guole.fun/img/posts/114.jpg" alt="获取微信公众号凭证 "></p><h1 id="创建云函数"><a href="#创建云函数" class="headerlink" title="创建云函数"></a>创建云函数</h1><ol><li>访问腾讯云云函数平台 <a href="https://console.cloud.tencent.com/scf/list">腾讯云 Serverless</a>;  </li><li>创建一个云函数，选择 <code>从头开始</code>，函数类型：<code>事件函数</code>；函数名称：自定义；地域：<code>中国香港</code>（要访问 LeanCloud，香港可能好一点）；运行环境：<code>Nodejs 16.13</code>;</li></ol><p><img src="https://cdn.guole.fun/img/posts/115.png" alt="创建云函数"><br>3. 其他配置中，启用<code>日志投递</code>。默认格式；启用<code>固定公网出口 IP</code>；触发器选择 <code>自定义创建</code>，触发方式选择 <code>API 网关触发</code>，勾选<code>集成响应</code>，其他用默认的不用改。<br>4. 创建一个 <code>src</code> 目录，函数代码拷贝我 <a href="https://github.com/kuole-o/BBtalk-Serverless">Github 仓库：BBtalk-Serverless</a>，总共是 6 个文件，都放在 <code>src</code>目录下保存。不要在线安装依赖，部署太慢了，往下看；<br>5. 本地创建个空目录，<code>git clone</code> 或手动下载解压缩都可以，下载我的代码包<a href="https://github.com/kuole-o/BBtalk-Serverless">Github 仓库：BBtalk-Serverless</a>，然后 <code>cd src</code> 后，<code>npm install</code> 安装依赖；<br>6. 进入 <code>src</code>下的 <code>node_modules</code> 目录，全选压缩为 .zip 压缩包；（一定要进入<code>node_modules</code>目录全选压缩）<br>7. 在腾讯云云函数页面，选择<code>层</code>，新建<code>层</code>，名称随意，上传刚才压缩的 zip 包；<br>8. 进入函数服务 —— 刚才创建的云函数 —— <code>层管理</code>，绑定刚才创建的 <code>层</code>；  </p><p><img src="https://cdn.guole.fun/img/posts/116.png" alt="层管理"><br>9. 回到 <code>函数配置</code>，右上角<code>编辑</code>，创建以下环境变量(Tcb_Bucket &#x2F; Tcb_Region &#x2F; Tcb_ImagePath &#x2F; Tcb_MediaPath &#x2F; Tcb_JsonPath 请自行手动创建)：  </p><table><thead><tr><th>key</th><th>value</th></tr></thead><tbody><tr><td>Binding_Key</td><td>绑定密钥，自定义一条字符串</td></tr><tr><td>LeanCloud_ID</td><td>上面记录的 LeanCloud AppID</td></tr><tr><td>LeanCloud_KEY</td><td>上面记录的 LeanCloud AppKey</td></tr><tr><td>LeanCloud_MasterKey</td><td>上面记录的 LeanCloud MasterKey</td></tr><tr><td>Tcb_SecretId</td><td>上面记录的腾讯云 API 访问秘钥 SecretId</td></tr><tr><td>Tcb_SecretKey</td><td>上面记录的腾讯云 API 访问秘钥 SecretKey</td></tr><tr><td>WeChat_Token</td><td>上面记录的微信公众平台自定义的 Token</td></tr><tr><td>WeChat_appId</td><td>上面记录的微信公众平台自定义的 AppID</td></tr><tr><td>WeChat_appSecret</td><td>上面记录的微信公众平台自定义的 AppSecret</td></tr><tr><td>WeChat_encodingAesKey</td><td>上面记录的微信公众平台自定义的 EncodingAESKey</td></tr><tr><td>Upload_Media_Method</td><td>图片 &#x2F; 视频的上传方式，可选值：<code>cos</code>或<code>qubu</code>，要使用发视频功能必须配置为<code>cos</code>；<code>qubu</code>我没测试…</td></tr><tr><td>Tcb_Bucket</td><td>腾讯云存储桶名称（如“file-1258755354”）。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>Tcb_Region</td><td>腾讯云存储桶地域(如“ap-guangzhou”)。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>Tcb_ImagePath</td><td>腾讯云存储桶图片路径(如“&#x2F;img&#x2F;bb-img&#x2F;”，即图片上传你要放在什么路径)。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>Tcb_MediaPath</td><td>腾讯云存储桶媒体路径(如“&#x2F;media&#x2F;bb-media&#x2F;”，即媒体上传你要放在什么路径)。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>Tcb_JsonPath</td><td>腾讯云存储桶 JSON 转储路径(如“&#x2F;json&#x2F;bb-json&#x2F;”，即媒体上传你要放在什么路径)。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>TopDomain</td><td>顶级域名（如 media.guole.fun 中的 “fun”）。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>SecondLevelDomain</td><td>二级域名（如 media.guole.fun 中的 “guole”）。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>SubDomain</td><td>子域（如 media.guole.fun 中的 “media”）。若 Upload_Media_Method 为 cos ，此项必填</td></tr><tr><td>PageSize</td><td>从 LeanCloud 获取数据转 Json 的每页条数。若 Upload_Media_Method 为 cos ，此项必填</td></tr></tbody></table><ol start="10"><li>提交保存环境变量后，回到函数配置界面，点击<code>部署</code>；  </li><li>在云函数<code>触发管理</code>中，记录下<code>访问路径</code>；</li></ol><h1 id="完成微信公众号配置"><a href="#完成微信公众号配置" class="headerlink" title="完成微信公众号配置"></a>完成微信公众号配置</h1><p>在刚才停留的公众号配置界面，服务器地址填写上面记录的云函数<code>访问路径</code>，然后提交，应该就成功了。  </p><p>IP 白名单：一定要配置这个，不然发图、视频时，取不到微信 Access token 。ip 就是上面云函数的固定出口 IP 地址。  </p><p><img src="https://cdn.guole.fun/img/posts/117.jpg" alt="ip白名单"> 这个地方如果微信校验不通过，重点检查云函数环境变量 Token 与微信这边填的是否相同，验证云函数执行方法是否为<code>index.main_handler</code>，浏览器访问云函数<code>访问路径</code>，显示<code>403</code>错误应该就没问题；  </p><h1 id="Hexo-创建说说页面"><a href="#Hexo-创建说说页面" class="headerlink" title="Hexo 创建说说页面"></a>Hexo 创建说说页面</h1><p>在 Blog 根目录，执行<code>hexo new page bb</code>新建一个页面，<code>bb</code>是说说页面路径，可以自定义；接着：    </p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">index.md</button><button type="button" class="tab">bbtalk.css</button><button type="button" class="tab">timeago.js</button><button type="button" class="tab">BBtalk.js</button></div><div class="tab-contents"><div class="tab-item-content active"><p>在 <code>/bb/</code> 目录下的 <code>index.md</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><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></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: 哔哔闪念</span><br><span class="line">date: 2021-06-07 17:29:43</span><br><span class="line">type: &quot;bb&quot;</span><br><span class="line">aplayer: false</span><br><span class="line">top<span class="emphasis">_img: false</span></span><br><span class="line"><span class="emphasis">#aside: false</span></span><br><span class="line"><span class="emphasis">---</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% note success %&#125;</span></span><br><span class="line"><span class="emphasis">本页使用「哔哔闪念 2.0」生成，记录 @夜的第八章 的胡思乱想<span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;/posts/17745&quot;</span> <span class="attr">class</span>=<span class="string">&quot;banner-button&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;iconfont icon-you&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">&quot;banner-button-text&quot;</span>&gt;</span></span>部署指引<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">a</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis">&#123;% endnote %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&lt;!-- 存放闪念的容器 --&gt;</span></span><br><span class="line"><span class="emphasis">&lt;!-- <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;js-pjax&quot;</span>&gt;</span></span> --&gt;</span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;bbtalk&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;info&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;loading&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align: center&quot;</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;/img/loading1.gif&#x27;</span> <span class="attr">alt</span>=<span class="string">&quot;loading…&quot;</span> <span class="attr">class</span>=<span class="string">&quot;no-lightbox nolazyload&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width: 11rem;&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">img</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&quot;load-more-btn&quot;</span> <span class="attr">class</span>=<span class="string">&quot;next&quot;</span> <span class="attr">style</span>=<span class="string">&quot;background:linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab); background-size: 1000% 1000%;box-shadow: 0 0px 6px 1px rgb(7,17,27,15%)&quot;</span>&gt;</span></span>再翻翻<span class="language-xml"><span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;bbtalk-bottom-tip&quot;</span> <span class="attr">id</span>=<span class="string">&quot;bbtalk-bottom-tip&quot;</span> <span class="attr">style</span>=<span class="string">&quot;display: none;color:#CACACA;text-align: center;font-size: 14px;&quot;</span>&gt;</span></span>~&amp;nbsp;我是有底线的&amp;nbsp;~<span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis">&lt;!-- <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;gaodeMap-22.521799-113.99757&quot;</span> <span class="attr">id</span>=<span class="string">&quot;gaodeMap-22.521799-113.99757&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span> --&gt;</span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.css&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;/css/bbtalk.css&quot;</span> <span class="attr">onload</span>=<span class="string">&quot;this.media=&#x27;all&#x27;&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">data-pjax</span>=<span class="string">&quot;&quot;</span> <span class="attr">src</span>=<span class="string">&quot;//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.js&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">data-pjax</span>=<span class="string">&quot;&quot;</span> <span class="attr">src</span>=<span class="string">&quot;//unpkg.com/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;/js/timeago@4.0.2.min.js&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;/js/BBtalk.js&quot;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span></span></span><br><span class="line"><span class="emphasis">  bbtalk.init(&#123;</span></span><br><span class="line"><span class="emphasis">    bbtalk_</span>name: &#x27;夜的第八章&#x27;, // 昵称</span><br><span class="line"><span class="code">    bbtalk_avatar: &#x27;/img/gl.jpg&#x27;, // 头像</span></span><br><span class="line"><span class="code">    bbtalk_avatar_svg: &#x27;&#x27;, //头像后的图标，可留空使用默认的</span></span><br><span class="line"><span class="code">    aplayer_js: &#x27;/js/APlayer.min.js&#x27;, //自定义引入 aplayer</span></span><br><span class="line"><span class="code">    // leaflet_css: &#x27;&#x27;, // 无必要可注释</span></span><br><span class="line"><span class="code">    // leaflet_js: &#x27;&#x27;, // 无必要可注释</span></span><br><span class="line"><span class="code">    // ChineseTmsProviders_js: &#x27;&#x27;, // 无必要可注释</span></span><br><span class="line"><span class="code">  &#125;);</span></span><br><span class="line"><span class="code">&lt;/script&gt;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>再去 <code>/source/css/</code> 目录下创建一个 <code>bbtalk.css</code> 文件（也可以命名其他的或者放在其他地方，上面 md 文件里记得同步修改），内容如下：  </p><figure class="highlight css"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br><span class="line">539</span><br><span class="line">540</span><br><span class="line">541</span><br><span class="line">542</span><br><span class="line">543</span><br><span class="line">544</span><br><span class="line">545</span><br><span class="line">546</span><br><span class="line">547</span><br><span class="line">548</span><br><span class="line">549</span><br><span class="line">550</span><br><span class="line">551</span><br><span class="line">552</span><br><span class="line">553</span><br><span class="line">554</span><br><span class="line">555</span><br><span class="line">556</span><br><span class="line">557</span><br><span class="line">558</span><br><span class="line">559</span><br><span class="line">560</span><br><span class="line">561</span><br><span class="line">562</span><br><span class="line">563</span><br><span class="line">564</span><br><span class="line">565</span><br><span class="line">566</span><br><span class="line">567</span><br><span class="line">568</span><br><span class="line">569</span><br><span class="line">570</span><br><span class="line">571</span><br><span class="line">572</span><br><span class="line">573</span><br><span class="line">574</span><br><span class="line">575</span><br><span class="line">576</span><br><span class="line">577</span><br><span class="line">578</span><br><span class="line">579</span><br><span class="line">580</span><br><span class="line">581</span><br><span class="line">582</span><br><span class="line">583</span><br><span class="line">584</span><br><span class="line">585</span><br><span class="line">586</span><br><span class="line">587</span><br><span class="line">588</span><br><span class="line">589</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-attr">[data-theme=light]</span> &#123;</span><br><span class="line">  <span class="attr">--bbtalk-from-color</span>: <span class="number">#fff</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-chrome</span>: <span class="number">#aa96f5</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-wechat</span>: <span class="number">#49c65b</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-postman</span>: <span class="number">#7194a4</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-edge</span>: <span class="number">#2196f3</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-siri</span>: <span class="number">#8290d6</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-bg</span>: <span class="number">#9e9e9e</span>;</span><br><span class="line">  <span class="attr">--bb-TimeTitle-bg</span>: <span class="built_in">rgba</span>(<span class="number">48</span>, <span class="number">49</span>, <span class="number">51</span>, <span class="number">0.85</span>);</span><br><span class="line">  <span class="attr">--bb-TimeTitle</span>: <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.9</span>);</span><br><span class="line">  <span class="attr">--bbtalk-url-bg</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-attr">[data-theme=dark]</span> &#123;</span><br><span class="line">  <span class="attr">--bbtalk-from-color</span>: <span class="built_in">rgba</span>(<span class="number">255</span>,<span class="number">255</span>,<span class="number">255</span>,<span class="number">0.7</span>);</span><br><span class="line">  <span class="attr">--bbtalk-from-chrome</span>: <span class="number">#8573c8</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-wechat</span>: <span class="number">#31933f</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-postman</span>: <span class="number">#607d8b</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-edge</span>: <span class="number">#1b84d8</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-siri</span>: <span class="number">#6b7bce</span>;</span><br><span class="line">  <span class="attr">--bbtalk-from-bg</span>: <span class="number">#847f7f</span>;</span><br><span class="line">  <span class="attr">--bb-TimeTitle-bg</span>: <span class="number">#042537</span>;</span><br><span class="line">  <span class="attr">--bb-TimeTitle</span>: <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.7</span>);</span><br><span class="line">  <span class="attr">--bbtalk-url-bg</span>: <span class="number">#222528</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#article-container</span> <span class="selector-tag">img</span><span class="selector-pseudo">:not</span>(<span class="selector-id">#loading</span> <span class="selector-tag">img</span>) &#123;<span class="attribute">margin</span>: unset;&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">div</span><span class="selector-class">.timenode</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: unset;</span><br><span class="line">    <span class="attribute">box-shadow</span>: unset;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="built_in">var</span>(--guole-card-border);</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">1.8rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">div</span><span class="selector-class">.timenode</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: unset;</span><br><span class="line">    <span class="attribute">box-shadow</span>: unset;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="built_in">rgba</span>(<span class="number">28</span>,<span class="number">105</span>,<span class="number">237</span>,<span class="number">0.5</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#loading</span> <span class="selector-tag">img</span> &#123;</span><br><span class="line">    <span class="attribute">text-align</span>: center;</span><br><span class="line">    <span class="attribute">display</span>: inline-block;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#loading</span> <span class="selector-class">.img-alt</span><span class="selector-class">.is-center</span> &#123;</span><br><span class="line">    <span class="attribute">text-align</span>: center</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@font-face</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&quot;iconfont&quot;</span>;</span><br><span class="line">  <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">&quot;//at.alicdn.com/t/font_1755564_z4mhxbw13mq.eot?t=1586882866168&quot;</span>);</span><br><span class="line">  <span class="comment">/* IE9 */</span></span><br><span class="line">  <span class="attribute">src</span>: <span class="built_in">url</span>(<span class="string">&quot;//at.alicdn.com/t/font_1755564_z4mhxbw13mq.eot?t=1586882866168#iefix&quot;</span>)</span><br><span class="line">      <span class="built_in">format</span>(<span class="string">&quot;embedded-opentype&quot;</span>),</span><br><span class="line">    <span class="comment">/* IE6-IE8 */</span></span><br><span class="line">      <span class="built_in">url</span>(<span class="string">&quot;data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAALcAAsAAAAAB2gAAAKPAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCfgqCUII8ATYCJAMMCwgABCAFhG0HQBuEBsiuMRkynL4YFCHtLKs4b+k7/80U8DwHIB6+xtr7u3vniDZI6tmnkyDS8NC5iFgJlE7pTPcO8e5b+803aYQy8YtH1JPKyZzY3ttb1EonioVGSBAiRJp4JV9cFppCxLpe2z8sUs37O4QEDFRM0lFeAw4XN6bQPG06zTG8DRwHFOBeGEVWIjE+mP8wduVFPCbQNK4ktN8/OgFJhbEqEFemLkEyFVcUVqoL1ZKDRbyIqafb9AA8+9+PX41IklQyY+PBSZ8KnR+9iBx0OxZcp8PxvGDHyFgACnFY6j8QCfMLIppKPmoCrGtW8OG/y0eufLX/8AiJqDKa22AGWpMzUth6p6aARySQQRUUL4AnSBmuyvIwPdbz21OX5ybO5duOJifaLl6cvkrd1HR7kWEy6yikff29PvgO17V/Tf/9f/oN3PDqz22a719IYlZJHQetpLY08MV6fwFDrF0B6F4XyB3/FyEEnZnU2XGtVwHvpxtA1d6pftKB4AcoWo4U1QQbiiy35Xow27whbwK2NNFlhAc99zeOtM4S6ikFQ1IzhqxuglAoC6ho2UBV3Raa5g0cbxnCRURpYM4pQOh3h6TXG7J+j4RCeULFqFdU9UcETYfRdGHLVJjpHk6SIBXlTTQV5mmWS6SD1jHSVx2JJ1U+a4p4YKawvrSSLQ2QR3yMLcGa3hBCQ40zF/vBc+Q4DH3OLFJExRDCb64un5S9qaIwF9L2cEQiEBWSbUImBePR3PFCOvf5MUS3yiHhNR0VySmEC5jTo7qKWgvCgN5r1XEtrwTW6BoEQYM0HONC/cBLHDPPIL98noUohAqjR7uvWVV1HlVbfWV+o/t8J6DJOJ4jRY6idmVKnmVS1q8tK8zfBAAA&quot;</span>)</span><br><span class="line">      <span class="built_in">format</span>(<span class="string">&quot;woff2&quot;</span>),</span><br><span class="line">    <span class="built_in">url</span>(<span class="string">&quot;//at.alicdn.com/t/font_1755564_z4mhxbw13mq.woff?t=1586882866168&quot;</span>)</span><br><span class="line">      <span class="built_in">format</span>(<span class="string">&quot;woff&quot;</span>),</span><br><span class="line">    <span class="built_in">url</span>(<span class="string">&quot;//at.alicdn.com/t/font_1755564_z4mhxbw13mq.ttf?t=1586882866168&quot;</span>)</span><br><span class="line">      <span class="built_in">format</span>(<span class="string">&quot;truetype&quot;</span>),</span><br><span class="line">    <span class="comment">/* chrome, firefox, opera, Safari, Android, iOS 4.2+ */</span></span><br><span class="line">      <span class="built_in">url</span>(<span class="string">&quot;//at.alicdn.com/t/font_1755564_z4mhxbw13mq.svg?t=1586882866168#iconfont&quot;</span>)</span><br><span class="line">      <span class="built_in">format</span>(<span class="string">&quot;svg&quot;</span>);</span><br><span class="line">  <span class="comment">/* iOS 4.1- */</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">img</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: block;</span><br><span class="line">  <span class="attribute">max-height</span>: <span class="number">16rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-content</span> <span class="selector-tag">a</span><span class="selector-pseudo">:not</span>(<span class="selector-class">.leaflet-control-container</span> <span class="selector-tag">a</span>) &#123;</span><br><span class="line">  <span class="attribute">display</span>: inline-block;</span><br><span class="line">  <span class="attribute">text-align</span>: left;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.iconfont</span> &#123;</span><br><span class="line">  <span class="attribute">font-family</span>: <span class="string">&quot;iconfont&quot;</span> <span class="meta">!important</span>;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">16px</span>;</span><br><span class="line">  <span class="attribute">font-style</span>: normal;</span><br><span class="line">  -webkit-<span class="attribute">font-smoothing</span>: antialiased;</span><br><span class="line">  -moz-osx-<span class="attribute">font-smoothing</span>: grayscale;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.icon-lianjie</span><span class="selector-pseudo">:before</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">&quot;\e6a3&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.icon-lianjie-copy</span><span class="selector-pseudo">:before</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">&quot;\e6a4&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#article-container</span> <span class="selector-class">.banner-button</span> &#123;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">40px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">118px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">justify-content</span>: center;</span><br><span class="line">    <span class="attribute">background</span>: <span class="number">#67b010</span>;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#fff</span>;;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">    <span class="attribute">z-index</span>: <span class="number">1</span>;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">3s</span>;</span><br><span class="line">    <span class="attribute">cursor</span>: pointer;</span><br><span class="line">    backdrop-<span class="attribute">filter</span>: <span class="built_in">saturate</span>(<span class="number">180%</span>) <span class="built_in">blur</span>(<span class="number">20px</span>);</span><br><span class="line">    -webkit-backdrop-<span class="attribute">filter</span>: <span class="built_in">blur</span>(<span class="number">20px</span>);</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">translateZ</span>(<span class="number">0</span>);</span><br><span class="line">    <span class="attribute">border-bottom</span>: unset <span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">right</span>: <span class="number">1.4rem</span>;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">display</span>: inline-flex;</span><br><span class="line">    <span class="attribute">bottom</span>: <span class="number">0.68rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#article-container</span> <span class="selector-class">.banner-button</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="number">#007909</span>;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#article-container</span> <span class="selector-class">.banner-button</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">6px</span>;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">22px</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1200px</span>) &#123;</span><br><span class="line">  <span class="selector-id">#article-container</span> <span class="selector-class">.banner-button</span> &#123;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">32px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">98px</span>;</span><br><span class="line">    <span class="attribute">right</span>: <span class="number">0.8rem</span>;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="selector-id">#article-container</span> <span class="selector-class">.banner-button</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">4px</span>;    </span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">16px</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.map-box</span> <span class="selector-class">.leaflet-container</span> &#123;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">300px</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/* bb样式 */</span></span><br><span class="line"><span class="comment">/* 移动端自定义布局适配 */</span></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-id">#bbtalk</span> <span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span> &#123;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">5px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line">    <span class="attribute">display</span>: block;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-id">#bbtalk</span> <span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.card-name</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">10px</span> <span class="number">5px</span> <span class="number">5px</span> <span class="number">5px</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-id">#bbtalk</span> <span class="selector-tag">div</span><span class="selector-class">.timenode</span> &#123;</span><br><span class="line">      <span class="attribute">padding</span>: <span class="number">8px</span> <span class="number">14px</span>;</span><br><span class="line">      <span class="attribute">margin-top</span>: <span class="number">1.4rem</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> &#123;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">10px</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">rgba</span>(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>, <span class="number">0.1</span>);</span><br><span class="line">    <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">3px</span> <span class="number">8px</span> <span class="number">6px</span> <span class="built_in">rgba</span>(<span class="number">7</span>, <span class="number">17</span>, <span class="number">27</span>, <span class="number">0.06</span>);</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">32px</span>;</span><br><span class="line">    user-<span class="selector-tag">select</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">2px</span> <span class="number">10px</span> <span class="number">5px</span> <span class="built_in">rgba</span>(<span class="number">7</span>, <span class="number">17</span>, <span class="number">27</span>, <span class="number">0.16</span>);</span><br><span class="line">  <span class="attribute">transition</span>: all .<span class="number">15s</span> ease-in-out;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span><span class="selector-pseudo">:last-child</span><span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">  <span class="attribute">height</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">26px</span> - <span class="number">16px</span>);</span><br><span class="line">  <span class="attribute">border-bottom-left-radius</span>: <span class="number">2px</span>;</span><br><span class="line">  <span class="attribute">border-bottom-right-radius</span>: <span class="number">2px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.time</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">32px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">32px</span>;</span><br><span class="line">  <span class="attribute">margin-left</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">cursor</span>: pointer;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.time</span> <span class="selector-tag">p</span> &#123;</span><br><span class="line">  <span class="attribute">font-weight</span>: bold;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">0</span> <span class="number">24px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span><span class="selector-pseudo">:empty</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span> &#123;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">16px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span> &gt; *<span class="selector-pseudo">:first-child</span> &#123;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0.25em</span> <span class="number">0</span> <span class="number">0.8rem</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span> &gt; *<span class="selector-pseudo">:last-child</span> &#123;</span><br><span class="line">  <span class="attribute">margin-bottom</span>: <span class="number">0.25em</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span> <span class="selector-class">.highlight</span> &#123;</span><br><span class="line">  <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#e4e4e4</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-tag">time</span><span class="selector-pseudo">::after</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="built_in">attr</span>(data-msg);</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">left</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-tag">time</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">var</span>(--bb-TimeTitle-bg);</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">var</span>(--bb-TimeTitle);</span><br><span class="line">  <span class="attribute">left</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">70px</span>);</span><br><span class="line">  <span class="attribute">top</span>: <span class="number">36px</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">8px</span> <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">6px</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">180px</span>;</span><br><span class="line">  <span class="attribute">height</span>: auto;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0.9</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">1.2</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: <span class="number">500</span>;</span><br><span class="line">  <span class="attribute">transition</span>: opacity <span class="number">1s</span>;</span><br><span class="line">  <span class="attribute">z-index</span>: <span class="number">10</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/* 小三角标 */</span></span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-tag">time</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">&quot;&quot;</span>;</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-tag">time</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:before</span> &#123;</span><br><span class="line">  <span class="attribute">top</span>: <span class="number">24px</span>;</span><br><span class="line">  <span class="attribute">left</span>: <span class="built_in">calc</span>(<span class="number">50%</span> - <span class="number">4px</span>);</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">8px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">6px</span>;</span><br><span class="line">  <span class="attribute">border</span>: <span class="number">6px</span> dashed <span class="built_in">var</span>(--bb-TimeTitle-bg);</span><br><span class="line">  <span class="attribute">border-color</span>: transparent transparent <span class="built_in">var</span>(--bb-TimeTitle-bg) transparent;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0.9</span>;</span><br><span class="line"><span class="comment">/*   transition: opacity 0.5s; */</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.body</span> &#123;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">15px</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">16px</span> <span class="number">16px</span> <span class="number">16px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line"><span class="comment">/*   background: #f6f6f6; */</span></span><br><span class="line">  <span class="attribute">display</span>: block;</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="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">border</span>: none;</span><br><span class="line">  <span class="attribute">background-color</span>: transparent;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">1.5</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#333</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-body</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-direction</span>: row;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">justify-content</span>: flex-start;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">40px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span><br><span class="line">  <span class="attribute">cursor</span>: pointer;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-body</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#e6e6e6</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-info</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-direction</span>: row;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">justify-content</span>: flex-start;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-info</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#e6e6e6</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-icon</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-direction</span>: row;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">justify-content</span>: center;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">40px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">40px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#4cd964</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">18px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-icon</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#44c662</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-icon</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-name</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-direction</span>: row;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">justify-content</span>: flex-start;</span><br><span class="line">  <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">40px</span>);</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: bold;</span><br><span class="line">  <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">text-overflow</span>: ellipsis;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-media</span> <span class="selector-class">.aplayer</span><span class="selector-class">.aplayer-withlrc</span><span class="selector-class">.aplayer-withlist</span> <span class="selector-class">.aplayer-author</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-direction</span>: row;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">justify-content</span>: flex-start;</span><br><span class="line">  <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">40px</span>);</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="number">#f5f5f5</span>;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#999</span>;</span><br><span class="line">  <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">text-overflow</span>: ellipsis;</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="selector-class">.bbtalk-url</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">  <span class="attribute">display</span>: inline-block;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">max-width</span>: <span class="number">600px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">10px</span> <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="built_in">var</span>(--bbtalk-url-bg);</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0px</span> <span class="number">1px</span> <span class="number">4px</span> <span class="built_in">rgba</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0.2</span>);</span><br><span class="line">  <span class="attribute">text-decoration</span>: auto <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.bbtalk-url-info</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">top</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">left</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">80px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">80px</span>;</span><br><span class="line">  <span class="attribute">background-size</span>: cover;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">10px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.bbtalk-url-info</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">4rem</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#5d91a366</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.bbtalk-url-title</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">18px</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: bold;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="number">110px</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">1.4rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.bbtalk-url-desc</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#999</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="number">110px</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">1.2rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-class">.bbtalk-url-info</span> &#123;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">0.6</span>;</span><br><span class="line">    <span class="attribute">bottom</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">right</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">top</span>: unset;</span><br><span class="line">    <span class="attribute">left</span>: unset;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.bbtalk-url-title</span>, <span class="selector-class">.bbtalk-url-desc</span> &#123;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">10px</span> <span class="number">0px</span>;</span><br><span class="line">  &#125;</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="selector-id">#bbtalk-content</span> <span class="selector-class">.leaflet-fade-anim</span> <span class="selector-class">.leaflet-map-pane</span> <span class="selector-class">.leaflet-popup</span> &#123;</span><br><span class="line">    <span class="attribute">bottom</span>: -<span class="number">30px</span> <span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">left</span>: -<span class="number">86px</span> <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bbtalk-content</span> <span class="selector-class">.map-box</span> &#123;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0.8rem</span> <span class="number">0</span> <span class="number">1.2rem</span> <span class="number">0</span>;</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="selector-id">#bbtalk-content</span> <span class="selector-tag">video</span> &#123;</span><br><span class="line">  <span class="attribute">margin-top</span>: <span class="number">0.8rem</span>;</span><br><span class="line">  <span class="attribute">max-height</span>: <span class="number">16rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.card-name</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">15px</span> <span class="number">5px</span> <span class="number">15px</span> <span class="number">15px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.card-name</span> <span class="selector-class">.is-badge</span> &#123;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">20px</span>;</span><br><span class="line">  <span class="attribute">margin-left</span>: <span class="number">8px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.card-name</span> <span class="selector-class">.avatar</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">32px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">32px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span><br><span class="line">  <span class="attribute">margin-right</span>: <span class="number">10px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.card-name</span> <span class="selector-class">.avatar-img</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: unset;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.bbtalk-from</span> &#123;</span><br><span class="line">    <span class="comment">/* background-color: #f596aa; */</span></span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--bbtalk-from-color);</span><br><span class="line">    <span class="attribute">font-weight</span>: <span class="number">600</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">4px</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">8px</span> <span class="number">2px</span> <span class="number">2px</span>;</span><br><span class="line">    <span class="attribute">width</span>:fit-content;</span><br><span class="line">    <span class="attribute">width</span>:-webkit-fit-content;</span><br><span class="line">    <span class="attribute">width</span>:-moz-fit-content;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-class">.timenode</span> <span class="selector-class">.loading</span> &#123;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">@keyframes</span> Gradient &#123;</span><br><span class="line">  <span class="number">0%</span> &#123;</span><br><span class="line">    <span class="attribute">background-position</span>: <span class="number">0</span> <span class="number">50%</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="number">50%</span> &#123;</span><br><span class="line">    <span class="attribute">background-position</span>: <span class="number">100%</span> <span class="number">50%</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="selector-tag">to</span> &#123;</span><br><span class="line">    <span class="attribute">background-position</span>: <span class="number">0</span> <span class="number">50%</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">button</span><span class="selector-class">.next</span> &#123;</span><br><span class="line">  <span class="attribute">cursor</span>: pointer;</span><br><span class="line">  <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">  <span class="attribute">border</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">2rem</span> auto <span class="number">3rem</span> auto;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">0.3125rem</span>;</span><br><span class="line">  <span class="attribute">display</span>: none;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">1rem</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">40px</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: <span class="number">500</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">transition</span>: all <span class="number">0.5s</span> ease-out;</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">-webkit-linear-gradient</span>(-<span class="number">45deg</span>, <span class="number">#ee7752</span>, <span class="number">#e73c7e</span>, <span class="number">#23a6d5</span>, <span class="number">#23d5ab</span>);</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(-<span class="number">45deg</span>, <span class="number">#ee7752</span>, <span class="number">#e73c7e</span>, <span class="number">#23a6d5</span>, <span class="number">#23d5ab</span>);</span><br><span class="line">  <span class="attribute">background-size</span>: <span class="number">1000%</span> <span class="number">1000%</span>;</span><br><span class="line">  <span class="attribute">animation</span>: Gradient <span class="number">10s</span> linear infinite;</span><br><span class="line">  <span class="attribute">outline</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">0px</span> <span class="number">6px</span> <span class="number">1px</span> <span class="built_in">rgb</span>(<span class="number">7</span> <span class="number">17</span> <span class="number">27</span> / <span class="number">15%</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">button</span><span class="selector-class">.next</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">0px</span> <span class="number">6px</span> <span class="number">2px</span> <span class="built_in">rgb</span>(<span class="number">7</span> <span class="number">17</span> <span class="number">27</span> / <span class="number">15%</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-class">.load-ctn</span> <span class="selector-tag">a</span>&#123;<span class="attribute">padding</span>:<span class="number">8px</span> <span class="number">18px</span>;<span class="attribute">background</span>:<span class="number">#eaeded</span>;<span class="attribute">border-radius</span>:<span class="number">6px</span>;<span class="attribute">color</span>:<span class="number">#333</span>&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-class">.load-ctn</span>  &#123;<span class="attribute">padding-top</span>:<span class="number">30px</span>;<span class="attribute">cursor</span>:pointer;&#125;</span><br><span class="line"><span class="selector-tag">blockquote</span> &#123;</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">var</span>(--guole-secondbg);</span><br><span class="line">  <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="built_in">var</span>(--guole-card-border);</span><br><span class="line">  <span class="attribute">box-shadow</span>: none;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">margin-bottom</span>: <span class="number">0.5rem</span>;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">0.6rem</span>;</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">var</span>(--guole-secondtext);</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0.5rem</span> <span class="number">0.8rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">blockquote</span> <span class="selector-tag">p</span> &#123;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-class">.bbtalk-bottom</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  -webkit-user-<span class="selector-tag">select</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span> &#123;</span><br><span class="line">  <span class="attribute">line-height</span>: initial;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">cursor</span>: pointer;</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">  <span class="attribute">text-decoration</span>: unset;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">1.3rem</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: bold;</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">var</span>(--bbtalk-reply)</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">var</span>(--guole-main)</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">&quot;&quot;</span>;</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:before</span> &#123;</span><br><span class="line">  <span class="attribute">bottom</span>: <span class="number">24px</span>;</span><br><span class="line">  <span class="attribute">left</span>: <span class="number">4px</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">8px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">6px</span>;</span><br><span class="line">  <span class="attribute">border</span>: <span class="number">6px</span> dashed <span class="built_in">var</span>(--bb-TimeTitle-bg);</span><br><span class="line">  <span class="attribute">border-color</span>: transparent transparent <span class="built_in">var</span>(--bb-TimeTitle-bg) transparent;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0.9</span>;</span><br><span class="line">  <span class="attribute">transform</span>: <span class="built_in">rotate</span>(<span class="number">180deg</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span><span class="selector-pseudo">::after</span> &#123;</span><br><span class="line">  <span class="attribute">content</span>: <span class="string">&quot;引用回复&quot;</span>;</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">left</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">height</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">26px</span> - <span class="number">16px</span>);</span><br><span class="line">  <span class="attribute">border-bottom-left-radius</span>: <span class="number">2px</span>;</span><br><span class="line">  <span class="attribute">border-bottom-right-radius</span>: <span class="number">2px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#bbtalk</span> <span class="selector-tag">a</span><span class="selector-class">.bbtalk-reply</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">var</span>(--bb-TimeTitle-bg);</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">var</span>(--bb-TimeTitle);</span><br><span class="line">  <span class="attribute">left</span>: -<span class="number">42px</span>;</span><br><span class="line">  <span class="attribute">bottom</span>: <span class="number">36px</span>;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">8px</span> <span class="number">10px</span>;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">6px</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100px</span>;</span><br><span class="line">  <span class="attribute">height</span>: auto;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0.9</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">1.2</span>;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">14px</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: <span class="number">500</span>;</span><br><span class="line">  <span class="attribute">transition</span>: opacity <span class="number">1s</span>;</span><br><span class="line">  <span class="attribute">z-index</span>: <span class="number">10</span>;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>引入的 timeago.js 内容如下，放到 <code>source/js/</code> 目录下（其他位置也可，记得修改 md 中地址）：    </p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">!<span class="keyword">function</span>(<span class="params">e,t</span>)&#123;<span class="string">&quot;object&quot;</span>==<span class="keyword">typeof</span> <span class="built_in">exports</span>&amp;&amp;<span class="string">&quot;undefined&quot;</span>!=<span class="keyword">typeof</span> <span class="variable language_">module</span>?<span class="title function_">t</span>(<span class="built_in">exports</span>):<span class="string">&quot;function&quot;</span>==<span class="keyword">typeof</span> define&amp;&amp;define.<span class="property">amd</span>?<span class="title function_">define</span>([<span class="string">&quot;exports&quot;</span>],t):<span class="title function_">t</span>((e=e||self).<span class="property">timeago</span>=&#123;&#125;)&#125;(<span class="variable language_">this</span>,<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="string">&quot;use strict&quot;</span>;<span class="keyword">var</span> r=[<span class="string">&quot;second&quot;</span>,<span class="string">&quot;minute&quot;</span>,<span class="string">&quot;hour&quot;</span>,<span class="string">&quot;day&quot;</span>,<span class="string">&quot;week&quot;</span>,<span class="string">&quot;month&quot;</span>,<span class="string">&quot;year&quot;</span>];<span class="keyword">var</span> a=[<span class="string">&quot;秒&quot;</span>,<span class="string">&quot;分钟&quot;</span>,<span class="string">&quot;小时&quot;</span>,<span class="string">&quot;天&quot;</span>,<span class="string">&quot;周&quot;</span>,<span class="string">&quot;个月&quot;</span>,<span class="string">&quot;年&quot;</span>];<span class="keyword">function</span> <span class="title function_">t</span>(<span class="params">e,t</span>)&#123;n[e]=t&#125;<span class="keyword">function</span> <span class="title function_">i</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> n[e]||n.<span class="property">en_US</span>&#125;<span class="keyword">var</span> n=&#123;&#125;,f=[<span class="number">60</span>,<span class="number">60</span>,<span class="number">24</span>,<span class="number">7</span>,<span class="number">365</span>/<span class="number">7</span>/<span class="number">12</span>,<span class="number">12</span>];<span class="keyword">function</span> <span class="title function_">o</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> e <span class="keyword">instanceof</span> <span class="title class_">Date</span>?<span class="attr">e</span>:!<span class="built_in">isNaN</span>(e)||<span class="regexp">/^\d+$/</span>.<span class="title function_">test</span>(e)?<span class="keyword">new</span> <span class="title class_">Date</span>(<span class="built_in">parseInt</span>(e)):(e=(e||<span class="string">&quot;&quot;</span>).<span class="title function_">trim</span>().<span class="title function_">replace</span>(<span class="regexp">/\.\d+/</span>,<span class="string">&quot;&quot;</span>).<span class="title function_">replace</span>(<span class="regexp">/-/</span>,<span class="string">&quot;/&quot;</span>).<span class="title function_">replace</span>(<span class="regexp">/-/</span>,<span class="string">&quot;/&quot;</span>).<span class="title function_">replace</span>(<span class="regexp">/(\d)T(\d)/</span>,<span class="string">&quot;$1 $2&quot;</span>).<span class="title function_">replace</span>(<span class="regexp">/Z/</span>,<span class="string">&quot; UTC&quot;</span>).<span class="title function_">replace</span>(<span class="regexp">/([+-]\d\d):?(\d\d)/</span>,<span class="string">&quot; $1$2&quot;</span>),<span class="keyword">new</span> <span class="title class_">Date</span>(e))&#125;<span class="keyword">function</span> <span class="title function_">d</span>(<span class="params">e,t</span>)&#123;<span class="keyword">for</span>(<span class="keyword">var</span> n=e&lt;<span class="number">0</span>?<span class="number">1</span>:<span class="number">0</span>,r=e=<span class="title class_">Math</span>.<span class="title function_">abs</span>(e),a=<span class="number">0</span>;e&gt;=f[a]&amp;&amp;a&lt;f.<span class="property">length</span>;a++)e/=f[a];<span class="keyword">return</span>(<span class="number">0</span>===(a*=<span class="number">2</span>)?<span class="number">9</span>:<span class="number">1</span>)&lt;(e=<span class="title class_">Math</span>.<span class="title function_">floor</span>(e))&amp;&amp;(a+=<span class="number">1</span>),<span class="title function_">t</span>(e,a,r)[n].<span class="title function_">replace</span>(<span class="string">&quot;%s&quot;</span>,e.<span class="title function_">toString</span>())&#125;<span class="keyword">function</span> <span class="title function_">l</span>(<span class="params">e,t</span>)&#123;<span class="keyword">return</span>((t?<span class="title function_">o</span>(t):<span class="keyword">new</span> <span class="title class_">Date</span>)-<span class="title function_">o</span>(e))/<span class="number">1e3</span>&#125;<span class="keyword">var</span> s=<span class="string">&quot;timeago-id&quot;</span>;<span class="keyword">function</span> <span class="title function_">h</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> <span class="built_in">parseInt</span>(e.<span class="title function_">getAttribute</span>(s))&#125;<span class="keyword">var</span> p=&#123;&#125;,v=<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="built_in">clearTimeout</span>(e),<span class="keyword">delete</span> p[e]&#125;;<span class="keyword">function</span> <span class="title function_">m</span>(<span class="params">e,t,n,r</span>)&#123;<span class="title function_">v</span>(<span class="title function_">h</span>(e));<span class="keyword">var</span> a=r.<span class="property">relativeDate</span>,i=r.<span class="property">minInterval</span>,o=<span class="title function_">l</span>(t,a);e.<span class="property">innerText</span>=<span class="title function_">d</span>(o,n);<span class="keyword">var</span> u,c=<span class="built_in">setTimeout</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;<span class="title function_">m</span>(e,t,n,r)&#125;,<span class="title class_">Math</span>.<span class="title function_">min</span>(<span class="number">1e3</span>*<span class="title class_">Math</span>.<span class="title function_">max</span>(<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="keyword">for</span>(<span class="keyword">var</span> t=<span class="number">1</span>,n=<span class="number">0</span>,r=<span class="title class_">Math</span>.<span class="title function_">abs</span>(e);e&gt;=f[n]&amp;&amp;n&lt;f.<span class="property">length</span>;n++)e/=f[n],t*=f[n];<span class="keyword">return</span> r=(r%=t)?t-<span class="attr">r</span>:t,<span class="title class_">Math</span>.<span class="title function_">ceil</span>(r)&#125;(o),i||<span class="number">1</span>),<span class="number">2147483647</span>));p[c]=<span class="number">0</span>,u=c,e.<span class="title function_">setAttribute</span>(s,u)&#125;<span class="title function_">t</span>(<span class="string">&quot;en_US&quot;</span>,<span class="keyword">function</span>(<span class="params">e,t</span>)&#123;<span class="keyword">if</span>(<span class="number">0</span>===t)<span class="keyword">return</span>[<span class="string">&quot;just now&quot;</span>,<span class="string">&quot;right now&quot;</span>];<span class="keyword">var</span> n=r[<span class="title class_">Math</span>.<span class="title function_">floor</span>(t/<span class="number">2</span>)];<span class="keyword">return</span> <span class="number">1</span>&lt;e&amp;&amp;(n+=<span class="string">&quot;s&quot;</span>),[e+<span class="string">&quot; &quot;</span>+n+<span class="string">&quot; ago&quot;</span>,<span class="string">&quot;in &quot;</span>+e+<span class="string">&quot; &quot;</span>+n]&#125;),<span class="title function_">t</span>(<span class="string">&quot;zh_CN&quot;</span>,<span class="keyword">function</span>(<span class="params">e,t</span>)&#123;<span class="keyword">if</span>(<span class="number">0</span>===t)<span class="keyword">return</span>[<span class="string">&quot;刚刚&quot;</span>,<span class="string">&quot;片刻后&quot;</span>];<span class="keyword">var</span> n=a[~~(t/<span class="number">2</span>)];<span class="keyword">return</span>[e+<span class="string">&quot; &quot;</span>+n+<span class="string">&quot;前&quot;</span>,e+<span class="string">&quot; &quot;</span>+n+<span class="string">&quot;后&quot;</span>]&#125;),e.<span class="property">cancel</span>=<span class="keyword">function</span>(<span class="params">e</span>)&#123;e?<span class="title function_">v</span>(<span class="title function_">h</span>(e)):<span class="title class_">Object</span>.<span class="title function_">keys</span>(p).<span class="title function_">forEach</span>(v)&#125;,e.<span class="property">format</span>=<span class="keyword">function</span>(<span class="params">e,t,n</span>)&#123;<span class="keyword">return</span> <span class="title function_">d</span>(<span class="title function_">l</span>(e,n&amp;&amp;n.<span class="property">relativeDate</span>),<span class="title function_">i</span>(t))&#125;,e.<span class="property">register</span>=t,e.<span class="property">render</span>=<span class="keyword">function</span>(<span class="params">e,t,n</span>)&#123;<span class="keyword">var</span> r=e.<span class="property">length</span>?<span class="attr">e</span>:[e];<span class="keyword">return</span> r.<span class="title function_">forEach</span>(<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="title function_">m</span>(e,e.<span class="title function_">getAttribute</span>(<span class="string">&quot;datetime&quot;</span>),<span class="title function_">i</span>(t),n||&#123;&#125;)&#125;),r&#125;,<span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(e,<span class="string">&quot;__esModule&quot;</span>,&#123;<span class="attr">value</span>:!<span class="number">0</span>&#125;)&#125;);</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>最后，md 文件引用的 <code>BBtalk.js</code> 代码如下，放到 <code>source/js/</code> 目录下（其他位置也可，记得修改 md 中地址）：  </p><figure class="highlight js"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> bbtalk = &#123;</span><br><span class="line">  <span class="attr">limit</span>: <span class="number">12</span>,</span><br><span class="line">  <span class="attr">bbtalk_name</span>: <span class="string">&#x27;夜的第八章&#x27;</span>,</span><br><span class="line">  <span class="attr">bbtalk_avatar</span>: <span class="string">&#x27;/img/gl.jpg&#x27;</span>,</span><br><span class="line">  <span class="attr">bbtalk_avatar_svg</span>: <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 512 512&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; class=&quot;is-badge&quot;&gt;&lt;path d=&quot;m512 268c0 17.9-4.3 34.5-12.9 49.7s-20.1 27.1-34.6 35.4c.4 2.7.6 6.9.6 12.6 0 27.1-9.1 50.1-27.1 69.1-18.1 19.1-39.9 28.6-65.4 28.6-11.4 0-22.3-2.1-32.6-6.3-8 16.4-19.5 29.6-34.6 39.7-15 10.2-31.5 15.2-49.4 15.2-18.3 0-34.9-4.9-49.7-14.9-14.9-9.9-26.3-23.2-34.3-40-10.3 4.2-21.1 6.3-32.6 6.3-25.5 0-47.4-9.5-65.7-28.6-18.3-19-27.4-42.1-27.4-69.1 0-3 .4-7.2 1.1-12.6-14.5-8.4-26-20.2-34.6-35.4-8.5-15.2-12.8-31.8-12.8-49.7 0-19 4.8-36.5 14.3-52.3s22.3-27.5 38.3-35.1c-4.2-11.4-6.3-22.9-6.3-34.3 0-27 9.1-50.1 27.4-69.1s40.2-28.6 65.7-28.6c11.4 0 22.3 2.1 32.6 6.3 8-16.4 19.5-29.6 34.6-39.7 15-10.1 31.5-15.2 49.4-15.2s34.4 5.1 49.4 15.1c15 10.1 26.6 23.3 34.6 39.7 10.3-4.2 21.1-6.3 32.6-6.3 25.5 0 47.3 9.5 65.4 28.6s27.1 42.1 27.1 69.1c0 12.6-1.9 24-5.7 34.3 16 7.6 28.8 19.3 38.3 35.1 9.5 15.9 14.3 33.4 14.3 52.4zm-266.9 77.1 105.7-158.3c2.7-4.2 3.5-8.8 2.6-13.7-1-4.9-3.5-8.8-7.7-11.4-4.2-2.7-8.8-3.6-13.7-2.9-5 .8-9 3.2-12 7.4l-93.1 140-42.9-42.8c-3.8-3.8-8.2-5.6-13.1-5.4-5 .2-9.3 2-13.1 5.4-3.4 3.4-5.1 7.7-5.1 12.9 0 5.1 1.7 9.4 5.1 12.9l58.9 58.9 2.9 2.3c3.4 2.3 6.9 3.4 10.3 3.4 6.7-.1 11.8-2.9 15.2-8.7z&quot; fill=&quot;#1da1f2&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>,</span><br><span class="line">  <span class="attr">aplayer_js</span>: <span class="string">&#x27;//unpkg.com/aplayer@1.10.1/dist/APlayer.min.js&#x27;</span>,</span><br><span class="line">  <span class="attr">init</span>: <span class="keyword">function</span> (<span class="params">options</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">bbtalk_name</span> = options.<span class="property">bbtalk_name</span> || <span class="variable language_">this</span>.<span class="property">bbtalk_name</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">bbtalk_avatar</span> = options.<span class="property">bbtalk_avatar</span> || <span class="variable language_">this</span>.<span class="property">bbtalk_avatar</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">bbtalk_avatar_svg</span> = options.<span class="property">bbtalk_avatar_svg</span> || <span class="variable language_">this</span>.<span class="property">bbtalk_avatar_svg</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">aplayer_js</span> = options.<span class="property">aplayer_js</span> || <span class="variable language_">this</span>.<span class="property">aplayer_js</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">leaflet_css</span> = options.<span class="property">leaflet_css</span> || <span class="variable language_">this</span>.<span class="property">leaflet_css</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">leaflet_js</span> = options.<span class="property">leaflet_js</span> || <span class="variable language_">this</span>.<span class="property">leaflet_js</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">ChineseTmsProviders_js</span> = options.<span class="property">ChineseTmsProviders_js</span> || <span class="variable language_">this</span>.<span class="property">ChineseTmsProviders_js</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> bbtalkPage = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">let</span> bbtalkIsLoading = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">BBtalk_init</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> loadMoreBtn = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;load-more-btn&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> loading = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;loading&#x27;</span>);</span><br><span class="line">  <span class="keyword">const</span> bbTalkBottomTip = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;bbtalk-bottom-tip&#x27;</span>);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (!loading || !loadMoreBtn || bbtalkIsLoading) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">  bbtalkIsLoading = <span class="literal">true</span>;</span><br><span class="line">  loading.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span><br><span class="line">  loadMoreBtn.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> timestamp = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Date</span>.<span class="title function_">now</span>() / <span class="number">1000</span> / <span class="number">60</span>);</span><br><span class="line">  <span class="keyword">const</span> jsonUrl = <span class="title function_">getJsonUrl</span>(bbtalkPage, timestamp); <span class="comment">// 生成 JSON URL</span></span><br><span class="line">  <span class="comment">//console.log(&quot;bbtalkPage: &quot;,bbtalkPage)</span></span><br><span class="line"></span><br><span class="line">  <span class="title function_">fetchData</span>(jsonUrl)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function"><span class="params">data</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">renderData</span>(data); <span class="comment">// 渲染数据</span></span><br><span class="line">      <span class="keyword">const</span> info = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;p.info&#x27;</span>);</span><br><span class="line">      <span class="keyword">if</span> (info) info.<span class="property">innerHTML</span> = <span class="string">`共计发送 <span class="subst">$&#123;data.count&#125;</span> 条闪念`</span>;</span><br><span class="line">      bbtalkPage++;</span><br><span class="line">      bbtalkIsLoading = <span class="literal">false</span>;</span><br><span class="line">      loading.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">      loadMoreBtn.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span><br><span class="line">      loadMoreBtn.<span class="title function_">addEventListener</span>(<span class="string">&quot;click&quot;</span>, <span class="title class_">BBtalk</span>_init);</span><br><span class="line">      bbTalkBottomTip.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">      <span class="comment">// 检查是否还有更多数据可加载</span></span><br><span class="line">      <span class="keyword">if</span> (data.<span class="property">results</span>.<span class="property">length</span> &lt; bbtalk.<span class="property">limit</span>) &#123;</span><br><span class="line">        loadMoreBtn.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">        loading.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">        bbTalkBottomTip.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">    .<span class="title function_">catch</span>(<span class="function"><span class="params">error</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">error</span>(error);</span><br><span class="line">      bbtalkIsLoading = <span class="literal">false</span>;</span><br><span class="line">      loading.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">      loadMoreBtn.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;block&#x27;</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getJsonUrl</span>(<span class="params">page, timestamp</span>) &#123;</span><br><span class="line">  <span class="comment">// 根据当前页和时间戳生成 JSON URL</span></span><br><span class="line">  <span class="keyword">return</span> location.<span class="property">host</span> === <span class="string">&#x27;blog.guole.fun&#x27;</span></span><br><span class="line">    ? <span class="string">`https://cdn.guole.fun/json/bb-json/bbtalk_page<span class="subst">$&#123;page&#125;</span>.json?t=<span class="subst">$&#123;timestamp&#125;</span>`</span></span><br><span class="line">    : <span class="string">`/test/bbtalk_page<span class="subst">$&#123;page&#125;</span>.json?t=<span class="subst">$&#123;timestamp&#125;</span>`</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">fetchData</span>(<span class="params">url</span>) &#123;</span><br><span class="line">  <span class="comment">// 从指定 URL 获取数据并返回 JSON 格式</span></span><br><span class="line">  <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(url);</span><br><span class="line">  <span class="keyword">if</span> (!response.<span class="property">ok</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`获取数据失败: <span class="subst">$&#123;response.status&#125;</span> - <span class="subst">$&#123;response.statusText&#125;</span>`</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> response.<span class="title function_">json</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">renderData</span>(<span class="params">data</span>) &#123;</span><br><span class="line">  <span class="comment">// 渲染获取到的数据</span></span><br><span class="line">  data.<span class="property">results</span>.<span class="title function_">forEach</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> timenode = <span class="title function_">createTimenode</span>(item);</span><br><span class="line">    <span class="keyword">const</span> bbtalk = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;bbtalk&#x27;</span>);</span><br><span class="line">    <span class="keyword">if</span> (bbtalk) bbtalk.<span class="title function_">appendChild</span>(timenode);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (item.<span class="property">MsgType</span> === <span class="string">&#x27;location&#x27;</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> assets = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>);</span><br><span class="line">      assets.<span class="property">innerHTML</span> = item.<span class="property">other</span>;</span><br><span class="line">      <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(assets);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (item.<span class="property">MsgType</span> === <span class="string">&#x27;music&#x27;</span>) &#123;</span><br><span class="line">      <span class="title function_">renderMusicAPlayer</span>(item);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">createTimenode</span>(<span class="params">item</span>) &#123;</span><br><span class="line">  <span class="comment">// 创建并返回 timenode 的 DOM 元素</span></span><br><span class="line">  <span class="keyword">const</span> timenode = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;div&#x27;</span>);</span><br><span class="line">  <span class="keyword">let</span> time = <span class="title function_">formatTime</span>(item.<span class="property">createdAt</span>);</span><br><span class="line">  <span class="keyword">let</span> time_ago = timeago.<span class="title function_">format</span>(time, <span class="string">&#x27;zh_CN&#x27;</span>);</span><br><span class="line">  <span class="keyword">let</span> content = <span class="title function_">urlToLink</span>(item.<span class="property">content</span>, <span class="literal">true</span>);</span><br><span class="line">  <span class="keyword">let</span> quote = <span class="title function_">urlToLink</span>(item.<span class="property">content</span>, item.<span class="property">MsgType</span>, <span class="literal">false</span>);</span><br><span class="line">  <span class="keyword">let</span> fromColor;</span><br><span class="line">  <span class="keyword">switch</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">    <span class="keyword">case</span> item.<span class="property">from</span>.<span class="title function_">includes</span>(<span class="string">&#x27;Chrome&#x27;</span>):</span><br><span class="line">      fromColor = <span class="string">&#x27;var(--bbtalk-from-chrome)&#x27;</span>;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> item.<span class="property">from</span>.<span class="title function_">includes</span>(<span class="string">&#x27;WeChat&#x27;</span>):</span><br><span class="line">      fromColor = <span class="string">&#x27;var(--bbtalk-from-wechat)&#x27;</span>;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> item.<span class="property">from</span>.<span class="title function_">includes</span>(<span class="string">&#x27;Postman&#x27;</span>):</span><br><span class="line">      fromColor = <span class="string">&#x27;var(--bbtalk-from-postman)&#x27;</span>;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> item.<span class="property">from</span>.<span class="title function_">includes</span>(<span class="string">&#x27;Edge&#x27;</span>):</span><br><span class="line">      fromColor = <span class="string">&#x27;var(--bbtalk-from-edge)&#x27;</span>;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> item.<span class="property">from</span>.<span class="title function_">includes</span>(<span class="string">&#x27;Siri&#x27;</span>):</span><br><span class="line">      fromColor = <span class="string">&#x27;var(--bbtalk-from-siri)&#x27;</span>;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">    <span class="attr">default</span>:</span><br><span class="line">      fromColor = <span class="string">&#x27;var(--bbtalk-from-bg)&#x27;</span>;</span><br><span class="line">      <span class="keyword">break</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  timenode.<span class="property">innerHTML</span> = <span class="string">`</span></span><br><span class="line"><span class="string">    &lt;div class=&quot;card-name&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;avatar&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;img src=<span class="subst">$&#123;bbtalk.bbtalk_avatar&#125;</span> class=&quot;avatar-img no-lightbox nolazyload&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;name&quot;&gt;<span class="subst">$&#123;bbtalk.bbtalk_name&#125;</span>&lt;/div&gt;</span></span><br><span class="line"><span class="string">      <span class="subst">$&#123;bbtalk.bbtalk_avatar_svg&#125;</span></span></span><br><span class="line"><span class="string">      &lt;div class=&quot;time&quot; style=&quot;margin-left:18px;&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;p&gt;</span></span><br><span class="line"><span class="string">          &lt;time datetime=&quot;<span class="subst">$&#123;time&#125;</span>&quot; data-msg=&quot;<span class="subst">$&#123;time&#125;</span>&quot;&gt;<span class="subst">$&#123;time_ago&#125;</span>&lt;/time&gt;</span></span><br><span class="line"><span class="string">        &lt;/p&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;div class=&quot;body&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;bbtalk-content&quot;&gt;</span></span><br><span class="line"><span class="string">      <span class="subst">$&#123;content&#125;</span></span></span><br><span class="line"><span class="string">      &lt;div class=&quot;bbtalk-media&quot; id=&quot;<span class="subst">$&#123;item.objectId&#125;</span>&quot;&gt;&lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">      &lt;div class=&quot;bbtalk-bottom&quot;&gt;</span></span><br><span class="line"><span class="string">        &lt;div class=&quot;bbtalk-from&quot; style=&quot;background-color: <span class="subst">$&#123;fromColor&#125;</span>;color: var(--bbtalk-from-color)&quot;&gt;</span></span><br><span class="line"><span class="string">          &lt;span&gt;<span class="subst">$&#123;item.<span class="keyword">from</span>&#125;</span>&lt;/span&gt;</span></span><br><span class="line"><span class="string">        &lt;/div&gt;</span></span><br><span class="line"><span class="string">        &lt;a id=&quot;bbtalk-reply&quot; class=&quot;bbtalk-reply&quot; onclick=&quot;quoteComment(\`<span class="subst">$&#123;quote&#125;</span>\`)&quot;&gt;</span></span><br><span class="line"><span class="string">          &lt;i class=&quot;iconfont icon-xiaoxi4&quot;&gt;&lt;/i&gt;</span></span><br><span class="line"><span class="string">        &lt;/a&gt;</span></span><br><span class="line"><span class="string">      &lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;/div&gt;</span></span><br><span class="line"><span class="string">  `</span>;</span><br><span class="line">  timenode.<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&#x27;timenode&#x27;</span>, <span class="string">&#x27;wow&#x27;</span>, <span class="string">&#x27;animate__zoomIn&#x27;</span>);</span><br><span class="line">  <span class="keyword">return</span> timenode;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">renderMusicAPlayer</span>(<span class="params">item</span>) &#123;</span><br><span class="line">  <span class="comment">// 渲染音乐的 APlayer</span></span><br><span class="line">  <span class="keyword">let</span> lrc = <span class="string">`<span class="subst">$&#123;item.other[<span class="string">&quot;lrc&quot;</span>]&#125;</span>`</span>;</span><br><span class="line">  <span class="keyword">let</span> lrcType = <span class="number">3</span>;</span><br><span class="line">  <span class="keyword">if</span> (!lrc) &#123;</span><br><span class="line">    lrcType = <span class="number">1</span>;</span><br><span class="line">    lrc = <span class="string">&quot;[00:00.00] 暂无歌词&quot;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> aplayerCode  = <span class="string">`</span></span><br><span class="line"><span class="string">    const ap_<span class="subst">$&#123;item.objectId&#125;</span> = new APlayer(&#123;</span></span><br><span class="line"><span class="string">      container: document.getElementById(&#x27;<span class="subst">$&#123;item.objectId&#125;</span>&#x27;),</span></span><br><span class="line"><span class="string">      lrcType: <span class="subst">$&#123;lrcType&#125;</span>,</span></span><br><span class="line"><span class="string">      audio: [&#123;</span></span><br><span class="line"><span class="string">          name: &#x27;<span class="subst">$&#123;item.other[<span class="string">&quot;name&quot;</span>]&#125;</span>&#x27;,</span></span><br><span class="line"><span class="string">          artist: &#x27;<span class="subst">$&#123;item.other[<span class="string">&quot;artist&quot;</span>]&#125;</span>&#x27;,</span></span><br><span class="line"><span class="string">          url: &#x27;<span class="subst">$&#123;item.other[<span class="string">&quot;url&quot;</span>]&#125;</span>&#x27;,</span></span><br><span class="line"><span class="string">          cover: &#x27;<span class="subst">$&#123;item.other[<span class="string">&quot;cover&quot;</span>]&#125;</span>&#x27;,</span></span><br><span class="line"><span class="string">          lrc: &#x27;<span class="subst">$&#123;lrc&#125;</span>&#x27;,</span></span><br><span class="line"><span class="string">      &#125;]</span></span><br><span class="line"><span class="string">  &#125;);</span></span><br><span class="line"><span class="string">  `</span></span><br><span class="line">  <span class="keyword">const</span> assets = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>);</span><br><span class="line">  assets.<span class="property">innerHTML</span> = aplayerCode;</span><br><span class="line">  <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">`<span class="subst">$&#123;item.objectId&#125;</span>`</span>).<span class="title function_">appendChild</span>(assets);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">formatTime</span>(<span class="params">time</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> timestamp = <span class="title class_">Date</span>.<span class="title function_">parse</span>(time);</span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">isNaN</span>(timestamp)) <span class="keyword">return</span> <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> date = <span class="keyword">new</span> <span class="title class_">Date</span>(timestamp);</span><br><span class="line">  <span class="keyword">const</span> year = date.<span class="title function_">getFullYear</span>();</span><br><span class="line">  <span class="keyword">const</span> month = <span class="title function_">padStart</span>(date.<span class="title function_">getMonth</span>() + <span class="number">1</span>);</span><br><span class="line">  <span class="keyword">const</span> day = <span class="title function_">padStart</span>(date.<span class="title function_">getDate</span>());</span><br><span class="line">  <span class="keyword">const</span> hour = <span class="title function_">padStart</span>(date.<span class="title function_">getHours</span>());</span><br><span class="line">  <span class="keyword">const</span> minute = <span class="title function_">padStart</span>(date.<span class="title function_">getMinutes</span>());</span><br><span class="line">  <span class="keyword">const</span> second = <span class="title function_">padStart</span>(date.<span class="title function_">getSeconds</span>());</span><br><span class="line">  <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;year&#125;</span>-<span class="subst">$&#123;month&#125;</span>-<span class="subst">$&#123;day&#125;</span> <span class="subst">$&#123;hour&#125;</span>:<span class="subst">$&#123;minute&#125;</span>:<span class="subst">$&#123;second&#125;</span>`</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">padStart</span>(<span class="params">number</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> number.<span class="title function_">toString</span>().<span class="title function_">padStart</span>(<span class="number">2</span>, <span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">urlToLink</span>(<span class="params">str, msgType = <span class="string">&#x27;text&#x27;</span>, convertToHtml = <span class="literal">true</span></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> re = <span class="regexp">/(?&lt;!&lt;img\s+[^&gt;]*\bsrc=[&quot;&#x27;])(?&lt;!&lt;video\s+[^&gt;]*\bsrc=[&quot;&#x27;])(?&lt;!\.(png|jpe?g|webp|gif|amr|speex|mp4|ts|flv)(\?.*)?$)\bhttps?:\/\/\S+\b/g</span>;</span><br><span class="line">  <span class="keyword">const</span> re_forpic = <span class="regexp">/\bhttps?:[^:&lt;&gt;&quot;]*\/([^:&lt;&gt;&quot;]*)(\.(jpeg)|(png)|(jpg)|(webp)|(gif))/ig</span>;</span><br><span class="line">  <span class="keyword">const</span> music_type = <span class="regexp">/(&amp;songmid=)|(songid=)|(songDetail)|(\/m\/song\?)|(cdn\.guole\.fun\/mp3\/)/g</span>;</span><br><span class="line">  <span class="keyword">const</span> reVideo = <span class="regexp">/\bhttps?:[^:&lt;&gt;&quot;]*\/([^:&lt;&gt;&quot;]*)(\.(mp4)|(ts)|(flv))/ig</span>;</span><br><span class="line">  <span class="keyword">const</span> reMap = <span class="regexp">/(&lt;div[^&gt;]*&gt;(.*?)&lt;\/div&gt;|&lt;\/div&gt;)/i</span>s;</span><br><span class="line">  <span class="keyword">const</span> lineBreak = <span class="regexp">/&lt;br&gt;/g</span>;</span><br><span class="line">  <span class="keyword">const</span> html = <span class="regexp">/&lt;[^&gt;]+&gt;/g</span>;</span><br><span class="line">  <span class="keyword">const</span> tencet = <span class="regexp">/y\.qq\.com/g</span>;</span><br><span class="line">  <span class="keyword">const</span> netease = <span class="regexp">/y\.music\.163\.com/g</span>;</span><br><span class="line">  <span class="keyword">const</span> urlRegex = <span class="regexp">/((http?s):\/\/[-A-Za-z0-9+&amp;@#/%?=~_|!:,.;]+[-A-Za-z0-9+&amp;@#/%=~_|])/g</span>;</span><br><span class="line">  <span class="keyword">let</span> type, server, song_id;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (convertToHtml) &#123;</span><br><span class="line">    str = str.<span class="title function_">replace</span>(re_forpic, <span class="function"><span class="params">url</span> =&gt;</span> <span class="string">`&lt;a href=&quot;<span class="subst">$&#123;url&#125;</span>&quot; target=&quot;_blank&quot; data-fancybox=&quot;group&quot; class=&quot;fancybox&quot;&gt;&lt;img src=&quot;<span class="subst">$&#123;url&#125;</span>&quot; data-lazy-src=&quot;<span class="subst">$&#123;url&#125;</span>&quot;&gt;&lt;/a&gt;`</span>)</span><br><span class="line">      .<span class="title function_">replace</span>(reVideo, <span class="function"><span class="params">url</span> =&gt;</span> <span class="string">`&lt;video src=&quot;<span class="subst">$&#123;url&#125;</span>&quot; controls&gt;&lt;/video&gt;`</span>)</span><br><span class="line">    <span class="comment">//.replace(re, url =&gt; `&lt;a href=&#x27;$&#123;url&#125;&#x27; rel=&#x27;noopener noreferrer&#x27; target=&#x27;_blank&#x27;&gt;外部链接&lt;/a&gt;`);</span></span><br><span class="line">    <span class="keyword">if</span> (tencet.<span class="title function_">test</span>(str) || netease.<span class="title function_">test</span>(str)) &#123;</span><br><span class="line">      <span class="keyword">let</span> url = str.<span class="title function_">match</span>(urlRegex)[<span class="number">0</span>];</span><br><span class="line">      url = <span class="keyword">new</span> <span class="title function_">URL</span>(str);</span><br><span class="line">      <span class="keyword">const</span> urlPath = url.<span class="property">pathname</span>;</span><br><span class="line">      <span class="keyword">const</span> urlParams = <span class="keyword">new</span> <span class="title class_">URLSearchParams</span>(url.<span class="property">search</span>);</span><br><span class="line">      type = urlPath.<span class="title function_">includes</span>(<span class="string">&quot;playlist&quot;</span>) || urlPath.<span class="title function_">includes</span>(<span class="string">&quot;details&quot;</span>) ? <span class="string">&quot;playlist&quot;</span> : <span class="string">&quot;song&quot;</span>;</span><br><span class="line">      server = url.<span class="property">host</span> === <span class="string">&quot;i.y.qq.com&quot;</span> ? <span class="string">&quot;tencent&quot;</span> : <span class="string">&quot;netease&quot;</span>;</span><br><span class="line">      song_id = urlParams.<span class="title function_">get</span>(<span class="string">&quot;songid&quot;</span>) || urlParams.<span class="title function_">get</span>(<span class="string">&quot;songmid&quot;</span>) || urlParams.<span class="title function_">get</span>(<span class="string">&quot;id&quot;</span>);</span><br><span class="line">      str = <span class="string">`&lt;meting-js server=&quot;<span class="subst">$&#123;server&#125;</span>&quot; type=&quot;<span class="subst">$&#123;type&#125;</span>&quot; id=&quot;<span class="subst">$&#123;song_id&#125;</span>&quot;&gt;&lt;/meting-js&gt;`</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">qqWechatEmotionParser</span>) &#123;</span><br><span class="line">      str = <span class="title function_">qqWechatEmotionParser</span>(str);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (music_type.<span class="title function_">test</span>(str)) &#123;</span><br><span class="line">      str = str.<span class="title function_">replace</span>(re, <span class="string">&quot; [音乐]&quot;</span>);</span><br><span class="line">      <span class="keyword">if</span> (msgType === <span class="string">&quot;music&quot;</span>) str = str + <span class="string">&quot; [音乐]&quot;</span> ;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      str = str.<span class="title function_">replace</span>(re_forpic, <span class="string">&quot; [图片]&quot;</span>)</span><br><span class="line">      .<span class="title function_">replace</span>(reVideo, <span class="string">&quot; [视频]&quot;</span>)</span><br><span class="line">      .<span class="title function_">replace</span>(reMap, <span class="string">&quot; [位置]&quot;</span>)</span><br><span class="line">      .<span class="title function_">replace</span>(re, <span class="string">&quot; [外部链接]&quot;</span>)</span><br><span class="line">      .<span class="title function_">replace</span>(lineBreak, <span class="string">&quot;&quot;</span>)</span><br><span class="line">      .<span class="title function_">replace</span>(html, <span class="string">&quot;&quot;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> str;</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">function</span> <span class="title function_">quoteComment</span>(<span class="params">txt</span>) &#123;</span><br><span class="line">  <span class="comment">//rm.hideRightMenu();</span></span><br><span class="line">  <span class="keyword">let</span> input = <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&#x27;el-textarea__inner&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">  <span class="keyword">let</span> evt = <span class="keyword">new</span> <span class="title class_">Event</span>(<span class="string">&#x27;input&#x27;</span>, &#123;</span><br><span class="line">    <span class="attr">bubbles</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">cancelable</span>: <span class="literal">true</span></span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">let</span> inputValue = <span class="title function_">replaceAll</span>(txt, <span class="string">&#x27;\n&#x27;</span>, <span class="string">&#x27;\n&gt; &#x27;</span>)</span><br><span class="line">  input.<span class="property">value</span> = <span class="string">&#x27;&gt; &#x27;</span> + inputValue + <span class="string">&#x27;\n\n&#x27;</span>;</span><br><span class="line">  input.<span class="title function_">dispatchEvent</span>(evt);</span><br><span class="line">  <span class="keyword">let</span> domTop = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&quot;#post-comment&quot;</span>).<span class="property">offsetTop</span>;</span><br><span class="line">  <span class="variable language_">window</span>.<span class="title function_">scrollTo</span>(<span class="number">0</span>, domTop - <span class="number">80</span>);</span><br><span class="line">  input.<span class="title function_">focus</span>();</span><br><span class="line">  input.<span class="title function_">setSelectionRange</span>(-<span class="number">1</span>, -<span class="number">1</span>);</span><br><span class="line">  <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;comment-tips&quot;</span>)) &#123;</span><br><span class="line">    <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;comment-tips&quot;</span>).<span class="property">style</span>.<span class="property">display</span> = <span class="string">&quot;flex&quot;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;pjax:complete&quot;</span>, (<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">  bbtalkPage = <span class="number">1</span>;</span><br><span class="line">  <span class="title class_">BBtalk</span>_init();</span><br><span class="line">&#125;));</span><br><span class="line"></span><br><span class="line"><span class="title class_">BBtalk</span>_init();</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h1 id="首页轮播说说"><a href="#首页轮播说说" class="headerlink" title="首页轮播说说"></a>首页轮播说说</h1><p>自定义或放到其他能全局引入的 js 文件里都可以，代码如下：  </p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">js实现</button><button type="button" class="tab">源码 Pug 修改</button><button type="button" class="tab">css样式</button></div><div class="tab-contents"><div class="tab-item-content active"><figure class="highlight js"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//- Guo Le&#x27;s Blog</span></span><br><span class="line"><span class="comment">//- https://guole.fun/</span></span><br><span class="line"><span class="comment">//- 2023.5.10</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//首页轮播闪念</span></span><br><span class="line"><span class="keyword">var</span> pathInfo = <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">pathname</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">bbtalkBanner</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> talkList = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;bbtalk-list&#x27;</span>);</span><br><span class="line">  <span class="keyword">let</span> bbtalkLoading = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;bbtalk-loading&#x27;</span>);</span><br><span class="line">  <span class="keyword">let</span> bbtalkRight = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;bbtalk-right&#x27;</span>);</span><br><span class="line">  <span class="keyword">if</span> (pathInfo === <span class="string">&#x27;/&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (talkList) &#123;</span><br><span class="line">      <span class="keyword">const</span> timestamp = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Date</span>.<span class="title function_">now</span>() / <span class="number">1000</span> / <span class="number">60</span>);</span><br><span class="line">      <span class="keyword">let</span> jsonUrl;</span><br><span class="line">      <span class="keyword">if</span> (location.<span class="property">host</span> === <span class="string">&#x27;blog.guole.fun&#x27;</span>) &#123;</span><br><span class="line">        jsonUrl = <span class="string">`https://cdn.guole.fun/json/bb-json/bbtalk_page1.json?t=<span class="subst">$&#123;timestamp&#125;</span>`</span>;</span><br><span class="line">        <span class="comment">//jsonUrl = &#x27;https://api.guole.fun/bbtalk?page=1&amp;limit=10&#x27;;</span></span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        jsonUrl = <span class="string">`/test/bbtalk_page1.json?t=<span class="subst">$&#123;timestamp&#125;</span>`</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">let</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">      xhr.<span class="title function_">open</span>(<span class="string">&#x27;GET&#x27;</span>, jsonUrl, <span class="literal">true</span>);</span><br><span class="line">      xhr.<span class="property">onreadystatechange</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (xhr.<span class="property">readyState</span> === <span class="number">4</span> &amp;&amp; xhr.<span class="property">status</span> === <span class="number">200</span>) &#123;</span><br><span class="line">          <span class="keyword">let</span> res = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(xhr.<span class="property">responseText</span>);</span><br><span class="line">          <span class="keyword">let</span> bberHtml = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">          res.<span class="property">results</span>.<span class="title function_">forEach</span>(<span class="keyword">function</span> (<span class="params">item, i</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> d = <span class="keyword">new</span> <span class="title class_">Date</span>(item.<span class="property">createdAt</span>);</span><br><span class="line">            <span class="keyword">const</span> date = d.<span class="title function_">getFullYear</span>() + <span class="string">&#x27;/&#x27;</span> + (d.<span class="title function_">getMonth</span>() + <span class="number">1</span>) + <span class="string">&#x27;/&#x27;</span> + d.<span class="title function_">getDate</span>() + <span class="string">&#x27; &#x27;</span> + d.<span class="title function_">getHours</span>() + <span class="string">&#x27;:&#x27;</span> + d.<span class="title function_">getMinutes</span>() + <span class="string">&#x27;:&#x27;</span> + d.<span class="title function_">getSeconds</span>();</span><br><span class="line">            <span class="keyword">const</span> dataTime = timeago.<span class="title function_">format</span>(date, <span class="string">&#x27;zh_CN&#x27;</span>);</span><br><span class="line">            <span class="keyword">const</span> newdataTime = <span class="string">&#x27;&lt;span class=&quot;datatime&quot;&gt;&#x27;</span> + dataTime + <span class="string">&#x27;&lt;/span&gt;&#x27;</span>;</span><br><span class="line">            bberHtml += <span class="string">&#x27;&lt;li class=&quot;bbtalk-list item-&#x27;</span> + (i + <span class="number">1</span>) + <span class="string">&#x27;&quot;&gt;&lt;a href=&quot;/bb&quot; style=&quot;color: var(--font-color);/*font-weight: normal;*/&quot;&gt;&#x27;</span> + newdataTime + <span class="string">&#x27;： &#x27;</span> + <span class="title function_">urlToLink</span>(item.<span class="property">content</span>,item.<span class="property">MsgType</span>) + <span class="string">&#x27;&lt;/a&gt;&lt;/li&gt;&#x27;</span>;</span><br><span class="line">          &#125;);</span><br><span class="line">          bbtalkLoading.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;none&#x27;</span>;</span><br><span class="line">          <span class="keyword">if</span> (bbtalkLoading) bbtalkLoading.<span class="title function_">remove</span>();</span><br><span class="line">          bbtalkRight.<span class="property">style</span>.<span class="property">display</span> = <span class="string">&#x27;unset&#x27;</span>;</span><br><span class="line">          talkList.<span class="title function_">insertAdjacentHTML</span>(<span class="string">&#x27;beforeend&#x27;</span>, bberHtml);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;;</span><br><span class="line">      xhr.<span class="title function_">send</span>();</span><br><span class="line"></span><br><span class="line">      <span class="keyword">function</span> <span class="title function_">urlToLink</span>(<span class="params">str,MsgType</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> imgTag = <span class="regexp">/(&lt;br&gt;)|([[\s\S]*])|(\()|(\))/g</span>;</span><br><span class="line">        <span class="keyword">const</span> reForImg = <span class="regexp">/\&lt;[img|IMG].*?src=[\&#x27;|\&quot;](https\:\/\/.*?(?:[\.jpg|\.jpeg|\.png|\.gif|\.bmp]))[\&#x27;|\&quot;].*?[\/]?&gt;/g</span>;</span><br><span class="line">        <span class="keyword">const</span> music = <span class="regexp">/(y.qq.com)|(music.163.com)/g</span>;</span><br><span class="line">        <span class="keyword">const</span> musicUrl = <span class="regexp">/[a-zA-z]+:\/\/[^\s]*/g</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (music.<span class="title function_">test</span>(str)) &#123;</span><br><span class="line">          str = str.<span class="title function_">replace</span>(musicUrl, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1024 1024&quot; width=&quot;16&quot; height=&quot;16&quot;&gt;&lt;path d=&quot;M960 0H1024v736c0 88.3712-100.283733 160-224 160S576 824.3712 576 736s100.283733-160 224-160c62.685867 0 119.3472 18.397867 160 48.042667V256l-512 113.783467v494.216533c0 88.3712-100.283733 160-224 160S0 952.3712 0 864s100.283733-160 224-160c62.685867 0 119.3472 18.397867 160 48.042667V128L960 0z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">          &#125;);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="keyword">if</span> (<span class="title class_">MsgType</span> === <span class="string">&quot;music&quot;</span>) &#123;</span><br><span class="line">            str = str + <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1024 1024&quot; width=&quot;16&quot; height=&quot;16&quot;&gt;&lt;path d=&quot;M960 0H1024v736c0 88.3712-100.283733 160-224 160S576 824.3712 576 736s100.283733-160 224-160c62.685867 0 119.3472 18.397867 160 48.042667V256l-512 113.783467v494.216533c0 88.3712-100.283733 160-224 160S0 952.3712 0 864s100.283733-160 224-160c62.685867 0 119.3472 18.397867 160 48.042667V128L960 0z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">            <span class="keyword">return</span> str;</span><br><span class="line">          &#125;  </span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        str = str.<span class="title function_">replace</span>(reForImg, <span class="string">&#x27;$1&#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> reForMd = <span class="regexp">/^!\[(.*)\]\((.*)\)/g</span>;</span><br><span class="line">        str = str.<span class="title function_">replace</span>(reForMd, <span class="string">&#x27;$2&#x27;</span>);</span><br><span class="line">        str = str.<span class="title function_">replace</span>(imgTag, <span class="string">&#x27;&#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> re = <span class="regexp">/\bhttps?:\/\/(?!\S+(?:jpe?g|png|bmp|gif|webp|gif|mp4))\S+/i</span>s;</span><br><span class="line">        <span class="keyword">const</span> reForPic = <span class="regexp">/\bhttps?:\/\/.*?(\.gif|\.jpe?g|\.png|\.bmp|\.webp)/i</span>s;</span><br><span class="line">        <span class="keyword">const</span> reImg = <span class="regexp">/&lt;img.*?src=&quot;(.*?)&quot;.*?&gt;/i</span>s;</span><br><span class="line">        <span class="keyword">const</span> reA = <span class="regexp">/&lt;a.*?href=&quot;(.*?)&quot;.*?&gt;.*?&lt;\/a&gt;/i</span>s;</span><br><span class="line">        <span class="keyword">const</span> reVideo = <span class="regexp">/\bhttps?:[^:&lt;&gt;&quot;]*\/([^:&lt;&gt;&quot;]*)(\.(mp4)|(ts)|(flv))/ig</span>;</span><br><span class="line">        <span class="keyword">const</span> reMap = <span class="regexp">/(&lt;div[^&gt;]*&gt;(.*?)&lt;\/div&gt;|&lt;\/div&gt;)/i</span>s;</span><br><span class="line">        <span class="keyword">let</span> count = <span class="number">0</span>;</span><br><span class="line">      </span><br><span class="line">        str = str.<span class="title function_">replace</span>(reImg, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1024 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M821.6 120.93333333H195.4c-74.1 0-134.2 60.1-134.2 134.2v492c0 74.1 60.1 134.2 134.2 134.2h626.2c74.1 0 134.2-60.1 134.2-134.2v-492c0-74.1-60.1-134.2-134.2-134.2zM251.3 255.13333333c30.9 0 55.9 25 55.9 55.9s-25 55.9-55.9 55.9-55.9-25-55.9-55.9 25-55.9 55.9-55.9z m614.6 559.1H153.3c-37.3 0-58.2-43.1-35.1-72.4L302.1 508.33333333c17.9-22.7 52.4-22.7 70.3 0l76.5 97.2 148.6-260c17.2-30.1 60.5-30.1 77.7 0L904.8 747.33333333c17 29.8-4.5 66.9-38.9 66.9z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        str = str.<span class="title function_">replace</span>(reForPic, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1024 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M821.6 120.93333333H195.4c-74.1 0-134.2 60.1-134.2 134.2v492c0 74.1 60.1 134.2 134.2 134.2h626.2c74.1 0 134.2-60.1 134.2-134.2v-492c0-74.1-60.1-134.2-134.2-134.2zM251.3 255.13333333c30.9 0 55.9 25 55.9 55.9s-25 55.9-55.9 55.9-55.9-25-55.9-55.9 25-55.9 55.9-55.9z m614.6 559.1H153.3c-37.3 0-58.2-43.1-35.1-72.4L302.1 508.33333333c17.9-22.7 52.4-22.7 70.3 0l76.5 97.2 148.6-260c17.2-30.1 60.5-30.1 77.7 0L904.8 747.33333333c17 29.8-4.5 66.9-38.9 66.9z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        str = str.<span class="title function_">replace</span>(reVideo, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1025 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M892.8 128H131.2c-19.2 0-35.2 6.4-48 22.4-12.8 12.8-19.2 32-19.2 54.4V816c0 44.8 28.8 80 67.2 80h761.6c19.2 0 35.2-6.4 48-22.4s19.2-35.2 19.2-54.4V204.8c0-41.6-32-76.8-67.2-76.8zM224 832h-51.2c-25.6 0-44.8-22.4-44.8-51.2V640h96v192z m0-256h-96V448h96v128z m0-192h-96V243.2c0-28.8 19.2-51.2 44.8-51.2H224v192z m512 32v416H288V192h448v224z m160 364.8c0 28.8-19.2 51.2-44.8 51.2H800V640h96v140.8z m0-204.8h-96V448h96v128z m0-192h-96V192h54.4c22.4 0 41.6 22.4 41.6 51.2V384z&quot; fill=&quot;#333333&quot; p-id=&quot;4200&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M444.8 627.2l144-73.6 25.6-12.8c32-16 32-41.6 0-57.6l-169.6-86.4c-16-6.4-28.8 0-28.8 16v192c0 22.4 12.8 28.8 28.8 22.4z&quot; fill=&quot;#333333&quot; p-id=&quot;4201&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        str = str.<span class="title function_">replace</span>(reA, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1025 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M333.06186 733.061768c-58.347896 52.210106-97.040127 49.051159-136.467091 9.492188l-45.156456-48.462758c-39.427988-39.541575-39.427988-103.667058 0-143.226029l193.260585-193.848986c39.426965-39.558971 103.355973-39.558971 142.78396 0l35.679617 35.794228c30.457686 30.555923 37.398772 75.762521 20.801768 112.997564l86.286202 66.040089c59.149145-59.33027 59.149145-155.517983 0-214.830857L523.162476 249.600755c-59.133795-59.33027-155.010423-59.33027-214.160591 0L44.350342 515.071965c-59.133795 59.313897-59.133795 155.50161 0 214.830857l107.08797 107.415428c59.133795 59.313897 155.026796 59.313897 214.176964 0l102.161774-105.647155-72.980151-70.034053L333.06186 733.061768zM987.196021 285.394982 880.1234 177.979554c-59.149145-59.33027-155.026796-59.33027-214.176964 0 0 0 4.223185-1.064238-57.988716 61.343113l71.113641 68.167542 31.604812-34.877345c39.427988-39.541575 103.356996-39.541575 142.78396 0l35.69599 35.8106c39.427988 39.541575 39.427988 103.667058 0 143.226029L714.818517 632.847345c-39.427988 39.541575-103.340623 39.541575-142.768611 0l-29.395494-48.462758c-61.883419-46.25344-42.865273-57.317427-37.611619-88.544639L426.548044 418.130076c-59.150168 59.33027-59.150168 155.517983 0 214.830857l107.072621 107.432825c59.149145 59.312874 155.026796 59.312874 214.176964 0l239.398392-240.166895C1071.582967 402.924769 987.196021 285.394982 987.196021 285.394982z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        str = str.<span class="title function_">replace</span>(re, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1025 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M333.06186 733.061768c-58.347896 52.210106-97.040127 49.051159-136.467091 9.492188l-45.156456-48.462758c-39.427988-39.541575-39.427988-103.667058 0-143.226029l193.260585-193.848986c39.426965-39.558971 103.355973-39.558971 142.78396 0l35.679617 35.794228c30.457686 30.555923 37.398772 75.762521 20.801768 112.997564l86.286202 66.040089c59.149145-59.33027 59.149145-155.517983 0-214.830857L523.162476 249.600755c-59.133795-59.33027-155.010423-59.33027-214.160591 0L44.350342 515.071965c-59.133795 59.313897-59.133795 155.50161 0 214.830857l107.08797 107.415428c59.133795 59.313897 155.026796 59.313897 214.176964 0l102.161774-105.647155-72.980151-70.034053L333.06186 733.061768zM987.196021 285.394982 880.1234 177.979554c-59.149145-59.33027-155.026796-59.33027-214.176964 0 0 0 4.223185-1.064238-57.988716 61.343113l71.113641 68.167542 31.604812-34.877345c39.427988-39.541575 103.356996-39.541575 142.78396 0l35.69599 35.8106c39.427988 39.541575 39.427988 103.667058 0 143.226029L714.818517 632.847345c-39.427988 39.541575-103.340623 39.541575-142.768611 0l-29.395494-48.462758c-61.883419-46.25344-42.865273-57.317427-37.611619-88.544639L426.548044 418.130076c-59.150168 59.33027-59.150168 155.517983 0 214.830857l107.072621 107.432825c59.149145 59.312874 155.026796 59.312874 214.176964 0l239.398392-240.166895C1071.582967 402.924769 987.196021 285.394982 987.196021 285.394982z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> (reMap.<span class="title function_">test</span>(str)) &#123;</span><br><span class="line">          <span class="keyword">if</span> (count === <span class="number">0</span>) &#123;</span><br><span class="line">            str = str.<span class="title function_">replace</span>(reMap, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">              <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1025 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M512 85.333333a233.386667 233.386667 0 0 0-234.666667 232.746667c0 85.333333 69.973333 185.6 207.573334 308.053333a40.96 40.96 0 0 0 54.186666 0C676.693333 503.68 746.666667 402.56 746.666667 318.08A233.386667 233.386667 0 0 0 512 85.333333z m0 448c-100.053333-91.306667-149.333333-164.266667-149.333333-215.253333a149.333333 149.333333 0 0 1 298.666666 0c0 51.626667-49.066667 124.586667-149.333333 215.253333z&quot; p-id=&quot;9700&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M933.546667 788.053333l1.92-3.84 1.28-3.84c0-1.28 0-2.56 1.066666-4.053333a33.066667 33.066667 0 0 0 0-6.613333V490.666667a42.666667 42.666667 0 0 0-85.333333 0v249.386666l-251.52 108.16-258.56-159.146666h-1.493333a14.08 14.08 0 0 0-4.053334-1.92l-3.84-1.706667h-24.32l-3.626666 1.28a15.36 15.36 0 0 0-4.266667 1.92h-1.493333L170.666667 759.68V490.666667a42.666667 42.666667 0 0 0-85.333334 0v343.466666a38.4 38.4 0 0 0 0 4.693334 24.746667 24.746667 0 0 0 0 3.84l1.28 4.053333a35.626667 35.626667 0 0 0 1.706667 4.266667 7.68 7.68 0 0 1 0 1.92 36.693333 36.693333 0 0 0 5.973333 7.893333 44.16 44.16 0 0 0 12.373334 7.466667l2.346666 1.493333a42.666667 42.666667 0 0 0 7.253334 2.773333h2.56A39.253333 39.253333 0 0 0 128 874.666667a49.066667 49.066667 0 0 0 9.6 0h2.56a38.186667 38.186667 0 0 0 6.826667-2.773334h1.493333l170.666667-94.506666 256 157.013333c1.92 0 3.84 1.493333 5.546666 2.346667a26.026667 26.026667 0 0 0 5.12 2.133333 42.666667 42.666667 0 0 0 10.453334 1.706667H597.333333a49.493333 49.493333 0 0 0 9.6-1.28l2.986667-1.066667 4.266667-1.28 298.666666-128a40.96 40.96 0 0 0 6.613334-3.84l2.986666-2.346667 3.2-2.773333a39.04 39.04 0 0 0 2.773334-3.413333l2.56-3.2z&quot; p-id=&quot;9701&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M512 320m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z&quot; p-id=&quot;9702&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">            &#125;);</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            str = str.<span class="title function_">replace</span>(reMap, <span class="string">&quot;&quot;</span>);</span><br><span class="line">          &#125;</span><br><span class="line">          count++;</span><br><span class="line">        &#125;</span><br><span class="line">        str = str.<span class="title function_">replace</span>(<span class="regexp">/\s+&lt;/g</span>, <span class="string">&#x27;&lt;&#x27;</span>);</span><br><span class="line">        <span class="keyword">return</span> str;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">bbtalkRoll</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> bbtalkLi = <span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(<span class="string">&#x27;li.bbtalk-list&#x27;</span>);</span><br><span class="line">  <span class="keyword">if</span> (bbtalkLi.<span class="property">length</span> &gt;= <span class="number">2</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> curLi = bbtalkLi[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">const</span> lastLi = bbtalkLi[bbtalkLi.<span class="property">length</span> - <span class="number">1</span>];</span><br><span class="line">    lastLi.<span class="property">parentNode</span>.<span class="title function_">insertBefore</span>(curLi, lastLi.<span class="property">nextSibling</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">setInterval</span>(bbtalkRoll, <span class="number">3000</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//pjax 兼容</span></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;pjax:complete&quot;</span>, (<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">  pathInfo = <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">pathname</span>;</span><br><span class="line">  <span class="title function_">bbtalkBanner</span>();</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;触发 pjax:complete 事件。&#x27;</span>)</span><br><span class="line">&#125;))</span><br><span class="line"></span><br><span class="line"><span class="title function_">bbtalkBanner</span>();</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>在<code>theme/Butterfly/layout/index.pug</code>中加入以下内容，icon 我用了阿里的，你可以自己换。  </p><figure class="highlight plaintext"><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">extends includes/layout.pug</span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line">  include ./includes/mixins/post-ui.pug</span><br><span class="line">  #recent-posts.recent-posts</span><br><span class="line">    #bber-talk(style=&#x27;display: flex; &#x27;)</span><br><span class="line">      a.index-talk-left(style=&quot;margin-right: 10px;cursor: pointer;&quot; href=&#x27;/bb/&#x27; title=&#x27;闪念&#x27;)</span><br><span class="line">        i.iconfont.icon-xiaoxi4(style=&#x27;font-size: 1.2rem; color: var(--guole-font-color);&#x27;)</span><br><span class="line">      ul.talk-list(style=&#x27;margin: 0; padding: 0; height: 36px; overflow: hidden; margin-bottom: -4px; transition: all 1s ease-in-out;&#x27;)</span><br><span class="line">        li.item.loading= _p(&#x27;闪念加载中…&#x27;)</span><br><span class="line">      a.index-talk-right(style=&#x27;text-align: right; position: relative; cursor: pointer; display:none&#x27; href=&#x27;/bb/&#x27; title=&#x27;查看全文&#x27;) </span><br><span class="line">        i.iconfont.icon-you(style=&quot;margin-left: 5px; font-size: 1.2rem; color: var(--font-color);&quot;)</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>css 样式随便找个地方丢进去，全局引用即可。有不对的，在本站再扒一下，太久远了 很难翻。  </p><figure class="highlight css"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 首页 bber 轮播 */</span></span><br><span class="line"><span class="selector-id">#bber-talk</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--guole-font-color);</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0.4rem</span> <span class="number">1rem</span> <span class="number">0.4rem</span> <span class="number">0.7rem</span>;</span><br><span class="line">    <span class="attribute">cursor</span>: auto;</span><br><span class="line">    <span class="attribute">display</span>: -webkit-flex;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    -webkit-<span class="attribute">align-items</span>: center;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">transition</span>: all <span class="number">0.3s</span>;</span><br><span class="line">    <span class="attribute">z-index</span>: <span class="number">10</span>;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">    <span class="comment">/* margin-top: 1rem; */</span></span><br><span class="line">    <span class="attribute">animation</span>: slide-in <span class="number">0.6s</span> <span class="number">0.4s</span> backwards;</span><br><span class="line">    <span class="attribute">will-change</span>: auto;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#e3e8f7</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line">    <span class="attribute">position</span>: -webkit-sticky;</span><br><span class="line">    <span class="attribute">position</span>: sticky;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">    <span class="selector-id">#bber-talk</span><span class="selector-pseudo">:hover</span>,</span><br><span class="line">    <span class="selector-class">.recent-post-item</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">      <span class="attribute">box-shadow</span>: <span class="built_in">var</span>(--guole-shadow-main) <span class="meta">!important</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="selector-class">.card-widget</span>,<span class="selector-class">.card-widget</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">        <span class="attribute">box-shadow</span>: <span class="built_in">var</span>(--guole-shadow-border) <span class="meta">!important</span>;</span><br><span class="line">      &#125;</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1300px</span>) &#123;</span><br><span class="line">    <span class="selector-id">#bber-talk</span> &#123;</span><br><span class="line">      <span class="attribute">margin-bottom</span>: <span class="number">1rem</span>;</span><br><span class="line">      <span class="attribute">animation</span>: slide-in <span class="number">0.6s</span> <span class="number">0s</span> backwards;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bber-talk</span><span class="selector-pseudo">:not</span>(<span class="selector-tag">a</span>) &#123;</span><br><span class="line">    <span class="attribute">font-weight</span>: bold;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-tag">svg</span> &#123;</span><br><span class="line">    <span class="attribute">fill</span>: currentColor;</span><br><span class="line">    <span class="attribute">vertical-align</span>: middle;</span><br><span class="line">    <span class="attribute">display</span>: inline;</span><br><span class="line">    <span class="attribute">margin-left</span>: <span class="number">5px</span>;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">5px</span>;</span><br><span class="line">    <span class="attribute">margin-bottom</span>: <span class="number">2px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> (<span class="attribute">any-hover</span>: <span class="attribute">hover</span>) &#123;</span><br><span class="line">    <span class="selector-id">#bber-talk</span> <span class="selector-tag">a</span><span class="selector-class">.index-talk-left</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">i</span>,</span><br><span class="line">    <span class="selector-id">#bber-talk</span> <span class="selector-tag">a</span><span class="selector-class">.index-talk-right</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">        <span class="attribute">color</span>: <span class="built_in">var</span>(--guole-theme-color) <span class="meta">!important</span>;</span><br><span class="line">        <span class="attribute">transition</span>: all <span class="number">0.3s</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">        <span class="attribute">color</span>: <span class="built_in">var</span>(--guole-theme-color) <span class="meta">!important</span>;</span><br><span class="line">        <span class="attribute">transition</span>: all .<span class="number">15s</span> ease-in-out;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span> <span class="selector-tag">li</span><span class="selector-class">.item</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">cursor</span>: pointer;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">16px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span> <span class="selector-tag">li</span> &#123;</span><br><span class="line">    <span class="attribute">list-style</span>: none;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">    <span class="attribute">text-overflow</span>: ellipsis;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h1 id="大功告成"><a href="#大功告成" class="headerlink" title="大功告成"></a>大功告成</h1><p>到这里，应该七七八八了。自己关注上面的微信号，发送以下指令绑定。<code>Binding_Key</code>是云函数配置的环境变量。  </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">/b bb,$&#123;Binding_Key&#125;</span><br></pre></td></tr></table></figure><p>假如我的<code>Binding_Key</code>环境变量中配置为<code>123456</code>（实际使用时，尽量设置复杂点啊……比如 32 位随机字符串），那么绑定的命令就是：<code>/b bb,123456</code>  </p><p><del>云函数代码中，我用了一些正则，如果换成你自己的，自行检查更新下正则内容……我大部分都是匹配 <code>cdn.guole.fun</code> 这个域名，处理一些逻辑的</del>。上传图片 &#x2F; 视频的逻辑，已抽取成环境变量，可自由配置（正则也做了环境变量导入）。如果你没有添加 自定义域名，那云函数<code>index.js</code>里不要加<code>serverURL</code>：  </p><figure class="highlight js"><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="variable constant_">AV</span>.<span class="title function_">init</span>(&#123;</span><br><span class="line">    <span class="attr">appId</span>: <span class="title class_">LeanCloud</span>_ID,</span><br><span class="line">    <span class="attr">appKey</span>: <span class="title class_">LeanCloud</span>_KEY,</span><br><span class="line">    <span class="attr">masterKey</span>: <span class="title class_">LeanCloud</span>_MasterKey,</span><br><span class="line">  <span class="comment">//serverURL: &#x27;https://leancloud.guole.fun&#x27;,</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h1 id="哔哔秘笈"><a href="#哔哔秘笈" class="headerlink" title="哔哔秘笈"></a>哔哔秘笈</h1><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><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><br><span class="line">==================</span><br><span class="line">/l 查询最近 10 条哔哔</span><br><span class="line">/l 数字 - 查询最近前几条，如 /l3</span><br><span class="line">---------------</span><br><span class="line">/a 文字 - 最新一条原内容后追加文字</span><br><span class="line">/a 数字 文字 - 第几条原内容后追加文字，如 /a3 开心！</span><br><span class="line">---------------</span><br><span class="line">/f 文字 - 最新一条原内容前插入文字</span><br><span class="line">/f 数字 文字 - 第几条原内容前插入文字，如 /f3 开心！</span><br><span class="line">---------------</span><br><span class="line">/s 关键词 - 搜索内容</span><br><span class="line">---------------</span><br><span class="line">/d 数字 - 删除第几条，如 /d2</span><br><span class="line">---------------</span><br><span class="line">/e 文字 - 编辑替换第 1 条</span><br><span class="line">/e 数字 文字 - 编辑替换第几条，如 /e2 新内容</span><br><span class="line">---------------</span><br><span class="line">/nobber - 解除绑定</span><br></pre></td></tr></table></figure><p>接下来，发条说说试试看吧。也欢迎关注我的，试试效果。  </p><details ><summary> 关注我的公众号「哔哔闪念」先行体验 </summary>              <div class='content'>              <p><img src="/img/posts/bb.png" alt="哔哔闪念"></p>              </div>            </details>]]></content>
    
    
    <summary type="html">自建不被卡脖子的云函数“说说”功能，支持位置、音乐、图片、视频、文本、卡片内容随时发布，支持 Siri 捷径。</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="踩坑笔记" scheme="https://blog.guole.fun/tags/%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>设置 iOS 上 web 以独立 App 运行时的状态栏颜色</title>
    <link href="https://blog.guole.fun/posts/53530/"/>
    <id>https://blog.guole.fun/posts/53530/</id>
    <published>2023-05-25T18:25:48.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>为网站添加<code>webApp</code>的功能，可以让网页保存在用户的桌面上，与原生<code>app</code>至少在视觉和一定的体验上，没有差异。点击访问，也能以独立应用的形态运行，且自动隐藏浏览器的菜单栏。  </p><p>要实现这个效果，只需准备一个<code>manifest</code>文件，其包含了各个尺寸的<code>icon</code>以及<code>webApp</code>启动时的闪屏背景色等等。在<code>Butterfly</code>主题中，作者已经给了通过 <code>pwa</code> 实现<code>webApp</code>的一系列教程。  </p><h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>我最近在折腾<code>HeoMusic</code>，已经部署在了<a href="https://music.guole.fun/">本站音乐</a>。我为其添加了<code>webApp</code>支持，如果你此刻使用 Chrome &#x2F; Safari 访问本篇，那可以试试浏览器工具中的<code>添加到主屏幕</code>。操作后，你可以在手机桌面主屏幕发现新增一个<code>音乐</code>的应用。  </p><p>主要改动，是在创建 <code>manifest</code> 文件后，在网页<code>head</code>添加以下代码即可：  </p><figure class="highlight html"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 设置网页添加到主屏幕后的名称 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;apple-mobile-web-app-title&quot;</span> <span class="attr">content</span>=<span class="string">&quot;音乐&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 为网页启动`webApp`独立应用运行支持，同时关闭工具栏和菜单栏 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;apple-mobile-web-app-capable&quot;</span> <span class="attr">content</span>=<span class="string">&quot;yes&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 添加到主屏幕“后，全屏显示 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&#x27;apple-touch-fullscreen&#x27;</span> <span class="attr">content</span>=<span class="string">&#x27;yes&#x27;</span> &gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- Apple 特有的，设置状态栏和工具栏颜色。可以设置为 default 或 black ，默认 default 是黑色。设置为 black-translucent 时，网页内容会显示在整个屏幕 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&#x27;apple-mobile-web-app-status-bar-style&#x27;</span> <span class="attr">content</span>=<span class="string">&#x27;black-translucent&#x27;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 引用 manifest --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;manifest&quot;</span> <span class="attr">href</span>=<span class="string">&quot;/manifest.json&quot;</span> &gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 添加一些 icon 引入 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2048x2732.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2732x2048.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1668x2388.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2388x1668.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1536x2048.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2048x1536.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1668x2224.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2224x1668.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1620x2160.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2160x1620.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1290x2796.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2796x1290.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1179x2556.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2556x1179.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1248x2778.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2778x1248.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1170x2532.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2532x1170.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1125x2436.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2436x1125.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1242x2688.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2688x1242.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-828x1792.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1792x828.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1242x2208.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-2208x1242.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-750x1334.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1334x750.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-640x1136.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)&quot;</span> &gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;apple-touch-startup-image&quot;</span> <span class="attr">href</span>=<span class="string">&quot;./img/splash-1136x640.png&quot;</span></span></span><br><span class="line"><span class="tag">  <span class="attr">media</span>=<span class="string">&quot;(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)&quot;</span> &gt;</span></span><br></pre></td></tr></table></figure><p><a href="https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html">有关于 Safari 上 Apple 特定的 meta 标签定义</a></p><p>由此产生一个问题：我该如何设置<code>webApp</code>独立运行时，手机的状态栏背景色呢？查阅相关文档，多次折腾终于搞清楚了。只需在上述<code>head</code>部分，新增一条：  </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;theme-color&quot;</span> <span class="attr">id</span>=<span class="string">&#x27;status-bar-meta&#x27;</span> <span class="attr">content</span>=<span class="string">&quot;rgb(195,193,180)&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="修改-webApp-的状态栏颜色"><a href="#修改-webApp-的状态栏颜色" class="headerlink" title="修改 webApp 的状态栏颜色"></a>修改 webApp 的状态栏颜色</h2><p>可以直接指定颜色，也可以为其添加一个 <code>id</code>，以便通过 <code>js</code> 动态的修改状态栏颜色，以便适配网页此刻的背景色。  </p><p>可以这样动态修改背景色：  </p><figure class="highlight js"><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">var</span> color = ***；</span><br><span class="line"><span class="keyword">let</span> statusBarMeta = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;#status-bar-meta&#x27;</span>);</span><br><span class="line">    statusBarMeta.<span class="title function_">setAttribute</span>(<span class="string">&#x27;content&#x27;</span>, color);</span><br></pre></td></tr></table></figure><p>这样，强迫症的问题就解决了~~ 😋😋</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;为网站添加&lt;code&gt;webApp&lt;/code&gt;的功能，可以让网页保存在用户的桌面上，与原生&lt;code&gt;app&lt;/code&gt;至少在视觉和一定的体验上，没有差异。点击访问，也能以独立应用的形态运行，且自动隐藏浏览器的菜单栏。  &lt;/p&gt;
&lt;p&gt;要实现这个效果，只需准备一个&lt;c</summary>
      
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="踩坑笔记" scheme="https://blog.guole.fun/tags/%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>记录一次腾讯云网站 CDN 加速配置异常，网站无法访问的问题</title>
    <link href="https://blog.guole.fun/posts/12857/"/>
    <id>https://blog.guole.fun/posts/12857/</id>
    <published>2023-05-21T13:28:33.000Z</published>
    <updated>2026-07-30T06:28:20.261Z</updated>
    
    <content type="html"><![CDATA[<h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>昨晚我将本站博客从 <code>guole.fun</code> 切换到了 <code>blog.guole.fun</code>，原来的 <code>guole.fun</code> 搞了个个人主页。（欢迎访问：<a href="https://guole.fun/">郭乐の主页</a>  </p><p>一顿操作猛如虎，搞完<code>SSL</code>证书又是大半宿。结果，不能访问？直接访问加速域名： <code>blog.guole.fun</code> 和 <code>guole.fun</code>报错如下：  </p><figure class="highlight html"><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">This XML file does not appear to have any style information associated with it. The document tree is shown below.</span><br><span class="line"><span class="tag">&lt;<span class="name">Error</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Code</span>&gt;</span>AccessDenied<span class="tag">&lt;/<span class="name">Code</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Message</span>&gt;</span>Request has expired<span class="tag">&lt;/<span class="name">Message</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">ServerTime</span>&gt;</span>2023-05-21T05:34:34Z<span class="tag">&lt;/<span class="name">ServerTime</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Resource</span>&gt;</span>/100008941858_7a5cde20-4599-46b6-8346-c26dcf283525_smarty_CSRP2X3DG2G0.png<span class="tag">&lt;/<span class="name">Resource</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">RequestId</span>&gt;</span>NjQ2OWFkNmFfZjQzOTY4MDlfOTM3MV9hMTY3ZTQ0<span class="tag">&lt;/<span class="name">RequestId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">TraceId</span>&gt;</span>OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTQyYWVlY2QwZTk2MDVmZDQ3MmI2Y2I4ZmI5ZmM4ODFjNWUxMmVmMDg0MjBiYzY2N2E1ZWU5NDEyNzE5YjliNzg=<span class="tag">&lt;/<span class="name">TraceId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">Error</span>&gt;</span></span><br></pre></td></tr></table></figure><p>于是，找到腾讯云客服问了一通，结果告诉我要明天下午再答复我……虽然是周末，不过你们真的没有真·人工服务？（因为跟我对话的是个工具人，不能解决问题，所以不算<code>真·人工服务</code>）  </p><p>于是一通 Google ，结果还是无果。  </p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>等到第二天中午，终于联系我了。但是这个客服好像不专业，一顿输出，先说我请求带了<code>/#/</code>所以不行，拉扯半天才发现，是<code>CDN</code>源站类型配置有误。</p><p><img src="/posts/12857/11.png" alt="腾讯云客服"></p><p>直接说吧，原因是腾讯云<code>CDN</code>加速域名源站类型配错了（可是我根本没配置，是添加加速域名时的默认配置……而且，名字就叫“默认”这很合理啊，很难发现问题），调整为<code>静态网站</code>即可。 </p><p><img src="/posts/12857/22.png" alt="CDN源站类型配置"></p><p>再简单理一下，其他排查解决方法：  </p><div class="note info flat"><ol><li>确认你的<code>cos</code>源站已开启<code>静态网站</code>；腾讯云 ——&gt; 对象存储 ——&gt; ${你的网站存储桶} ——&gt; 左侧基础配置 ——&gt; 静态网站，设置<code>开启</code>，索引文档一般是<code>index.html</code>;</li><li>确认你的<code>cdn</code>已配置源站类型为<code>静态网站</code>；腾讯云 ——&gt; 内容分发网络 CDN ——&gt; 域名管理 ——&gt; ${你的网站加速域名} ——&gt; 基础配置划到底部 ——&gt; 源站信息 ——&gt; 主源站 ——&gt; 编辑，源站地址后设置为<code>静态网站</code>；</li><li>确认你的加速域名，已配置<code>SSL</code>证书；在上述 2 的页面，点击<code>HTTPS</code>配置，配置证书；</li></ol></div><p>注意，主要你能确认，网站部署到<code>cos</code>存储桶，且已开启静态网站（上述 1 路径），那就可以试着通过存储桶的源站域名访问。地址：腾讯云 ——&gt; 对象存储 ——&gt; ${你的网站存储桶} ——&gt; 左侧基础配置 ——&gt; <code>访问节点</code>，试着用这个 URL 如果能正常打开，那么 恭喜，用上述三点绝对能解决问题。  </p><p>另外，<code>SSL</code>证书，我一直在这里申请，也还简单（但是我一直申请<code>泛域名</code>证书，就一直不成功，好像原因比较复杂；用免 DNS 授权验证也不成功），推荐选择“多域名” “DNS授权模式”。  </p><p>这里还能自动部署到你的腾讯云 CDN，自动更新 SSL 证书，自动部署，还算可以。申请地址是：<a href="https://www.ohttps.com/?invitationCode=mlyxprokvo8ez6jw">OHTTP</a>  </p><p>如果还不是很清楚，见本站另一篇 SSL 证书申请指引：<a href="/posts/38768/">为你的网站添加https加密-免费申请SSL证书</a>  </p><h2 id="以下是广告时间"><a href="#以下是广告时间" class="headerlink" title="以下是广告时间"></a>以下是广告时间</h2><p>这两天，上线了几个小站，欢迎大家体验：  </p><p><a href="https://guole.fun/">郭乐の主页</a><br><a href="https://hot.guole.fun/">今日热榜-汇聚多平台热搜</a><br><a href="https://music.guole.fun/">我的音乐</a>  </p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;起因&quot;&gt;&lt;a href=&quot;#起因&quot; class=&quot;headerlink&quot; title=&quot;起因&quot;&gt;&lt;/a&gt;起因&lt;/h2&gt;&lt;p&gt;昨晚我将本站博客从 &lt;code&gt;guole.fun&lt;/code&gt; 切换到了 &lt;code&gt;blog.guole.fun&lt;/code&gt;，原来的 </summary>
      
    
    
    
    <category term="吐槽大会" scheme="https://blog.guole.fun/categories/%E5%90%90%E6%A7%BD%E5%A4%A7%E4%BC%9A/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="踩坑笔记" scheme="https://blog.guole.fun/tags/%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0/"/>
    
    <category term="沙雕互联网产品" scheme="https://blog.guole.fun/tags/%E6%B2%99%E9%9B%95%E4%BA%92%E8%81%94%E7%BD%91%E4%BA%A7%E5%93%81/"/>
    
  </entry>
  
  <entry>
    <title>前端踩坑笔记</title>
    <link href="https://blog.guole.fun/posts/41614/"/>
    <id>https://blog.guole.fun/posts/41614/</id>
    <published>2023-05-13T15:25:00.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>此处记录个人折腾博客过程中，挠掉不少头发的前端踩坑笔记。将以时间倒序更新。  </p><h2 id="首页哔哔闪念轮播字体模糊"><a href="#首页哔哔闪念轮播字体模糊" class="headerlink" title="首页哔哔闪念轮播字体模糊"></a>首页哔哔闪念轮播字体模糊</h2><p>2023.6.25 突然发现首页轮播哔哔字体怎么是糊的。排查发现是 css 样式设置的 <code>will-change</code> 属性导致的。  </p><p><strong>原因：</strong></p><p>ChatGPT：<code>will-change</code> 是 CSS3 中的一个属性，用于告诉浏览器哪些属性将要被改变，从而使浏览器在元素实际发生变化之前对其进行优化，提高页面性能。使用 <code>will-change</code> 属性可以让浏览器提前为元素做好一些优化工作，从而在元素实际发生变化时能够更快地响应。  </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">will-change 属性可以接受多个值，用逗号分隔。常用的值包括：  </span><br><span class="line">  </span><br><span class="line">auto：默认值，表示浏览器自行决定哪些属性需要被优化。  </span><br><span class="line">scroll-position：告诉浏览器元素的滚动位置将要发生变化，从而使浏览器在滚动时能够更快地响应。  </span><br><span class="line">contents：告诉浏览器元素的内容将要发生变化，从而使浏览器在元素内容发生变化时能够更快地响应。  </span><br><span class="line">transform：告诉浏览器元素的变换将要发生变化，从而使浏览器在元素变换时能够更快地响应。  </span><br><span class="line">opacity：告诉浏览器元素的透明度将要发生变化，从而使浏览器在元素透明度发生变化时能够更快地响应。  </span><br></pre></td></tr></table></figure><p>在上述问题中，之前不知道啥时候给 <code>#bbtalk</code> 添加了 <code>will-change: transition;</code> 属性，原本是想让浏览器提前准备，更好地响应。但是但该属性给纯文本添加后，就会导致模糊问题。<br><strong>解决方法：</strong></p><p>设置为 <code>will-change: auto;</code> 即可解决。  </p><figure class="highlight css"><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="selector-id">#bbtalk</span> &#123;</span><br><span class="line">  <span class="attribute">will-change</span>: auto;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="友链滚动效果——奇怪的对齐问题"><a href="#友链滚动效果——奇怪的对齐问题" class="headerlink" title="友链滚动效果——奇怪的对齐问题"></a>友链滚动效果——奇怪的对齐问题</h2><p>2023.5.14，雨天，就没出去溜达。于是乎，继续打开电脑，对<code>Heo</code>博客做<code>像素级</code>的致（chao）敬（xi）。洪哥那个友链页面，太高大上了，必须安排。  </p><p><code>html</code>结构都很简单，进行到<code>css</code>部分时，诡异的事情发生了：</p><p><img src="/posts/41614/bug.png" alt="无规律的不对齐问题"></p><p>如上图，动画基本搞出来后，发现怎么跟想象中的不一样？为什么第一排头像正常水平对齐，第二排就不行？查看有一句<code>css</code>是这样的：  </p><figure class="highlight css"><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="selector-class">.tags-group-icon-pair</span> <span class="selector-class">.tags-group-icon</span><span class="selector-pseudo">:nth-child</span>(even) &#123;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">1rem</span>;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">translate</span>(-<span class="number">60px</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这块儿是为了实现，第二排与第一排有一个水平偏移量，以及上下间距。正常实现后是很好看的：</p><p><img src="/posts/41614/heo.png" alt="Heo页面的正常效果"></p><p>查询发现，这是一个很有意思的<code>css</code>属性：</p><blockquote><p>查阅发现 <code>:nth-child()</code> 定义：<br>选择器匹配作为其<strong>父元素</strong>的第 <code>n</code>个子元素的每个元素。<code>:nth-child(n)</code><br><code>n</code>可以是数字、关键字（奇数或偶数）或公式（如<code>an + b</code>）。</p></blockquote><p>重点来了，<code>父元素</code>。而我这边渲染后的<code>html</code>结构是怎样的呢？  </p><figure class="highlight html"><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="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tags-group-icon-pair&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;tags-group-icon&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://crazywong.com/&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;noopener external nofollow&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span> <span class="attr">title</span>=<span class="string">&quot;crazywong&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;entered loading&quot;</span> <span class="attr">data-ll-status</span>=<span class="string">&quot;loaded&quot;</span> <span class="attr">src</span>=<span class="string">&quot;/img/loading22.gif&quot;</span> <span class="attr">data-lazy-src</span>=<span class="string">&quot;https://cdn.guole.fun/logo/Jerry.png&quot;</span> <span class="attr">title</span>=<span class="string">&quot;crazywong&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;img-alt is-center&quot;</span>&gt;</span>crazywong<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;tags-group-icon&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://blog.zhheo.com/&quot;</span> <span class="attr">rel</span>=<span class="string">&quot;noopener external nofollow&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span> <span class="attr">title</span>=<span class="string">&quot;张洪Heo&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;entered loading&quot;</span> <span class="attr">data-ll-status</span>=<span class="string">&quot;loaded&quot;</span> <span class="attr">src</span>=<span class="string">&quot;/img/loading22.gif&quot;</span> <span class="attr">data-lazy-src</span>=<span class="string">&quot;https://cdn.guole.fun/logo/zhheo.png&quot;</span> <span class="attr">title</span>=<span class="string">&quot;张洪Heo&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;img-alt is-center&quot;</span>&gt;</span>张洪 Heo<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p><strong>原因：</strong></p><p>原来，多了个<code>.img-alt.is-center</code>。这样一来，<code>.tags-group-icon:nth-child(even)</code> 虽然匹配到了 <code>.tags-group-icon</code> 的父元素 <code>.tags-group-icon-pair</code>，但由于此时多了个<code>.img-alt.is-center</code>子元素，导致选择<code>偶数项</code>的时候，第二排的头像并非是父元素的第<code>偶数项</code>个元素。  </p><p><strong>解决方法：</strong></p><blockquote><ol><li>由于我配置开启了 <code>Butterfly</code> 默认的 <code>图片描述功能</code>，主题的 <code>addPhotoFigcaption()</code> 方法会自动给图片添加 <code>.img-alt.is-center</code> 。查看主题源码发现，最简单就是非<code>#article-container</code> 节点，就不会添加。</li><li>于是，调整 <code>flink.pug</code> ，将首行的 <code>#article-container</code> 改成 <code>#page</code>，问题解决。</li><li>请注意，也需要一并调整 <code>flink.styl</code> 的首行，不然友链的默认样式没了。</li></ol></blockquote><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">addPhotoFigcaption() 源码</button><button type="button" class="tab">调整 fink.pug</button></div><div class="tab-contents"><div class="tab-item-content active"><figure class="highlight js"><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="comment">/**</span></span><br><span class="line"><span class="comment"> * PhotoFigcaption</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">addPhotoFigcaption</span> (<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(<span class="string">&#x27;#article-container img&#x27;</span>).<span class="title function_">forEach</span>(<span class="keyword">function</span> (<span class="params">item</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> parentEle = item.<span class="property">parentNode</span></span><br><span class="line">    <span class="keyword">const</span> altValue = item.<span class="property">title</span> || item.<span class="property">alt</span></span><br><span class="line">    <span class="keyword">if</span> (altValue &amp;&amp; !parentEle.<span class="property">parentNode</span>.<span class="property">classList</span>.<span class="title function_">contains</span>(<span class="string">&#x27;justified-gallery&#x27;</span>)) &#123;</span><br><span class="line">      <span class="keyword">const</span> ele = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;div&#x27;</span>)</span><br><span class="line">      ele.<span class="property">className</span> = <span class="string">&#x27;img-alt is-center&#x27;</span></span><br><span class="line">      ele.<span class="property">textContent</span> = altValue</span><br><span class="line">      parentEle.<span class="title function_">insertBefore</span>(ele, item.<span class="property">nextSibling</span>)</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></div><div class="tab-item-content"><figure class="highlight plaintext"><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">- #article-container</span><br><span class="line">+ #page</span><br><span class="line">    .flink</span><br><span class="line">      - let pageContent = page.content</span><br><span class="line">      if page.flink_url</span><br><span class="line">        script.</span><br><span class="line">          (()=&gt;&#123;</span><br><span class="line">            const replaceSymbol = (str) =&gt; &#123;</span><br><span class="line">              return str.replace(/[\p&#123;P&#125;\p&#123;S&#125;]/gu, &quot;-&quot;)</span><br><span class="line">          &#125;</span><br><span class="line">  ……</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="添加-box-shadow-无效"><a href="#添加-box-shadow-无效" class="headerlink" title="添加 box-shadow 无效"></a>添加 box-shadow 无效</h2><p><strong>原因：</strong></p><ol><li>其他<code>box-shadow</code>效果覆盖；</li><li>图层问题，试着添加<code>z-index: 2000;</code>验证下；</li><li>我遇到的，是由于 <code>clip-path</code> 属性导致不生效。如下，注释掉既可：</li></ol><figure class="highlight css"><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="selector-id">#category-bar</span> &#123;</span><br><span class="line">        <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line">        <span class="attribute">border</span>: <span class="built_in">var</span>(--guole-border);</span><br><span class="line">        <span class="comment">/* clip-path: inset(0 0 0 0 round 8px); */</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="transition-无效"><a href="#transition-无效" class="headerlink" title="transition 无效"></a>transition 无效</h2><p><strong>原因：</strong><br><code>transition</code> 属性无法对一个从无到有的元素进行过渡显示。设置 <code>display: none</code> 导致过渡无效。  </p><p>我在实现首页文章列表<code>hover</code>悬浮时，从底部向上浮现出文章摘要<code>content</code>时，对<code>content</code>设置了此属性：</p><figure class="highlight css"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-id">#recent-posts</span> <span class="selector-class">.recent-post-item</span> &gt; <span class="selector-class">.recent-post-info</span> &gt; <span class="selector-class">.recent-post-info-top</span> &gt; <span class="selector-class">.content</span> &#123;</span><br><span class="line">    <span class="attribute">visibility</span>: hidden;</span><br><span class="line">    -webkit-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -moz-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -o-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -ms-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    <span class="attribute">transition</span>: <span class="number">0.2s</span> linear;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">1.4</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">    -ms-<span class="attribute">filter</span>: <span class="string">&quot;progid:DXImageTransform.Microsoft.Alpha(Opacity=0)&quot;</span>;</span><br><span class="line">    <span class="attribute">filter</span>: <span class="built_in">alpha</span>(opacity=<span class="number">0</span>);</span><br><span class="line">    <span class="attribute">display</span>: none;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-id">#recent-posts</span> <span class="selector-class">.recent-post-item</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.recent-post-info</span> &gt; <span class="selector-class">.recent-post-info-top</span> &gt; <span class="selector-class">.content</span> &#123;</span><br><span class="line">    <span class="attribute">visibility</span>: visible;</span><br><span class="line">    -webkit-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -moz-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -o-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -ms-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">3s</span> linear;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">1.4</span>;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">    -ms-<span class="attribute">filter</span>: none;</span><br><span class="line">    <span class="attribute">filter</span>: none;</span><br><span class="line">    <span class="attribute">display</span>: -webkit-box;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>解决方法：</strong>  </p><blockquote><p>查阅得知：<br><code>visibility:hidden</code>的时候元素仍然存在于文档流中，同时<code>opacity:0</code>；<code>visibility:visible</code>时<code>opacity:1</code>，<code>transition</code>属性可以对在<code>opacity0～1</code>之间进行过渡。  </p></blockquote><p>因此使用<code>visibility: visible;</code>代替<code>display: none</code>既可：</p><figure class="highlight css"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-id">#recent-posts</span> <span class="selector-class">.recent-post-item</span> &gt; <span class="selector-class">.recent-post-info</span> &gt; <span class="selector-class">.recent-post-info-top</span> &gt; <span class="selector-class">.content</span> &#123;</span><br><span class="line">    <span class="attribute">visibility</span>: hidden;</span><br><span class="line">    -webkit-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -moz-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -o-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -ms-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    <span class="attribute">transition</span>: <span class="number">0.2s</span> linear;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">20px</span>;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">1.4</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">    -ms-<span class="attribute">filter</span>: <span class="string">&quot;progid:DXImageTransform.Microsoft.Alpha(Opacity=0)&quot;</span>;</span><br><span class="line">    <span class="attribute">filter</span>: <span class="built_in">alpha</span>(opacity=<span class="number">0</span>);</span><br><span class="line">    <span class="attribute">visibility</span>: visible;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-id">#recent-posts</span> <span class="selector-class">.recent-post-item</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.recent-post-info</span> &gt; <span class="selector-class">.recent-post-info-top</span> &gt; <span class="selector-class">.content</span> &#123;</span><br><span class="line">    <span class="attribute">visibility</span>: visible;</span><br><span class="line">    -webkit-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -moz-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -o-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    -ms-<span class="attribute">transition</span>: <span class="number">0.3s</span> linear;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">3s</span> linear;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">1.4</span>;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">    -ms-<span class="attribute">filter</span>: none;</span><br><span class="line">    <span class="attribute">filter</span>: none;</span><br><span class="line">    <span class="attribute">display</span>: -webkit-box;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;此处记录个人折腾博客过程中，挠掉不少头发的前端踩坑笔记。将以时间倒序更新。  &lt;/p&gt;
&lt;h2 id=&quot;首页哔哔闪念轮播字体模糊&quot;&gt;&lt;a href=&quot;#首页哔哔闪念轮播字体模糊&quot; class=&quot;headerlink&quot; title=&quot;首页哔哔闪念轮播字体模糊&quot;&gt;&lt;/a&gt;首页哔</summary>
      
    
    
    
    <category term="前端知识" scheme="https://blog.guole.fun/categories/%E5%89%8D%E7%AB%AF%E7%9F%A5%E8%AF%86/"/>
    
    
    <category term="踩坑笔记" scheme="https://blog.guole.fun/tags/%E8%B8%A9%E5%9D%91%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>Heo动态分类条增强：关联任意自定义页面+配置化</title>
    <link href="https://blog.guole.fun/posts/13386/"/>
    <id>https://blog.guole.fun/posts/13386/</id>
    <published>2023-05-10T17:05:34.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>闲了好一阵子，最近突来兴趣，再扒<code>洪哥</code>的博客。  </p><p>关于页面动态分类条，<code>洪哥</code>早已提供教程（<a href="https://blog.zhheo.com/p/bc61964d.html#">HEO：Butterfly魔改动态分类条</a>）。本文主要分享，在此基础上增强支持自定义页面的心得（原版只支持“分类”）。  </p><p>注意看，<code>小游戏</code>这个内容（path为<code>/game/</code>）并非分类或子分类，而是我自定义的一个页面，包含了一些自部署的趣味游戏。原本<code>洪哥</code>的方法，在<code>小游戏</code>页面是无法展示上述“分类条”的，点击进入这个页面后，分类条上的<code>小游戏</code>也无法自动高亮。所以，以下为个人再次魔改内容。  </p><h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><p><img src="/posts/13386/2.png" alt="动态分类条"></p><h2 id="实现方式"><a href="#实现方式" class="headerlink" title="实现方式"></a>实现方式</h2><h3 id="新建categoryBar-pug"><a href="#新建categoryBar-pug" class="headerlink" title="新建categoryBar.pug"></a>新建categoryBar.pug</h3><p>在<code>洪哥</code>版本上，调整为配置化，方便随时修改。不然老去改源码有点不优雅。新建以下文件：<code>themes/butterfly/layout/includes/categoryBar.pug</code> ，内容如下：</p><figure class="highlight js"><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">if</span> theme.<span class="property">DynamicCategoryBar</span>.<span class="property">enable</span> &amp;&amp; theme.<span class="property">DynamicCategoryBar</span>.<span class="property">category</span> !== <span class="literal">undefined</span> </span><br><span class="line">    #category-bar</span><br><span class="line">        .<span class="property">category</span>-bar-items#category-bar-items</span><br><span class="line">            each item <span class="keyword">in</span> theme.<span class="property">DynamicCategoryBar</span>.<span class="property">category</span></span><br><span class="line">                <span class="keyword">if</span> (item.<span class="property">name</span> == <span class="literal">undefined</span> || item.<span class="property">id</span> == <span class="literal">undefined</span> || item.<span class="property">url</span> == <span class="literal">undefined</span>)</span><br><span class="line">                    - <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;DynamicCategoryBar：当前存在某项配置异常，已跳过其渲染（配置指引：https://blog.guole.fun/posts/13386/）&#x27;</span>)</span><br><span class="line">                <span class="keyword">else</span> </span><br><span class="line">                    .<span class="property">category</span>-bar-<span class="title function_">item</span>(id=item.<span class="property">id</span>)</span><br><span class="line">                        <span class="title function_">a</span>(href=item.<span class="property">url</span>)= <span class="title function_">_p</span>(item.<span class="property">name</span>)</span><br><span class="line">        #category-bar-next.<span class="property">category</span>-bar-<span class="title function_">next</span>(onclick=<span class="string">&quot;scrollCategoryBarToRight()&quot;</span>)</span><br><span class="line">            <span class="comment">//- i.fa-solid</span></span><br><span class="line">        a.<span class="property">category</span>-bar-<span class="title function_">more</span>(href=<span class="string">&quot;/categories/&quot;</span>)= <span class="title function_">_p</span>(<span class="string">&#x27;更多&#x27;</span>)</span><br></pre></td></tr></table></figure><h3 id="引用模板"><a href="#引用模板" class="headerlink" title="引用模板"></a>引用模板</h3><p>在<code>themes/butterfly/layout/index.pug</code>文件中，<code>+postUI</code>上新增一行内容<code>include includes/categoryBar.pug</code>，注意缩进。  </p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">新增内容</button><button type="button" class="tab">完整内容</button></div><div class="tab-contents"><div class="tab-item-content active"><p>注意缩进呀~</p><figure class="highlight js"><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">+   include includes/categoryBar.<span class="property">pug</span></span><br><span class="line">    +postUI</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight js"><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="keyword">extends</span> includes/layout.<span class="property">pug</span></span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line">  include ./includes/mixins/post-ui.<span class="property">pug</span></span><br><span class="line">  #recent-posts.<span class="property">recent</span>-posts</span><br><span class="line">    include includes/categoryBar.<span class="property">pug</span></span><br><span class="line">    +postUI</span><br><span class="line">    include includes/pagination.<span class="property">pug</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>在<code>themes/butterfly/layout/category.pug</code>文件中，<code>#category</code>下新增以下内容：</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">新增内容</button><button type="button" class="tab">完整内容</button></div><div class="tab-contents"><div class="tab-item-content active"><figure class="highlight js"><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="property">category</span>-<span class="keyword">in</span>-bar</span><br><span class="line">  .<span class="property">category</span>-<span class="keyword">in</span>-bar-tips</span><br><span class="line">    | 分类</span><br><span class="line">  include includes/categoryBar.<span class="property">pug</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">extends</span> includes/layout.<span class="property">pug</span></span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line">  <span class="keyword">if</span> theme.<span class="property">category_ui</span> == <span class="string">&#x27;index&#x27;</span></span><br><span class="line">    include ./includes/mixins/post-ui.<span class="property">pug</span></span><br><span class="line">    #recent-posts.<span class="property">recent</span>-posts.<span class="property">category_ui</span></span><br><span class="line">      +postUI</span><br><span class="line">      include includes/pagination.<span class="property">pug</span></span><br><span class="line">  <span class="keyword">else</span></span><br><span class="line">    include ./includes/mixins/article-sort.<span class="property">pug</span></span><br><span class="line">    #category</span><br><span class="line">      .<span class="property">category</span>-<span class="keyword">in</span>-bar</span><br><span class="line">        .<span class="property">category</span>-<span class="keyword">in</span>-bar-tips</span><br><span class="line">          | 分类</span><br><span class="line">        include includes/categoryBar.<span class="property">pug</span></span><br><span class="line">      .<span class="property">article</span>-sort-title= <span class="title function_">_p</span>(<span class="string">&#x27;page.category&#x27;</span>) + <span class="string">&#x27; - &#x27;</span> + page.<span class="property">category</span></span><br><span class="line">      +<span class="title function_">articleSort</span>(page.<span class="property">posts</span>)</span><br><span class="line">      include includes/pagination.<span class="property">pug</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h4 id="继续引用"><a href="#继续引用" class="headerlink" title="继续引用"></a>继续引用</h4><p>编辑<code>themes/butterfly/layout/page.pug</code>文件，主要是实现了<code>关联任意自定义页面</code>：</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">新增内容</button><button type="button" class="tab">纯净版</button></div><div class="tab-contents"><div class="tab-item-content active"><figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">extends</span> includes/layout.<span class="property">pug</span></span><br><span class="line"> </span><br><span class="line">block content</span><br><span class="line">  #page</span><br><span class="line">+   <span class="keyword">if</span> (page.<span class="property">type</span> == <span class="string">&#x27;categoryBar&#x27;</span>)</span><br><span class="line">+     #category</span><br><span class="line">+       .<span class="property">category</span>-<span class="keyword">in</span>-bar</span><br><span class="line">+         .<span class="property">category</span>-<span class="keyword">in</span>-bar-tips</span><br><span class="line">+           | 分类</span><br><span class="line">+         include includes/categoryBar.<span class="property">pug</span></span><br><span class="line">    <span class="keyword">if</span> top_img === <span class="literal">false</span></span><br><span class="line">      h1.<span class="property">page</span>-title= page.<span class="property">title</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">case</span> page.<span class="property">type</span></span><br><span class="line">      when <span class="string">&#x27;tags&#x27;</span></span><br><span class="line">        include includes/page/tags.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;link&#x27;</span></span><br><span class="line">        include includes/page/flink.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;categories&#x27;</span></span><br><span class="line">        include includes/page/categories.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;about&#x27;</span></span><br><span class="line">        include includes/page/about.<span class="property">pug</span></span><br><span class="line">+     when <span class="string">&#x27;categoryBar&#x27;</span></span><br><span class="line">+       include includes/page/<span class="keyword">default</span>-page.<span class="property">pug</span></span><br><span class="line">      <span class="keyword">default</span></span><br><span class="line">        include includes/page/<span class="keyword">default</span>-page.<span class="property">pug</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> page.<span class="property">comments</span> !== <span class="literal">false</span> &amp;&amp; theme.<span class="property">comments</span> &amp;&amp; theme.<span class="property">comments</span>.<span class="property">use</span></span><br><span class="line">      - <span class="keyword">var</span> commentsJsLoad = <span class="literal">true</span></span><br><span class="line">      !=<span class="title function_">partial</span>(<span class="string">&#x27;includes/third-party/comments/index&#x27;</span>, &#123;&#125;, &#123;<span class="attr">cache</span>: <span class="literal">true</span>&#125;)</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">extends</span> includes/layout.<span class="property">pug</span></span><br><span class="line"> </span><br><span class="line">block content</span><br><span class="line">  #page</span><br><span class="line">    <span class="keyword">if</span> (page.<span class="property">type</span> == <span class="string">&#x27;categoryBar&#x27;</span>)</span><br><span class="line">      #category</span><br><span class="line">        .<span class="property">category</span>-<span class="keyword">in</span>-bar</span><br><span class="line">          .<span class="property">category</span>-<span class="keyword">in</span>-bar-tips</span><br><span class="line">            | 分类</span><br><span class="line">          include includes/categoryBar.<span class="property">pug</span></span><br><span class="line">    <span class="keyword">if</span> top_img === <span class="literal">false</span></span><br><span class="line">      h1.<span class="property">page</span>-title= page.<span class="property">title</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">case</span> page.<span class="property">type</span></span><br><span class="line">      when <span class="string">&#x27;tags&#x27;</span></span><br><span class="line">        include includes/page/tags.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;link&#x27;</span></span><br><span class="line">        include includes/page/flink.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;categories&#x27;</span></span><br><span class="line">        include includes/page/categories.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;about&#x27;</span></span><br><span class="line">        include includes/page/about.<span class="property">pug</span></span><br><span class="line">      when <span class="string">&#x27;categoryBar&#x27;</span></span><br><span class="line">        include includes/page/<span class="keyword">default</span>-page.<span class="property">pug</span></span><br><span class="line">      <span class="keyword">default</span></span><br><span class="line">        include includes/page/<span class="keyword">default</span>-page.<span class="property">pug</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> page.<span class="property">comments</span> !== <span class="literal">false</span> &amp;&amp; theme.<span class="property">comments</span> &amp;&amp; theme.<span class="property">comments</span>.<span class="property">use</span></span><br><span class="line">      - <span class="keyword">var</span> commentsJsLoad = <span class="literal">true</span></span><br><span class="line">      !=<span class="title function_">partial</span>(<span class="string">&#x27;includes/third-party/comments/index&#x27;</span>, &#123;&#125;, &#123;<span class="attr">cache</span>: <span class="literal">true</span>&#125;)</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="配置自定义页面"><a href="#配置自定义页面" class="headerlink" title="配置自定义页面"></a>配置自定义页面</h3><p>若某个页面想添加进分类条（非分类页），则需要在其<code>.md</code>文件头，设置<code>type: categoryBar</code>。这样就能自动把分类条插入进去渲染了。  </p><p>比如，我的<code>/game/index.md</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></pre></td><td class="code"><pre><span class="line">title: 休闲小游戏</span><br><span class="line">date: 2023-01-09 11:01:05</span><br><span class="line">top<span class="emphasis">_img: false</span></span><br><span class="line"><span class="emphasis">type: &quot;categoryBar&quot;</span></span><br></pre></td></tr></table></figure><h3 id="新建js"><a href="#新建js" class="headerlink" title="新建js"></a>新建js</h3><p>如果你还没有独立的自定义<code>js</code>文件，可以考虑新建一个，建议放到<code>root/source/js/</code>（root为你的blog项目根目录）。随后，在<code>_config.butterfly.yml</code>的<code>inject:</code>下<code>bottom:</code>中新增一条内容，假如这个文件叫<code>diy.js</code>：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="string">&lt;script</span> <span class="string">async</span> <span class="string">defer</span> <span class="string">src=&#x27;/js/diy.js&#x27;&gt;&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><p><code>diy.js</code>内容为：</p><figure class="highlight js"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//动态分类条</span></span><br><span class="line"><span class="keyword">var</span> pathInfo = <span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">pathname</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">categoriesBarActive</span>(<span class="params"></span>) &#123;</span><br><span class="line">  pathInfo = <span class="built_in">decodeURIComponent</span>(pathInfo)</span><br><span class="line">  <span class="comment">// console.log(pathInfo);</span></span><br><span class="line">  <span class="comment">//判断是否是首页</span></span><br><span class="line">  <span class="keyword">if</span> (pathInfo == <span class="string">&#x27;/&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;#category-bar&#x27;</span>)) &#123;</span><br><span class="line">      <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;首页&#x27;</span>).<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;select&quot;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 验证是否是分类链接</span></span><br><span class="line">    <span class="keyword">const</span> pattern = <span class="regexp">/\/categories\/.*?\//</span>;</span><br><span class="line">    <span class="keyword">let</span> patbool = pattern.<span class="title function_">test</span>(pathInfo);</span><br><span class="line">    <span class="keyword">let</span> valuegroup = pathInfo.<span class="title function_">split</span>(<span class="string">&quot;/&quot;</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> n = <span class="number">0</span>; n &lt;= valuegroup.<span class="property">length</span>; n++) &#123;</span><br><span class="line">      n = valuegroup.<span class="property">length</span>;</span><br><span class="line">      <span class="keyword">var</span> nowCategorie = valuegroup[n - <span class="number">2</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// console.log(patbool);</span></span><br><span class="line">    <span class="keyword">if</span> (patbool) &#123;</span><br><span class="line">      <span class="comment">// console.log(valuegroup[2]);</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(nowCategorie)) &#123;</span><br><span class="line">        <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(nowCategorie).<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;select&quot;</span>);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">let</span> id;</span><br><span class="line">      <span class="keyword">switch</span> (nowCategorie) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;game&#x27;</span>:</span><br><span class="line">          id = <span class="string">&#x27;小游戏&#x27;</span>;</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;#category-bar&#x27;</span>)) &#123;</span><br><span class="line">        <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(id).<span class="property">classList</span>.<span class="title function_">add</span>(<span class="string">&quot;select&quot;</span>);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">categoriesBarNext</span>()</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//翻页按钮</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">scrollCategoryBarToRight</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">var</span> e = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-items&quot;</span>)</span><br><span class="line">    , t = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-next&quot;</span>)</span><br><span class="line">    , o = e.<span class="property">clientWidth</span>;</span><br><span class="line">  e &amp;&amp; (e.<span class="property">scrollLeft</span> + e.<span class="property">clientWidth</span> &gt;= e.<span class="property">scrollWidth</span> ? (e.<span class="title function_">scroll</span>(&#123;</span><br><span class="line">    <span class="attr">left</span>: <span class="number">0</span>,</span><br><span class="line">    <span class="attr">behavior</span>: <span class="string">&quot;smooth&quot;</span></span><br><span class="line">  &#125;),</span><br><span class="line">    t.<span class="property">innerHTML</span> = <span class="string">&#x27;&lt;i class=&quot;fa-solid fa-chevrons-right&quot;&gt;&lt;/i&gt;&#x27;</span>) : e.<span class="title function_">scrollBy</span>(&#123;</span><br><span class="line">      <span class="attr">left</span>: o,</span><br><span class="line">      <span class="attr">behavior</span>: <span class="string">&quot;smooth&quot;</span></span><br><span class="line">    &#125;))</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//新增方法：动态插入翻页按钮</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">categoriesBarNext</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-items&quot;</span>)) &#123;</span><br><span class="line">    <span class="keyword">let</span> e = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-items&quot;</span>)</span><br><span class="line">    , t = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-next&quot;</span>)</span><br><span class="line">    <span class="keyword">if</span> (e.<span class="property">scrollWidth</span> &gt; e.<span class="property">clientWidth</span>) &#123;</span><br><span class="line">      t.<span class="property">innerHTML</span> = <span class="string">&#x27;&lt;i class=&quot;fa-solid fa-chevrons-right&quot;&gt;&lt;/i&gt;&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (t.<span class="property">children</span>[<span class="number">0</span>]) &#123;</span><br><span class="line">      <span class="keyword">const</span> iElement = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;.category-bar-next i&#x27;</span>);</span><br><span class="line">      <span class="keyword">const</span> parentElement = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;category-bar-next&#x27;</span>);</span><br><span class="line">      </span><br><span class="line">      parentElement.<span class="title function_">removeChild</span>(iElement);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//窗口改变就执行</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">onresize</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="title function_">categoriesBarNext</span>()</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">function</span> <span class="title function_">topCategoriesBarScroll</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-items&quot;</span>)) &#123;</span><br><span class="line">    <span class="keyword">let</span> xscroll = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;category-bar-items&quot;</span>);</span><br><span class="line">    xscroll.<span class="title function_">addEventListener</span>(<span class="string">&quot;mousewheel&quot;</span>, <span class="keyword">function</span> (<span class="params">e</span>) &#123;</span><br><span class="line">      <span class="comment">//计算鼠标滚轮滚动的距离</span></span><br><span class="line">      <span class="keyword">let</span> v = -e.<span class="property">wheelDelta</span> / <span class="number">2</span>;</span><br><span class="line">      xscroll.<span class="property">scrollLeft</span> += v;</span><br><span class="line">      <span class="comment">//阻止浏览器默认方法</span></span><br><span class="line">      e.<span class="title function_">preventDefault</span>();</span><br><span class="line">    &#125;, <span class="literal">false</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//方法调用</span></span><br><span class="line"><span class="title function_">categoriesBarActive</span>()</span><br><span class="line"><span class="title function_">topCategoriesBarScroll</span>()</span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;pjax:complete&quot;</span>, (<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">  <span class="title function_">categoriesBarActive</span>()</span><br><span class="line">  <span class="title function_">topCategoriesBarScroll</span>()</span><br><span class="line">&#125;))</span><br></pre></td></tr></table></figure><h3 id="配置分类条内容"><a href="#配置分类条内容" class="headerlink" title="配置分类条内容"></a>配置分类条内容</h3><p>在主题配置文件<code>_config.butterfly.yml</code>适当位置，新增以下内容：  </p><h4 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a>参数说明</h4><table><thead><tr><th>字段</th><th>是否必填</th><th>释义</th><th>取值来源</th></tr></thead><tbody><tr><td>enable</td><td>Y</td><td>分类条开关</td><td>无</td></tr><tr><td>name</td><td>Y</td><td>分类条上展示的分类项名称</td><td>自定义</td></tr><tr><td>id</td><td>Y</td><td>唯一值，根据这个实现点击切换</td><td>自定义，支持中文</td></tr><tr><td>url</td><td>Y</td><td>页面path，即待添加页面的访问 URL ，去除域名剩余的部分</td><td>path</td></tr></tbody></table><figure class="highlight yml"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 动态分类条</span></span><br><span class="line"><span class="comment"># 使用指南：https://guole.fun/posts/13386/</span></span><br><span class="line"><span class="comment"># --------------------------------------</span></span><br><span class="line"><span class="attr">DynamicCategoryBar:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">category:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">首页</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">首页</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">经验分享</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">经验分享</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/categories/经验分享/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">NPM插件</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">NPM插件</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/categories/NPM插件/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">小游戏</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">小游戏</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/game/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">找点儿乐子</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">找点儿乐子</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/categories/找点儿乐子/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">文案摘录</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">文案摘录</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/categories/文案摘录/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">给生活加点颜色</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">给生活加点颜色</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/categories/给生活加点颜色/&#x27;</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">胡思乱想</span></span><br><span class="line">      <span class="attr">id:</span> <span class="string">胡思乱想</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">&#x27;/categories/胡思乱想/&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="引入css"><a href="#引入css" class="headerlink" title="引入css"></a>引入css</h3><p>同上，可以直接放到你自己的自定义样式表里，如果没有就新建一个。在<code>_config.butterfly.yml</code>的<code>inject:</code>下<code>head:</code>中新增一条内容，假如这个文件叫<code>diy.css</code>：</p><figure class="highlight yml"><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 class="bullet">-</span> <span class="string">&lt;link</span> <span class="string">rel=&quot;stylesheet&quot;</span> <span class="string">href=&quot;/css/diy.css&quot;</span> <span class="string">media=&quot;print&quot;</span> <span class="string">onload=&quot;this.media=&#x27;all&#x27;&quot;&gt;</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">&lt;link</span> <span class="string">rel=&quot;stylesheet&quot;</span> <span class="string">href=&quot;/css/color.css&quot;</span> <span class="string">media=&quot;print&quot;</span> <span class="string">onload=&quot;this.media=&#x27;all&#x27;&quot;&gt;</span></span><br></pre></td></tr></table></figure><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">diy.css内容</button><button type="button" class="tab">color.css内容</button></div><div class="tab-contents"><div class="tab-item-content active"><p>前前后后改了好几次，如有样式问题，可在本站自行查找调整。</p><figure class="highlight css"><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><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 首页分类条展示 */</span></span><br><span class="line"><span class="selector-id">#category-bar</span> &#123;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0.4rem</span> <span class="number">1rem</span> <span class="number">0.4rem</span> <span class="number">0.7rem</span>;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">transition</span>: <span class="number">0.3s</span>;</span><br><span class="line">    <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">    -webkit-user-<span class="selector-tag">select</span>: none;</span><br><span class="line">    user-<span class="selector-tag">select</span>: none;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#category-bar</span>,</span><br><span class="line"><span class="selector-class">.category-in-bar-tips</span> &#123;</span><br><span class="line">      <span class="attribute">margin-bottom</span>: <span class="number">0.75rem</span>;</span><br><span class="line">      <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">8px</span> <span class="number">16px</span> -<span class="number">4px</span> <span class="number">#2c2d300c</span>;</span><br><span class="line">      <span class="attribute">animation</span>: slide-in <span class="number">0.6s</span> <span class="number">0.3s</span> backwards;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#category</span> <span class="selector-id">#category-bar</span> &#123;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">border</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#category</span> <span class="selector-tag">a</span><span class="selector-class">.category-bar-item</span><span class="selector-class">.select</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-in-bar</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-in-bar-tips</span> &#123;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">1rem</span>;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">0.25rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>)  &#123;</span><br><span class="line">    <span class="selector-class">.category-in-bar-tips</span> &#123;</span><br><span class="line">        <span class="attribute">margin-right</span>: <span class="number">0.2rem</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-items</span> &#123;</span><br><span class="line">    <span class="attribute">white-space</span>: nowrap;</span><br><span class="line">    <span class="attribute">overflow-x</span>: scroll;</span><br><span class="line">    <span class="attribute">overflow-y</span>: hidden;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">30px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-items</span>::-webkit-scrollbar &#123;</span><br><span class="line">    <span class="attribute">display</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-item</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--font-color);</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0.1rem</span> <span class="number">0.5rem</span>;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">6px</span>;</span><br><span class="line">    <span class="attribute">font-weight</span>: bold;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">8px</span>;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">align-items</span>: center;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">30px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-item</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--guole-color-hover);</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-item</span><span class="selector-class">.select</span> <span class="selector-tag">a</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--guole-color-hover);</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-more</span> &#123;</span><br><span class="line">    <span class="attribute">margin-left</span>: <span class="number">1rem</span>;</span><br><span class="line">    <span class="attribute">font-weight</span>: bold;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--font-color);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-next</span> &#123;</span><br><span class="line">    <span class="attribute">margin-left</span>: <span class="number">16px</span>;</span><br><span class="line">    <span class="attribute">cursor</span>: pointer;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-next</span><span class="selector-pseudo">:hover</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--guole-main);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.category-bar-next</span> <span class="selector-tag">i</span><span class="selector-pseudo">::before</span>&#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="string">&quot;\f101&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#page</span> &gt; <span class="selector-id">#category</span> &gt; <span class="selector-class">.category-in-bar</span> &#123;</span><br><span class="line">    <span class="attribute">border-bottom</span>: <span class="number">2px</span> solid <span class="built_in">var</span>(--guole-card-border);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>为什么要再新建一个<code>color.css</code>？因为实测，<code>diy.css</code>内容与<code>color.css</code>放一起，定义的颜色不生效……分开也方便管理。色值可以按你自己的主题色调整。</p><figure class="highlight css"><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 class="selector-pseudo">:root</span> &#123;</span><br><span class="line">  <span class="attr">--guole-theme-color</span>: <span class="number">#1c69ed</span>;</span><br><span class="line">  <span class="attr">--guole-main</span>: <span class="built_in">var</span>(--guole-theme-color);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-attr">[data-theme=light]</span> &#123;</span><br><span class="line">  <span class="attr">--guole-color-hover</span>: <span class="number">#1c69ed</span>;</span><br><span class="line">  <span class="attr">--guole-card-border</span>: <span class="built_in">rgba</span>(<span class="number">66</span>, <span class="number">68</span>, <span class="number">74</span>, .<span class="number">15</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-attr">[data-theme=dark]</span> &#123;</span><br><span class="line">  <span class="attr">--guole-color-hover</span>: <span class="number">#11459d</span>;</span><br><span class="line">  <span class="attr">--guole-card-border</span>: <span class="built_in">rgba</span>(<span class="number">66</span>, <span class="number">68</span>, <span class="number">74</span>, .<span class="number">5</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="后续新增分类"><a href="#后续新增分类" class="headerlink" title="后续新增分类"></a>后续新增分类</h3><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">1.新增分类页面</button><button type="button" class="tab">2.1新增非分类页面</button><button type="button" class="tab">2.2添加文件头</button></div><div class="tab-contents"><div class="tab-item-content active"><p>若新增项为分类页面（path为<code>/categories/……/</code>类型），直接编辑<code>_config.butterfly.yml</code>即可。  </p><figure class="highlight yml"><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="attr">DynamicCategoryBar:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">category:</span></span><br><span class="line"><span class="string">+</span>   <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">NPM插件</span></span><br><span class="line"><span class="string">+</span>     <span class="attr">id:</span> <span class="string">NPM插件</span></span><br><span class="line"><span class="string">+</span>     <span class="attr">url:</span> <span class="string">&#x27;/categories/NPM插件/&#x27;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><ol><li>还是先配置<code>_config.butterfly.yml</code>，新增内容<figure class="highlight yml"><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="attr">DynamicCategoryBar:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">category:</span></span><br><span class="line"><span class="string">+</span>   <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">关于本站</span></span><br><span class="line"><span class="string">+</span>     <span class="attr">id:</span> <span class="string">关于本站</span></span><br><span class="line"><span class="string">+</span>     <span class="attr">url:</span> <span class="string">&#x27;/about/&#x27;</span></span><br></pre></td></tr></table></figure></li><li>编辑<code>diy.js</code>：<br>在原有<code>switch</code>中，新增一个<code>case</code>：<div class="note info flat"><p><strong>小贴士：</strong></p><ul><li>‘about’: 即<code>category.pug</code>中，你填写的<code>a</code>标签<code>href</code>属性值，也就是这个自定义页面实际访问时的<code>path</code>；</li><li>id: 即<code>category.pug</code>中，你设置的<code>id</code>；</li></ul></div><figure class="highlight js"><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="keyword">switch</span> (nowCategorie) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">&#x27;game&#x27;</span>:</span><br><span class="line">          id = <span class="string">&#x27;小游戏&#x27;</span>;</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">+       <span class="keyword">case</span> <span class="string">&#x27;about&#x27;</span>:</span><br><span class="line">+         id = <span class="string">&#x27;关于本站&#x27;</span>;</span><br><span class="line">+         <span class="keyword">break</span>;</span><br><span class="line">      &#125;</span><br></pre></td></tr></table></figure></li></ol></div><div class="tab-item-content"><p>在对应独立页面的<code>.md</code>文件头，设置<code>type: categoryBar</code>。</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>大功告成，<code>hexo</code>三连，看看效果吧。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;闲了好一阵子，最近突来兴趣，再扒&lt;code&gt;洪哥&lt;/code&gt;的博客。  &lt;/p&gt;
&lt;p&gt;关于页面动态分类条，&lt;code&gt;洪哥&lt;/code&gt;早已提供教程（&lt;a href=&quot;https://blog.zhheo.com/p/bc61964d.html#&quot;&gt;HEO：Butter</summary>
      
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Butterfly美化" scheme="https://blog.guole.fun/tags/Butterfly%E7%BE%8E%E5%8C%96/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>为你的网站添加https加密-免费申请SSL证书</title>
    <link href="https://blog.guole.fun/posts/38768/"/>
    <id>https://blog.guole.fun/posts/38768/</id>
    <published>2022-05-06T09:36:02.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>本站差不多是去年这个时候搭建的，近期<code>DNSPod</code>提醒我，原来申请的域名<code>SSL证书</code>到期了，让我及时续期。  </p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>正如上文所说，本来也没什么问题，正常再操作一遍申请免费SSL证书即可。但我尝试了3~5次，均失败告终，每一次都提示<code>超过3天未检测到指定添加的CNAME解析记录，无法确认域名身份</code>。我：？？？<br><img src="/posts/38768/3.png"><br>要知道DNS解析都是正常添加的，提交SSL证书时也验证通过才“下一步”的。因此，严重怀疑腾讯云卖屁股，故意这样搞。免费证书续费失败，可不得买他家的付费证书？  </p><p>联系客服，也答复“不是100%审核通过”，把问题都推给<code>TrustAsia</code>了。我会买付费证书？做梦去。  </p><h2 id="证书级别"><a href="#证书级别" class="headerlink" title="证书级别"></a>证书级别</h2><p>一般SSL证书分为三种类型，域名型SSL证书（DV SSL）、企业型SSL证书（OVSSL）、增强型SSL证书（EVSSL）。而我们常用的（免费）一般是第一个。  </p><p>市面还有很多证书颁发机构，比如<code>Let&#39;s Encrypt</code>。  </p><blockquote><p>Let’s Encrypt是国外一个公共的免费SSL项目，由 Linux 基金会托管，它的来头不小，由Mozilla、思科、Akamai、IdenTrust和EFF等组织发起，目的就是向网站自动签发和管理免费证书，以便加速互联网由HTTP过渡到HTTPS。  </p></blockquote><h2 id="OHTTP免费证书"><a href="#OHTTP免费证书" class="headerlink" title="OHTTP免费证书"></a>OHTTP免费证书</h2><p>一般我们使用例如腾讯云SSL证书就满足需求了，365天有效期，申请操作简单。而<code>OHTTP</code>免费证书，是基于<code>Let&#39;s Encrypt</code>的公开接口，获取<code>Let&#39;s Encrypt</code>证书。<br><img src="/posts/38768/1.png"><br><a href="https://www.ohttps.com/?invitationCode=mlyxprokvo8ez6jw">点击这里即可访问OHTTP官网</a>，注册帐号备用。（使用了我的邀请链接，注册后你也能得1000积分，用于后续证书自动化部署）  </p><p>OHTTP网站使用简单，<a href="https://www.ohttps.com/guide/createcertificate">点击此处即可进入申请证书页面</a>。多个二级域名可以一次申请，如本站的<code>guole.fun</code>、<code>cdn.guole.fun</code>、<code>www.guole.fun</code>。当然选择<code>泛域名</code>，直接申请<code>*.guole.fun</code>是最简单的，但实际操作一直报错<code>urn:acme:params:auto:error:authorizationStatusNotValid: undefined</code>。<br><img src="/posts/38768/4.png"></p><h2 id="验证域名"><a href="#验证域名" class="headerlink" title="验证域名"></a>验证域名</h2><p>验证域名推荐使用 DNS授权方式，简单。以<code>DNSPod</code>为例，在<code>DNSPod控制台</code>创建一个API访问密钥。这里留意，是在<code>DNSPod控制台</code>，而不是腾讯云控制台。<a href="https://console.cloud.tencent.com/cam/capi">直接点击这里跳转最方便</a>。  </p><p>生成的密钥和ID，填写到OHTTP页面即可。接着点击“授权验证”，下一步就能创建证书。<br><img src="/posts/38768/2.png"></p><h2 id="上传证书"><a href="#上传证书" class="headerlink" title="上传证书"></a>上传证书</h2><p>申请到的证书，可手动添加到腾讯云SSL证书管理中。  </p><div class="tag link"><a class="link-card" title="腾讯云SSL证书管理" href="https://console.cloud.tencent.com/ssl"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/weizhi1.png"/></div><div class="right"><p class="text">腾讯云SSL证书管理</p><p class="url">https://console.cloud.tencent.com/ssl</p></div></a></div><p>选择上传证书，默认国际标准，粘贴证书密钥、签名证书即可。（选择带有中间证书的那个）<br><img src="/posts/38768/5.png"></p><h2 id="自动部署"><a href="#自动部署" class="headerlink" title="自动部署"></a>自动部署</h2><p>证书创建后，可以通过<code>OHTTP</code>自动部署到腾讯云CDN加速中。点击下方查看<code>OHTTP</code>给出的指导即可操作！至此，已经免费申请到了SSL证书，90天自动更新一次，自动部署到腾讯云。  </p><div class="tag link"><a class="link-card" title="部署节点-腾讯云内容分发CDN" href="https://www.ohttps.com/docs/cloud/tcloud/cdn"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/weizhi1.png"/></div><div class="right"><p class="text">部署节点-腾讯云内容分发CDN</p><p class="url">https://www.ohttps.com/docs/cloud/tcloud/cdn</p></div></a></div><h2 id="手动部署"><a href="#手动部署" class="headerlink" title="手动部署"></a>手动部署</h2><p><code>OHTTP</code>自动部署需要消耗余额，注册赠送的1000余额，每部署一个域名证书即消耗25，所以看看手动部署吧。  </p><p>在腾讯云CDN加速页面，选择“证书配置”——“已托管证书”，选择新申请的证书即可。</p><div class="tag link"><a class="link-card" title="腾讯云CDN证书配置" href="https://console.cloud.tencent.com/cdn/certificate"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/weizhi1.png"/></div><div class="right"><p class="text">腾讯云CDN证书配置</p><p class="url">https://console.cloud.tencent.com/cdn/certificate</p></div></a></div>]]></content>
    
    
    <summary type="html">免费申请 SSL 证书，完成网站 HTTPS 加密，到期自动更新！</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Butterfly美化" scheme="https://blog.guole.fun/tags/Butterfly%E7%BE%8E%E5%8C%96/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>ispeak-bber前端美化增强版，支持歌曲分享</title>
    <link href="https://blog.guole.fun/posts/34234/"/>
    <id>https://blog.guole.fun/posts/34234/</id>
    <published>2021-09-13T18:51:52.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>一些感动瞬间，很想记录下来，之前使用的<code>bber</code>很强大，但是在音乐分享方面没有支持，最近摸鱼，就折腾出来了。  </p><h2 id="包含"><a href="#包含" class="headerlink" title="包含"></a>包含</h2><ol><li>支持<code>hexo</code>主题，特别是<code>Butterfly</code>的首页轮播bber</li><li>支持自定义说说页面，直接播放分享的QQ音乐&#x2F;网易云音乐，歌单或歌曲</li></ol><h2 id="效果演示"><a href="#效果演示" class="headerlink" title="效果演示"></a>效果演示</h2><details blue><summary> 效果预览 </summary>              <div class='content'>              <p><img src="/posts/34234/bber1.png" alt="说说页面在线播放"></p><div class="tag link"><a class="link-card" title="点击查看我的说说页面" href="/bb/"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/guole.fun.png"/></div><div class="right"><p class="text">点击查看我的说说页面</p><p class="url">/bb/</p></div></a></div>              </div>            </details><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><div class="note success flat"><p>当前版本 v1.4.5  </p><ol><li>增加QQ音乐或网易云音乐的歌曲&#x2F;歌单分享，说说页面在线播放</li><li>调整了说说出现图片时，顶部空白过大问题  </li><li>调整了“再翻翻”，增加阴影和hover效果  </li><li>调整顶部“My BiBi”为“闪念”  </li><li>更换一种<code>timeago</code>方法，解决“两周前”、“三周前”等部分情况下显示实际日期的bug  </li><li>修复头像尺寸异常的bug  </li><li>bber说说首页轮播效果，链接、音乐、图片的美化展示</li><li>支持<code>Markdown</code>格式图片链接或<code>URL</code></li></ol></div><h2 id="首页bber轮播实现"><a href="#首页bber轮播实现" class="headerlink" title="首页bber轮播实现"></a>首页bber轮播实现</h2><details yellow><summary> 代码实现流程 </summary>              <div class='content'>              <div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">第一步：创建js、css</button><button type="button" class="tab">第二步：添加css</button><button type="button" class="tab">第三步：首页布局中引入</button><button type="button" class="tab">jQuery与timeago下载</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>依赖jQuery</strong></p><p>添加以下<code>js</code>代码，自己新建或加到已有的<code>js</code>文件中，其中跳转<code>URL</code>和<code>json URL</code>换成你自己的。（自己新建的，记得<code>blog/_config.butterfly.yml</code>中<code>inject</code>里引入）</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> pathName = <span class="variable language_">window</span>.<span class="property">document</span>.<span class="property">location</span>.<span class="property">pathname</span></span><br><span class="line"><span class="keyword">if</span> (pathName === <span class="string">&#x27;/&#x27;</span>) &#123;</span><br><span class="line">  $(<span class="variable language_">document</span>).<span class="title function_">ready</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">      <span class="keyword">if</span> ( $(<span class="string">&quot;#bber-talk&quot;</span>).<span class="property">length</span> &gt; <span class="number">0</span> ) &#123;</span><br><span class="line">        <span class="keyword">var</span> jsonUrl = <span class="string">&#x27;&#x27;</span></span><br><span class="line">        jsonUrl = <span class="string">&quot;https://626c-blogpkly-13278c-1258453354.tcb.qcloud.la/json/bber.json&quot;</span></span><br><span class="line">        $.<span class="title function_">getJSON</span>(jsonUrl+<span class="string">&quot;?t=&quot;</span>+<span class="title class_">Date</span>.<span class="title function_">parse</span>( <span class="keyword">new</span> <span class="title class_">Date</span>()),<span class="keyword">function</span>(<span class="params">res</span>)&#123;</span><br><span class="line">          <span class="keyword">var</span> bberHtml = <span class="string">&#x27;&#x27;</span></span><br><span class="line">          $.<span class="title function_">each</span>(res.<span class="property">data</span>, <span class="keyword">function</span>(<span class="params">i, item</span>)&#123;</span><br><span class="line">            <span class="keyword">var</span> d = <span class="keyword">new</span> <span class="title class_">Date</span>(item.<span class="property">date</span>)</span><br><span class="line">            <span class="keyword">var</span> date = d.<span class="title function_">getFullYear</span>()+<span class="string">&#x27;/&#x27;</span>+(d.<span class="title function_">getMonth</span>()+<span class="number">1</span>)+<span class="string">&#x27;/&#x27;</span>+d.<span class="title function_">getDate</span>() +<span class="string">&#x27; &#x27;</span>+d.<span class="title function_">getHours</span>()+<span class="string">&#x27;:&#x27;</span>+d.<span class="title function_">getMinutes</span>()+<span class="string">&#x27;:&#x27;</span>+d.<span class="title function_">getSeconds</span>()</span><br><span class="line">            <span class="keyword">var</span> dataTime = timeago.<span class="title function_">format</span>(date, <span class="string">&#x27;zh_CN&#x27;</span>);</span><br><span class="line">            <span class="keyword">var</span> newdataTime = <span class="string">&#x27;&lt;span class=&quot;datatime&quot;&gt;&#x27;</span>+dataTime+<span class="string">&#x27;&lt;/span&gt;&#x27;</span></span><br><span class="line">            bberHtml += <span class="string">&#x27;&lt;li class=&quot;item item-&#x27;</span>+(i+<span class="number">1</span>)+<span class="string">&#x27;&quot;&gt;&#x27;</span>+<span class="string">&#x27;&lt;a href=&quot;https://guole.fun/bb/&quot; style=&quot;color: var(--font-color);/*font-weight: normal;*/&quot;&gt;&#x27;</span>+newdataTime+<span class="string">&#x27;： &#x27;</span>+<span class="title function_">urlToLink</span>(item.<span class="property">content</span>)+<span class="string">&#x27;&lt;/a&gt;&lt;/li&gt;&#x27;</span></span><br><span class="line">          &#125;);</span><br><span class="line">          $(<span class="string">&#x27;#bber-talk&#x27;</span>).<span class="title function_">append</span>(<span class="string">&#x27;&lt;span class=&quot;index-talk-icon&quot; style=&quot;margin-right: 5px&quot;&gt;&lt;svg viewBox=&quot;0 0 550 550&quot; width=&quot;15&quot; height=&quot;15&quot;&gt;&lt;path d=&quot;M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 7.1 5.8 12 12 12 2.4 0 4.9-.7 7.1-2.4L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64zm16 352c0 8.8-7.2 16-16 16H288l-12.8 9.6L208 428v-60H64c-8.8 0-16-7.2-16-16V64c0-8.8 7.2-16 16-16h384c8.8 0 16 7.2 16 16v288z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;&lt;ul class=&quot;talk-list&quot;&gt;&#x27;</span>+bberHtml+<span class="string">&#x27;&lt;/ul&gt;&#x27;</span>)</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">urlToLink</span>(<span class="params">str</span>) &#123;</span><br><span class="line">          <span class="keyword">var</span> img_tag = <span class="regexp">/(&lt;br&gt;)|([[\s\S]*])|(\()|(\))/g</span>;</span><br><span class="line">          <span class="keyword">var</span> re_forimg =<span class="regexp">/\&lt;[img|IMG].*?src=[\&#x27;|\&quot;](https\:\/\/.*?(?:[\.jpg|\.jpeg|\.png|\.gif|\.bmp]))[\&#x27;|\&quot;].*?[\/]?&gt;/g</span>;</span><br><span class="line">          <span class="keyword">var</span> music = <span class="regexp">/(y.qq.com)|(music.163.com)/g</span>;</span><br><span class="line">          <span class="keyword">var</span> music_url = <span class="regexp">/[a-zA-z]+:\/\/[^\s]*/g</span>;</span><br><span class="line">            <span class="keyword">if</span> (music.<span class="title function_">test</span>(str)) &#123;</span><br><span class="line">              str =str.<span class="title function_">replace</span>(music_url,<span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1024 1024&quot; width=&quot;18&quot; height=&quot;18&quot;&gt;&lt;path d=&quot;M960 0H1024v736c0 88.3712-100.283733 160-224 160S576 824.3712 576 736s100.283733-160 224-160c62.685867 0 119.3472 18.397867 160 48.042667V256l-512 113.783467v494.216533c0 88.3712-100.283733 160-224 160S0 952.3712 0 864s100.283733-160 224-160c62.685867 0 119.3472 18.397867 160 48.042667V128L960 0z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;音乐分享&#x27;</span>;</span><br><span class="line">              &#125;);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;&#125;</span><br><span class="line">          str =str.<span class="title function_">replace</span>(re_forimg,<span class="string">&#x27;$1&#x27;</span>);</span><br><span class="line">          <span class="keyword">var</span> re_formd = <span class="regexp">/^!\[(.*)\]\((.*)\)/g</span>;</span><br><span class="line">          str = str.<span class="title function_">replace</span>(re_formd,<span class="string">&#x27;$2&#x27;</span>);</span><br><span class="line">          str = str.<span class="title function_">replace</span>(img_tag,<span class="string">&quot;&quot;</span>);</span><br><span class="line">          <span class="keyword">var</span> re =<span class="regexp">/\bhttps?:\/\/(?!\S+(?:jpe?g|png|bmp|gif|webp|gif))\S+/g</span>;</span><br><span class="line">          <span class="keyword">var</span> re_forpic =<span class="regexp">/\bhttps?:\/\/.*?(\.gif|\.jpe?g|\.png|\.bmp|\.webp)/g</span>;</span><br><span class="line">          str =str.<span class="title function_">replace</span>(re,<span class="keyword">function</span> (<span class="params">website</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1025 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M333.06186 733.061768c-58.347896 52.210106-97.040127 49.051159-136.467091 9.492188l-45.156456-48.462758c-39.427988-39.541575-39.427988-103.667058 0-143.226029l193.260585-193.848986c39.426965-39.558971 103.355973-39.558971 142.78396 0l35.679617 35.794228c30.457686 30.555923 37.398772 75.762521 20.801768 112.997564l86.286202 66.040089c59.149145-59.33027 59.149145-155.517983 0-214.830857L523.162476 249.600755c-59.133795-59.33027-155.010423-59.33027-214.160591 0L44.350342 515.071965c-59.133795 59.313897-59.133795 155.50161 0 214.830857l107.08797 107.415428c59.133795 59.313897 155.026796 59.313897 214.176964 0l102.161774-105.647155-72.980151-70.034053L333.06186 733.061768zM987.196021 285.394982 880.1234 177.979554c-59.149145-59.33027-155.026796-59.33027-214.176964 0 0 0 4.223185-1.064238-57.988716 61.343113l71.113641 68.167542 31.604812-34.877345c39.427988-39.541575 103.356996-39.541575 142.78396 0l35.69599 35.8106c39.427988 39.541575 39.427988 103.667058 0 143.226029L714.818517 632.847345c-39.427988 39.541575-103.340623 39.541575-142.768611 0l-29.395494-48.462758c-61.883419-46.25344-42.865273-57.317427-37.611619-88.544639L426.548044 418.130076c-59.150168 59.33027-59.150168 155.517983 0 214.830857l107.072621 107.432825c59.149145 59.312874 155.026796 59.312874 214.176964 0l239.398392-240.166895C1071.582967 402.924769 987.196021 285.394982 987.196021 285.394982z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">          &#125;);</span><br><span class="line">          str =str.<span class="title function_">replace</span>(re_forpic,<span class="keyword">function</span> (<span class="params">imgurl</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&#x27;&lt;svg viewBox=&quot;0 0 1024 1024&quot; width=&quot;21&quot; height=&quot;21&quot;&gt;&lt;path d=&quot;M821.6 120.93333333H195.4c-74.1 0-134.2 60.1-134.2 134.2v492c0 74.1 60.1 134.2 134.2 134.2h626.2c74.1 0 134.2-60.1 134.2-134.2v-492c0-74.1-60.1-134.2-134.2-134.2zM251.3 255.13333333c30.9 0 55.9 25 55.9 55.9s-25 55.9-55.9 55.9-55.9-25-55.9-55.9 25-55.9 55.9-55.9z m614.6 559.1H153.3c-37.3 0-58.2-43.1-35.1-72.4L302.1 508.33333333c17.9-22.7 52.4-22.7 70.3 0l76.5 97.2 148.6-260c17.2-30.1 60.5-30.1 77.7 0L904.8 747.33333333c17 29.8-4.5 66.9-38.9 66.9z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&#x27;</span>;</span><br><span class="line">          &#125;);</span><br><span class="line">          <span class="keyword">return</span> str;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">Roll</span> (<span class="params"></span>)&#123;</span><br><span class="line">          <span class="keyword">var</span> list_li = $(<span class="string">&#x27;.talk-list li&#x27;</span>),cur_li = list_li.<span class="title function_">first</span>(),last_li = list_li.<span class="title function_">last</span>();</span><br><span class="line">          last_li.<span class="title function_">after</span>(cur_li);</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="built_in">setInterval</span>(<span class="title class_">Roll</span>,<span class="number">3000</span>);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>可以新建或添加以下代码到已有的自定义<code>css</code>文件中。（自己新建的，记得<code>blog/_config.butterfly.yml</code>中<code>inject</code>里引入）</p><figure class="highlight css"><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="comment">/* bber轮播 */</span></span><br><span class="line"><span class="selector-id">#bber-talk</span>&#123;<span class="attribute">background</span>:<span class="built_in">var</span>(--card-bg);<span class="attribute">color</span>:<span class="built_in">var</span>(--fontcolor);<span class="attribute">padding</span>:<span class="number">0.6rem</span> <span class="number">1rem</span> <span class="number">0.5rem</span> <span class="number">1rem</span>;<span class="attribute">border-radius</span>:<span class="number">12px</span>;<span class="attribute">cursor</span>:auto;<span class="attribute">box-shadow</span>:<span class="built_in">var</span>(--card-box-shadow);<span class="attribute">display</span>:-webkit-flex;<span class="attribute">display</span>:flex;-webkit-<span class="attribute">align-items</span>:center;<span class="attribute">align-items</span>:center;<span class="attribute">overflow</span>:hidden;<span class="attribute">transition</span>:all <span class="number">0.3s</span>;<span class="attribute">margin-bottom</span>:-<span class="number">0.2rem</span>;<span class="attribute">z-index</span>: <span class="number">10</span>;<span class="attribute">position</span>: relative;&#125;</span><br><span class="line"><span class="selector-id">#bber-talk</span><span class="selector-pseudo">:not</span>(<span class="selector-tag">a</span>)&#123;<span class="attribute">font-weight</span>:bold;&#125;</span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-tag">svg</span>&#123;<span class="attribute">fill</span>: currentColor;<span class="attribute">vertical-align</span>: middle;<span class="attribute">display</span>: inline;<span class="attribute">margin-right</span>:<span class="number">5px</span>;&#125;</span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span>&#123;<span class="attribute">margin</span>: <span class="number">0</span>;<span class="attribute">padding</span>: <span class="number">0</span>;<span class="attribute">max-height</span>: <span class="number">1.6rem</span>;<span class="attribute">overflow</span>: hidden;<span class="attribute">margin-bottom</span>: -<span class="number">0.3rem</span>;<span class="attribute">transition</span>: all <span class="number">1s</span> ease-in-out;&#125;</span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span> <span class="selector-pseudo">:hover</span>&#123;<span class="attribute">color</span>: <span class="number">#49b1f5</span> <span class="meta">!important</span>;<span class="attribute">transition</span>: all .<span class="number">15s</span> ease-in-out;&#125;</span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span> <span class="selector-tag">li</span><span class="selector-class">.item</span> <span class="selector-tag">a</span> &#123;<span class="attribute">cursor</span>:pointer;&#125;</span><br><span class="line"><span class="selector-id">#bber-talk</span> <span class="selector-class">.talk-list</span> <span class="selector-tag">li</span> &#123;<span class="attribute">list-style</span>: none;<span class="attribute">width</span>: <span class="number">100%</span>;<span class="attribute">white-space</span>: nowrap;<span class="attribute">text-overflow</span>: ellipsis;<span class="attribute">overflow</span>: hidden;&#125;</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>找到<code>/themes/butterfly/layout/index.pug</code>文件，在<code>#recent-posts.recent-posts</code>这一行下，添加以下内容，注意缩进：</p><figure class="highlight plaintext"><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">#recent-posts.recent-posts</span><br><span class="line">  #bber-talk</span><br><span class="line">    script(src=&#x27;/js/jquery.min.js&#x27;)</span><br><span class="line">    script(src=&#x27;/js/timeago.min.js&#x27;)</span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><p>文件放到<code>blog/source/js/</code>目录下。</p><div class="btns rounded grid5">            <a class="button" href='/js/jquery.min.js' download='' title='jQuery下载'><i class='fas fa-download'></i>jQuery下载</a><a class="button" href='/js/timeago.min.js' download='' title='timeago下载'><i class='fas fa-download'></i>timeago下载</a>          </div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>              </div>            </details> <h2 id="说说页面使用"><a href="#说说页面使用" class="headerlink" title="说说页面使用"></a>说说页面使用</h2><details yellow><summary> 代码实现流程 </summary>              <div class='content'>              <div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">新建说说页面</button><button type="button" class="tab">timeago.min.js下载</button></div><div class="tab-contents"><div class="tab-item-content active"><p>新建一个<code>bb</code>（说说）独立页面，然后直接复制粘贴以下内容：</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line">&lt;!--  自言自语  --&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&#x27;speak&#x27;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;/js/timeago.min.js&quot;</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/gh/kuole-o/bber-ispeak@main/dist/ispeak-bber.min.js&quot;</span> <span class="attr">charset</span>=<span class="string">&quot;utf-8&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">ispeakBber</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    .<span class="title function_">init</span>(&#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">el</span>: <span class="string">&#x27;#speak&#x27;</span>, <span class="comment">// 容器选择器</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">name</span>: <span class="string">&#x27;夜的第八章 🦄&#x27;</span>, <span class="comment">// 显示的昵称</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">envId</span>: <span class="string">&#x27;blogpkly-13278c&#x27;</span>, <span class="comment">// 环境id</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">region</span>: <span class="string">&#x27;ap-shanghai&#x27;</span>, <span class="comment">// 腾讯云地址，默认为上海</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">limit</span>: <span class="number">7</span>, <span class="comment">// 每次加载的条数，默认为5</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">avatar</span>: <span class="string">&#x27;https://cdn.guole.fun/img/gl.jpg&#x27;</span>, <span class="comment">// 头像地址</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">fromColor</span>:<span class="string">&#x27;rgb(245, 150, 170)&#x27;</span>, <span class="comment">// 下方标签背景颜色 默认 rgb(245, 150, 170)</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">loadingImg</span>: <span class="string">&#x27;https://7.dusays.com/2021/03/04/d2d5e983e2961.gif&#x27;</span>, <span class="comment">// 自定义loading的图片，示例值为默认值</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">dbName</span>:<span class="string">&#x27;talks&#x27;</span> <span class="comment">// 数据的名称，默认talks，避免有人的命名不是这个，所以加入此配置字段。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    &#125;)</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    .<span class="title function_">then</span>(<span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">// 哔哔加载完成后的回调函数，你可以写你自己的功能</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;哔哔 加载完成&#x27;</span>)</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    &#125;)</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></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></div><div class="tab-item-content"><p>文件放到<code>blog/source/js/</code>目录下。</p><div class="btns rounded grid5">            <a class="button" href='/js/timeago.min.js' download='' title='timeago下载'><i class='fas fa-download'></i>timeago下载</a>          </div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>              </div>            </details> <h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><h3 id="分享QQ音乐"><a href="#分享QQ音乐" class="headerlink" title="分享QQ音乐"></a>分享QQ音乐</h3><div class="note success flat"><p><strong>分享歌曲</strong><br>在QQ音乐中，选择要分享的歌曲——复制链接——发给文件传输助手，点开这个链接，微信中获取当前页面链接，将这个<code>URL</code>直接发给bber云函数<br>注：如果是手机中点击链接，则会得到一条类似<code>https://i.y.qq.com/v8/playsong.html?ADTAG=cbshare&amp;_wv=1&amp;appshare=android_qq&amp;appsongtype=1&amp;appversion=10170011&amp;channelId=10036163&amp;hosteuin=oKoA7inioKn5oz%2A%2A&amp;openinqqmusic=1&amp;platform=11&amp;songmid=000srYoG1nhunX&amp;type=0https://y.qq.com/n/ryqq/songDetail/000srYoG1nhunX?songtype=0&amp;ADTAG=h5_playsong</code>这样的链接；PC端，则是这样的<code>https://y.qq.com/n/ryqq/songDetail/000srYoG1nhunX?songtype=0&amp;ADTAG=h5_playsong</code></p><p><strong>分享歌单</strong><br>在QQ音乐中，选择要分享的歌单——分享给微信好友——微信传输助手，点击这个分享结果，微信中获取当前页面链接，将这个<code>URL</code>直接发给bber云函数<br>注：如果是手机中点击链接，则会得到一条类似<code>https://i.y.qq.com/n2/m/share/details/taoge.html?platform=11&amp;appshare=android_qq&amp;appversion=10170011&amp;hosteuin=oKoA7inioKn5oz**&amp;id=7828767579&amp;ADTAG=wxfshare</code>这样的链接；PC端，则是这样的<code>https://y.qq.com/n/ryqq/playlist/7828767579</code></p></div><h3 id="分享网易云音乐"><a href="#分享网易云音乐" class="headerlink" title="分享网易云音乐"></a>分享网易云音乐</h3><p>网易云音乐要简单些，无论歌单还是歌曲，选择复制链接，去除无关字符，将<code>URL</code>发给云函数即可。<br><img src="/posts/34234/bber2.png" alt="bber分享歌曲示例"></p><h3 id="可能遇到的问题"><a href="#可能遇到的问题" class="headerlink" title="可能遇到的问题"></a>可能遇到的问题</h3><div class="note danger flat"><ol><li><p>分享网易云音乐歌单，页面空白不显示<br>确实如此。我排查了相关代码，应该没错，似乎是<code>meting.js</code>的问题，暂且搁置  </p></li><li><p>页面没有出现<code>aplayer</code>效果<br>首先在主题配置文件中，将<code>aplayer</code>自动插入打开；再说说页面顶部信息里，增加<code>aplayer: true</code>  </p></li><li><p>同一首歌曲&#x2F;歌单，同个音乐源，分享2次及以上，只有第一次会展示。主要是id相同了</p></li><li><p>其他非<code>butterfly</code>主题如何使用<br>自行摸索</p></li></ol></div><p><strong>关联阅读：</strong></p><div class="tag link"><a class="link-card" title="木木bber正确食用方法|美化日记" href="https://blog.guole.fun/posts/butterfly-custom/#%E6%9C%A8%E6%9C%A8bber%E6%AD%A3%E7%A1%AE%E9%A3%9F%E7%94%A8%E6%96%B9%E6%B3%95"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/guole.fun.png"/></div><div class="right"><p class="text">木木bber正确食用方法|美化日记</p><p class="url">https://blog.guole.fun/posts/butterfly-custom/#%E6%9C%A8%E6%9C%A8bber%E6%AD%A3%E7%A1%AE%E9%A3%9F%E7%94%A8%E6%96%B9%E6%B3%95</p></div></a></div><div class="tag link"><a class="link-card" title="ispeak-bber原作者：小康博客" href="https://www.antmoe.com/"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/antmoe.jpg"/></div><div class="right"><p class="text">ispeak-bber原作者：小康博客</p><p class="url">https://www.antmoe.com/</p></div></a></div>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;一些感动瞬间，很想记录下来，之前使用的&lt;code&gt;bber&lt;/code&gt;很强大，但是在音乐分享方面没有支持，最近摸鱼，就折腾出来了。  &lt;/p&gt;
&lt;h2 id=&quot;包含&quot;&gt;&lt;a href=&quot;#包含&quot; class=&quot;headerlink&quot; title=&quot;包含&quot;&gt;&lt;/a&gt;包含&lt;/</summary>
      
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Butterfly美化" scheme="https://blog.guole.fun/tags/Butterfly%E7%BE%8E%E5%8C%96/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>看星星，做个彩色的梦</title>
    <link href="https://blog.guole.fun/posts/meteor/"/>
    <id>https://blog.guole.fun/posts/meteor/</id>
    <published>2021-08-14T15:05:01.000Z</published>
    <updated>2026-01-02T20:54:12.000Z</updated>
    
    <content type="html"><![CDATA[<p>有时候真想回到那年夏天，躺在草垛上，看星星，看萤火虫，再做个彩色的梦。  </p><style>[data-theme=dark] {--card-bg: rgba(24, 29, 39, 0) !important;} #content-inner #post {border: unset !important;} .post-outdate-notice, #post-firstinfo {display:none;} #content-inner #post {box-shadow: unset !important;} #post {background: unset !important;}</style><div class="music" id="music"></div><script src="/js/APlayer.min.js"></script><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><a href="https://blog.justlovesmile.top/posts/6a260bf6.html" target="_blank">* 背景星空js来自这里</a><script>function initMusic() {  const ap = new APlayer({          container: document.getElementById('music'),          lrcType: 1,          mini: false,          autoplay: true,          loop: 'one',          order: 'random',          preload: 'auto',          volume: 0.7,          mutex: true,          listFolded: false,          listMaxHeight: 90,          audio: [{              name: '稻香',              artist: '周杰伦',              url: 'https://cdn.guole.fun/mp3/%E7%A8%BB%E9%A6%99.mp3',              cover: 'https://cdn.guole.fun/img/gallery/jay/jay20.jpg',              lrc: '[00:00.10]周杰伦 - 稻香\n[00:01.09]词：周杰伦\n[00:01.90]曲：周杰伦\n[00:31.19]对这个世界如果你有太多的抱怨\n[00:34.44]跌倒了就不敢继续往前走\n[00:37.43]为什么人要这么的脆弱堕落\n[00:41.63]请你打开电视看看\n[00:43.25]多少人为生命在努力勇敢的走下去\n[00:47.23]我们是不是该知足\n[00:49.76]珍惜一切就算没有拥有\n[00:54.28]还记得你说家是唯一的城堡\n[00:57.88]随着稻香河流继续奔跑\n[01:00.88]微微笑小时候的梦我知道\n[01:06.05]不要哭让萤火虫带着你逃跑\n[01:09.55]乡间的歌谣永远的依靠\n[01:12.59]回家吧回到最初的美好\n[01:41.41]不要这么容易就想放弃就像我说的\n[01:44.90]追不到的梦想换个梦不就得了\n[01:48.08]为自己的人生鲜艳上色\n[01:50.12]先把爱涂上喜欢的颜色\n[01:53.18]笑一个吧功成名就不是目的\n[01:55.97]让自己快乐快乐这才叫做意义\n[01:58.90]童年的纸飞机\n[02:00.27]现在终于飞回我手里\n[02:04.54]所谓的那快乐\n[02:05.81]赤脚在田里追蜻蜓追到累了\n[02:08.86]偷摘水果被蜜蜂给叮到怕了\n[02:11.96]谁在偷笑呢\n[02:13.52]我靠着稻草人吹着风唱着歌睡着了\n[02:16.81]哦哦午后吉他在虫鸣中更清脆\n[02:19.75]哦哦阳光洒在路上就不怕心碎\n[02:23.35]珍惜一切就算没有拥有\n[02:28.08]还记得你说家是唯一的城堡\n[02:31.53]随着稻香河流继续奔跑\n[02:34.47]微微笑小时候的梦我知道\n[02:39.70]不要哭让萤火虫带着你逃跑\n[02:43.22]乡间的歌谣永远的依靠\n[02:46.13]回家吧回到最初的美好\n[02:51.47]还记得你说家是唯一的城堡\n[02:54.95]随着稻香河流继续奔跑\n[02:57.80]微微笑小时候的梦我知道\n[03:03.02]不要哭让萤火虫带着你逃跑\n[03:06.67]乡间的歌谣永远的依靠\n[03:09.63]回家吧回到最初的美好'          }]        });  }try {  let themeData = JSON.parse(localStorage.getItem("theme")).value;  console.log("themeData : ", themeData)  document.addEventListener('DOMContentLoaded', function () {    initMusic();    document.documentElement.setAttribute("data-theme", "dark");  })  document.addEventListener("pjax:complete", (function () {    initMusic();    document.documentElement.setAttribute("data-theme", "dark");  }))  document.addEventListener("beforeunload", (function () {    ap.destroy();    document.documentElement.setAttribute("data-theme", themeData);  }))} catch (err) {    console.error(err);}</script>]]></content>
    
    
    <summary type="html">想回到过去，试着让故事继续……</summary>
    
    
    
    <category term="胡思乱想" scheme="https://blog.guole.fun/categories/%E8%83%A1%E6%80%9D%E4%B9%B1%E6%83%B3/"/>
    
    
    <category term="找点儿乐子" scheme="https://blog.guole.fun/tags/%E6%89%BE%E7%82%B9%E5%84%BF%E4%B9%90%E5%AD%90/"/>
    
  </entry>
  
  <entry>
    <title>使用Hexo-tag-map插件，给文章插入高德百度谷歌等5类9种地图</title>
    <link href="https://blog.guole.fun/posts/41887/"/>
    <id>https://blog.guole.fun/posts/41887/</id>
    <published>2021-07-29T15:23:07.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>给你的 Hexo 文章插入交互式地图吧！支持GoogleMap、高德地图、百度地图、Geoq地图、openstreetMap常规地图+卫星地图+卫星标注地图！一个强大的地图插件。  </p><h2 id="演示"><a href="#演示" class="headerlink" title="演示"></a>演示</h2><link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div class="map-box" style="margin: 0.8rem 0 1.6rem 0;"><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:'高德地图'});var imgm=L.tileLayer.chinaProvider('GaoDe.Satellite.Map',{maxZoom:20,minZoom:1,attribution:'高德地图'});var imga=L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion',{maxZoom:20,minZoom:1,attribution:'高德地图'});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:15,layers:[normal],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><div class="tag link"><a class="link-card" title="点击查看Demo页面" href="/map/"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/guole.fun.png"/></div><div class="right"><p class="text">点击查看Demo页面</p><p class="url">/map/</p></div></a></div><details blue><summary> 点击查看其他地图效果 </summary>              <div class='content'>              <div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">混合地图</button><button type="button" class="tab">googleMap</button><button type="button" class="tab">高德地图</button><button type="button" class="tab">百度地图</button><button type="button" class="tab">geoqMap</button><button type="button" class="tab">openstreetMap</button></div><div class="tab-contents"><div class="tab-item-content active"><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202107/hunhe1.jpg","alt":"混合地图","title":""},{"url":"https://cdn.guole.fun/img/202107/hunhe2.jpg","alt":"混合地图","title":""},{"url":"https://cdn.guole.fun/img/202107/hunhe3.jpg","alt":"混合地图","title":""},{"url":"https://cdn.guole.fun/img/202107/hunhe4.jpg","alt":"混合地图","title":""},{"url":"https://cdn.guole.fun/img/202107/hunhe5.jpg","alt":"混合地图","title":""},{"url":"https://cdn.guole.fun/img/202107/hunhe6.jpg","alt":"混合地图","title":""},{"url":"https://cdn.guole.fun/img/202107/hunhe7.jpg","alt":"混合地图","title":""}]</div>  </div></div><div class="tab-item-content"><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202107/google1.jpg","alt":"谷歌地图","title":""},{"url":"https://cdn.guole.fun/img/202107/google2.jpg","alt":"谷歌地图","title":""},{"url":"https://cdn.guole.fun/img/202107/google3.jpg","alt":"谷歌地图","title":""}]</div>  </div></div><div class="tab-item-content"><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202107/gaode1.jpg","alt":"高德地图","title":""},{"url":"https://cdn.guole.fun/img/202107/gaode2.jpg","alt":"高德地图","title":""},{"url":"https://cdn.guole.fun/img/202107/gaode3.png","alt":"高德地图","title":""}]</div>  </div></div><div class="tab-item-content"><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202107/baidu1.jpg","alt":"百度地图","title":""},{"url":"https://cdn.guole.fun/img/202107/baidu2.jpg","alt":"百度地图","title":""},{"url":"https://cdn.guole.fun/img/202107/baidu3.jpg","alt":"百度地图","title":""}]</div>  </div></div><div class="tab-item-content"><div class="gallery-container" data-type="data" data-button="" data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://cdn.guole.fun/img/202107/baidu1.jpg","alt":"Geoq地图","title":""},{"url":"https://cdn.guole.fun/img/202107/baidu2.jpg","alt":"Geoq地图","title":""},{"url":"https://cdn.guole.fun/img/202107/baidu3.jpg","alt":"Geoq地图","title":""},{"url":"https://cdn.guole.fun/img/202107/baidu4.jpg","alt":"Geoq地图","title":""},{"url":"https://cdn.guole.fun/img/202107/baidu5.jpg","alt":"Geoq地图","title":""}]</div>  </div></div><div class="tab-item-content"><p><img src="https://cdn.guole.fun/img/202107/openstreet.jpg" alt="openstreetMap"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>              </div>            </details><h2 id="更新记录"><a href="#更新记录" class="headerlink" title="更新记录"></a>更新记录</h2><details green><summary> 点击查看更新日志v1.2.1 </summary>              <div class='content'>              <div class="timeline "><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2023-06-24 <a href="https://www.npmjs.com/package/hexo-tag-map">1.2.1</a></p></div>        </div>        <div class='timeline-item-content'><ol><li>优化地图容器样式，增加间距 <code>margin: 0.8rem 0 1.6rem 0;</code> <br></li><li>更换依赖包为 <code>unpkg.com</code> <br></li></ol></div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2022-07-01 <a href="https://www.npmjs.com/package/hexo-tag-map">1.2.0</a></p></div>        </div>        <div class='timeline-item-content'><p>调整地图上供应商的名称，视觉体验更好；标签名称兼容大小写，如 <link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/proj4@2.4.3.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/proj4leaflet@1.0.1.min.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div id="baiduMap-110.073028-34.497647" 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('Baidu.Normal.Map',{maxZoom:20,minZoom:4,attribution:'Baidu Map'}),satelliteMap=L.tileLayer.chinaProvider('Baidu.Satellite.Map',{maxZoom:18,minZoom:1,attribution:'Baidu Map'}),annotionMap=L.tileLayer.chinaProvider('Baidu.Satellite.Annotion',{maxZoom:18,minZoom:1,attribution:'Baidu Map'});var imageMap=L.layerGroup([satelliteMap,annotionMap]);var baseLayers={"百度地图":normalMap,"百度卫星图":satelliteMap,"百度卫星标注":imageMap};var mymap=L.map("baiduMap-110.073028-34.497647",{crs:L.CRS.Baidu,minZoom:2,maxZoom:20,attributionControl:true,center:[34.497647,110.073028],zoom:14,layers:[normalMap],zoomControl:false});L.control.layers(baseLayers,overlayLayers).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['34.497647','110.073028']).addTo(mymap);marker.bindPopup("这里是西岳华山，海拔2154.9米！").openPopup();</script>和 <link rel="stylesheet" href="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/proj4@2.4.3.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/proj4leaflet@1.0.1.min.js"></script><script data-pjax src="//unpkg.com/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div id="baiduMap-110.073028-34.497647" 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('Baidu.Normal.Map',{maxZoom:20,minZoom:4,attribution:'Baidu Map'}),satelliteMap=L.tileLayer.chinaProvider('Baidu.Satellite.Map',{maxZoom:18,minZoom:1,attribution:'Baidu Map'}),annotionMap=L.tileLayer.chinaProvider('Baidu.Satellite.Annotion',{maxZoom:18,minZoom:1,attribution:'Baidu Map'});var imageMap=L.layerGroup([satelliteMap,annotionMap]);var baseLayers={"百度地图":normalMap,"百度卫星图":satelliteMap,"百度卫星标注":imageMap};var mymap=L.map("baiduMap-110.073028-34.497647",{crs:L.CRS.Baidu,minZoom:2,maxZoom:20,attributionControl:true,center:[34.497647,110.073028],zoom:14,layers:[normalMap],zoomControl:false});L.control.layers(baseLayers,overlayLayers).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['34.497647','110.073028']).addTo(mymap);marker.bindPopup("这里是西岳华山，海拔2154.9米！").openPopup();</script>都可以使用<br></p></div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2021-08-26 <a href="https://www.npmjs.com/package/hexo-tag-map">1.1.8</a></p></div>        </div>        <div class='timeline-item-content'><p>优化百度地图图层展示，卫星标注图不再单独作为复选图层<br></p></div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2021-07-29 <a href="https://www.npmjs.com/package/hexo-tag-map">1.0.8 -&gt; 1.1.1</a></p></div>        </div>        <div class='timeline-item-content'><ol><li>发布第一个正式版本 <br></li><li>若干优化 <br></li></ol></div>      </div></div>              </div>            </details><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><p>将各类交互式地图呈现到你的网站！    </p><p><strong>包含</strong></p><div class='checkbox plus blue checked'><input type="checkbox" checked="checked"/>            <p>[混合地图]一个混合切换GoogleMap、高德地图、Geoq地图，常规地图+卫星地图+卫星标注地图共7个图层的地图</p>            </div><div class='checkbox plus green checked'><input type="checkbox" checked="checked"/>            <p>[GoogleMap]一个单独的谷歌地图+谷歌卫星地图</p>            </div><div class='checkbox plus yellow checked'><input type="checkbox" checked="checked"/>            <p>[高德地图]一个单独的高德地图+高德卫星地图+高德卫星标注地图</p>            </div><div class='checkbox plus red checked'><input type="checkbox" checked="checked"/>            <p>[百度地图]一个单独的百度地图+百度卫星地图</p>            </div><div class='checkbox plus cyan checked'><input type="checkbox" checked="checked"/>            <p>[Geoq地图]一个单独的Geoq地图+5种显示风格</p>            </div><div class='checkbox plus blue checked'><input type="checkbox" checked="checked"/>            <p>[openstreetMap]一个单独的openstreetMap常规地图</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 green checked'><input type="checkbox" checked="checked"/>            <p>支持默认展示地图类型配置</p>            </div><div class='checkbox yellow checked'><input type="checkbox" checked="checked"/>            <p>用法超级简单，Butterfly已验证</p>            </div><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><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">npm i hexo-tag-map</span><br></pre></td></tr></table></figure><h2 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h2><div class="note warning flat"><p><strong>全局语法</strong></p></div><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">&#123;% + 标签值 + 经度 + 纬度 + 文本 + 缩放等级 + 宽 + 高 + 默认图层 + %&#125;</span><br></pre></td></tr></table></figure><p>如：</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">&#123;% map 120.101101,30.239119, 这里是西湖灵隐寺，据说求姻缘很灵验哦！, 15, 100%, 360px, 1 %&#125;</span><br></pre></td></tr></table></figure><h3 id="一些示例"><a href="#一些示例" class="headerlink" title="一些示例"></a>一些示例</h3><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">&#123;% map 120.101101,30.239119 %&#125;</span><br></pre></td></tr></table></figure><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">&#123;% googleMap 120.101101,30.239119, 这里是西湖灵隐寺，据说求姻缘很灵验哦！ %&#125;</span><br></pre></td></tr></table></figure><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">&#123;% gaodeMap 120.101101,30.239119, 这里是西湖灵隐寺，据说求姻缘很灵验哦！, 16 %&#125;</span><br></pre></td></tr></table></figure><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">&#123;% geoqMap 120.101101,30.239119, 这里是西湖灵隐寺，据说求姻缘很灵验哦！, 13, 90%, 320px, 3 %&#125;</span><br></pre></td></tr></table></figure><h2 id="参数取值"><a href="#参数取值" class="headerlink" title="参数取值"></a>参数取值</h2><p>表1：  </p><table><thead><tr><th>地图名</th><th>标签值&lt;必填&gt;</th><th>经度(-180~180)</th><th>纬度(-90~90)</th><th>文本</th><th>缩放等级(默认14)</th></tr></thead><tbody><tr><td>混合地图</td><td>map</td><td>坐标经度</td><td>坐标纬度</td><td>文本</td><td>取值3~18</td></tr><tr><td>谷歌地图</td><td>googleMap</td><td>坐标经度</td><td>坐标纬度</td><td>文本</td><td>取值1~20</td></tr><tr><td>高德地图</td><td>gaodeMap</td><td>坐标经度</td><td>坐标纬度</td><td>文本</td><td>取值3~18</td></tr><tr><td>百度地图</td><td>baiduMap</td><td>坐标经度</td><td>坐标纬度</td><td>文本</td><td>取值4~18</td></tr><tr><td>Geoq地图</td><td>geoqMap</td><td>坐标经度</td><td>坐标纬度</td><td>文本</td><td>取值1~18</td></tr><tr><td>openstreet地图</td><td>openstreetMap</td><td>坐标经度</td><td>坐标纬度</td><td>文本</td><td>取值1~18</td></tr></tbody></table><p>表2：  </p><table><thead><tr><th>地图名</th><th>宽(默认100%) &#x2F; 高(默认360px)</th><th>默认图层(默认1)</th></tr></thead><tbody><tr><td>混合地图</td><td>百分数或具体值(100%或360px)</td><td>取值1~7</td></tr><tr><td>谷歌地图</td><td>百分数或具体值(100%或360px)</td><td>取值1~3</td></tr><tr><td>高德地图</td><td>百分数或具体值(100%或360px)</td><td>取值1~3</td></tr><tr><td>百度地图</td><td>百分数或具体值(100%或360px)</td><td>取值1~2</td></tr><tr><td>Geoq地图</td><td>百分数或具体值(100%或360px)</td><td>取值1~5</td></tr><tr><td>openstreet地图</td><td>百分数或具体值(100%或360px)</td><td>不支持此参数</td></tr></tbody></table><div class="note danger flat"><ol><li>参数之间，用<strong>英文逗号</strong>相隔</li><li>参数必须按上述事例顺序输入，不得为空</li><li><font color=#0089ff><strong>同一个页面，同一组经纬度值，只能插入一个相同标签值的地图</strong></font>(若有需要，可以将第二个地图上，经度或纬度末尾删除一两个数)</li><li>参数取值必须在上述范围内</li><li>默认图层：即地图叠加层的值，默认常规地图还是卫星地图，可按地图显示顺序取值</li><li><strong>缩放等级，数字越大，地图比例尺越小，显示的越精细</strong></li><li>除<strong>标签值</strong>外，其他参数选填，但 <font color=#FF0000><strong>每个参数的左边的参数必填</strong></font></li><li>谷歌地图需要外网才能加载查看</li></ol></div><h2 id="坐标经纬度获取"><a href="#坐标经纬度获取" class="headerlink" title="坐标经纬度获取"></a>坐标经纬度获取</h2><p>坐标经纬度只分两种情况，百度地图 or 非百度地图。虽然都采用了坐标参考系统 (CRS)，即 EPSG:3857，但实测百度地图还是会有偏差。因此，分开取坐标经纬度即可解决。  </p><h3 id="其他地图"><a href="#其他地图" class="headerlink" title="其他地图"></a>其他地图</h3><p>包括GoogleMap、高德地图、Geoq地图、openstreetMap，均可共用一个坐标值。在高德官网，坐标拾取器页面获取即可。</p><div class="tag link"><a class="link-card" title="高德地图坐标拾取系统" href="https://lbs.amap.com/tools/picker"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/高德地图.png"/></div><div class="right"><p class="text">高德地图坐标拾取系统</p><p class="url">https://lbs.amap.com/tools/picker</p></div></a></div><h3 id="百度地图"><a href="#百度地图" class="headerlink" title="百度地图"></a>百度地图</h3><p>百度地图经纬度坐标值，可在百度地图坐标拾取页面获得。</p><div class="tag link"><a class="link-card" title="百度地图坐标拾取系统" href="https://api.map.baidu.com/lbsapi/getpoint/index.html"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/百度地图.png"/></div><div class="right"><p class="text">百度地图坐标拾取系统</p><p class="url">https://api.map.baidu.com/lbsapi/getpoint/index.html</p></div></a></div><h2 id="鸣谢"><a href="#鸣谢" class="headerlink" title="鸣谢"></a>鸣谢</h2><p>感谢<code>Leaflet.js</code>及其开发者，感谢<code>Leaflet.ChineseTmsProviders</code>及其开发者。</p><div class="tag link"><a class="link-card" title="Leaflet.js" href="https://api.map.baidu.com/lbsapi/getpoint/index.html"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/github.png"/></div><div class="right"><p class="text">Leaflet.js</p><p class="url">https://api.map.baidu.com/lbsapi/getpoint/index.html</p></div></a></div><div class="tag link"><a class="link-card" title="Leaflet.ChineseTmsProviders" href="https://github.com/htoooth/Leaflet.ChineseTmsProviders"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/github.png"/></div><div class="right"><p class="text">Leaflet.ChineseTmsProviders</p><p class="url">https://github.com/htoooth/Leaflet.ChineseTmsProviders</p></div></a></div><div class="tag link"><a class="link-card" title="本项目仓库" href="https://github.com/kuole-o/hexo-tag-map"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/github.png"/></div><div class="right"><p class="text">本项目仓库</p><p class="url">https://github.com/kuole-o/hexo-tag-map</p></div></a></div><div class="tag link"><a class="link-card" title="本项目 NPM 页面" href="https://www.npmjs.com/package/hexo-tag-map"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/npm.png"/></div><div class="right"><p class="text">本项目 NPM 页面</p><p class="url">https://www.npmjs.com/package/hexo-tag-map</p></div></a></div>]]></content>
    
    
    <summary type="html">给你的 Hexo 文章插入交互式地图吧！支持GoogleMap、高德地图、百度地图、Geoq地图、openstreetMap常规地图+卫星地图+卫星标注地图！一个强大的地图插件。</summary>
    
    
    
    <category term="NPM插件" scheme="https://blog.guole.fun/categories/NPM%E6%8F%92%E4%BB%B6/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Butterfly美化" scheme="https://blog.guole.fun/tags/Butterfly%E7%BE%8E%E5%8C%96/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>使用Charts插件给Butterfly增加统计图表</title>
    <link href="https://blog.guole.fun/posts/18158/"/>
    <id>https://blog.guole.fun/posts/18158/</id>
    <published>2021-07-26T18:47:34.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="写在开始"><a href="#写在开始" class="headerlink" title="写在开始"></a>写在开始</h2><p>之前就想给blog加上统计图表，查到的方法无奈要么太复杂，要么插件有bug，于是干脆自己插件化了一个<code>hexo-butterfly-charts</code>。</p><h2 id="效果演示"><a href="#效果演示" class="headerlink" title="效果演示"></a>效果演示</h2><div class="tag link"><a class="link-card" title="点击查看Demo页面" href="/charts/"><div class="left"><img class="no-lightbox" src="https://cdn.guole.fun/logo/guole.fun.png"/></div><div class="right"><p class="text">点击查看Demo页面</p><p class="url">/charts/</p></div></a></div><details blue><summary> 点击查看截图 </summary>              <div class='content'>              <div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">文章发布日历效果</button><button type="button" class="tab">文章发布统计效果</button><button type="button" class="tab">标签统计效果</button><button type="button" class="tab">分类统计效果</button><button type="button" class="tab">分类雷达图效果</button></div><div class="tab-contents"><div class="tab-item-content active"><p><img src="/posts/18158/%E5%8F%91%E5%B8%83%E6%97%A5%E5%8E%863.jpg" alt="发布日历"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E5%8F%91%E5%B8%83%E7%BB%9F%E8%AE%A13.jpg" alt="发布统计"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E6%A0%87%E7%AD%BE3.jpg" alt="标签统计"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E5%88%86%E7%B1%BB%E7%BB%9F%E8%AE%A13.jpg" alt="分类统计"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E5%88%86%E7%B1%BB%E9%9B%B7%E8%BE%BE3.jpg" alt="分类雷达"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>              </div>            </details><details blue><summary> 点击查看暗色模式下的截图 </summary>              <div class='content'>              <div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">文章发布日历效果</button><button type="button" class="tab">文章发布统计效果</button><button type="button" class="tab">标签统计效果</button><button type="button" class="tab">分类统计效果</button><button type="button" class="tab">分类雷达图效果</button></div><div class="tab-contents"><div class="tab-item-content active"><p><img src="/posts/18158/%E5%8F%91%E5%B8%83%E6%97%A5%E5%8E%864.jpg" alt="发布日历"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E5%8F%91%E5%B8%83%E7%BB%9F%E8%AE%A14.jpg" alt="发布统计"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E6%A0%87%E7%AD%BE4.jpg" alt="标签统计"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E5%88%86%E7%B1%BB%E7%BB%9F%E8%AE%A14.jpg" alt="分类统计"></p></div><div class="tab-item-content"><p><img src="/posts/18158/%E5%88%86%E7%B1%BB%E9%9B%B7%E8%BE%BE4.jpg" alt="分类雷达"></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div>              </div>            </details><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><p>将 hexo poats、类别和标签的统计数据呈现到图表中。  </p><blockquote><p>灵感来自 HEXO 主题 <a href="https://github.com/blinkfox/hexo-theme-matery">matery</a>.</p></blockquote><p><strong>包含</strong></p><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>发布统计图</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>发布日历图</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>标签统计图</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>分类统计图</p>            </div><div class='checkbox green 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 blue checked'><input type="checkbox" checked="checked"/>            <p>支持标签&#x2F;分类统计图横坐标间隔数自定义配置</p>            </div><div class='checkbox red checked'><input type="checkbox" checked="checked"/>            <p>适配butterfly暗色模式<u>（有瑕疵）</u></p>            </div><h2 id="更新记录"><a href="#更新记录" class="headerlink" title="更新记录"></a>更新记录</h2><details green><summary> 点击查看更新日志 </summary>              <div class='content'>              <div class="timeline "><div class='timeline-item headline'>        <div class='timeline-item-title'>          <div class='item-circle'><p>hexo-butterfly-charts更新日志</p></div>        </div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2023-05-19 [1.1.4 -&gt; 1.1.45]</p></div>        </div>        <div class='timeline-item-content'><ol><li>插件默认 <code>echarts_CDN</code> 修改为：<code>https://lib.baomitu.com/echarts/4.7.0/echarts.min.js</code>    </li><li>新增配置项：<code>echarts_CDN</code> 解决原来使用的固定 CDN 资源失效问题。使用方法：  <figure class="highlight yml"><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 class="comment"># 统计图表，支持发布文章统计、发布日历、Top标签统计、分类统计、分类雷达。</span></span><br><span class="line"><span class="comment"># see https://www.npmjs.com/package/hexo-butterfly-charts</span></span><br><span class="line"><span class="attr">charts:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span> <span class="comment"># 是否启用功能</span></span><br><span class="line">  <span class="attr">postsChart:</span></span><br><span class="line">    <span class="attr">title:</span> <span class="string">文章发布统计</span> <span class="comment"># 设置文章发布统计的标题，默认为空</span></span><br><span class="line">    <span class="attr">interval:</span> <span class="number">1</span> <span class="comment"># 横坐标间隔</span></span><br><span class="line">  <span class="attr">tagsChart:</span></span><br><span class="line">    <span class="attr">title:</span> <span class="string">Top</span> <span class="number">10</span> <span class="string">标签统计</span> <span class="comment"># 设置标签统计的标题，默认为空</span></span><br><span class="line">    <span class="attr">interval:</span> <span class="number">1</span> <span class="comment"># 横坐标间隔</span></span><br><span class="line">  <span class="attr">postsCalendar_title:</span> <span class="string">文章发布日历</span> <span class="comment"># 设置发布日历的标题，默认为空</span></span><br><span class="line">  <span class="attr">categoriesChart_title:</span> <span class="comment"># 设置分类统计的标题，默认为空</span></span><br><span class="line">  <span class="attr">categoriesRadar_title:</span> <span class="comment"># 设置分类雷达的标题，默认为空</span></span><br><span class="line"><span class="string">+</span> <span class="attr">echarts_CDN:</span> <span class="comment"># https://lib.baomitu.com/echarts/4.7.0/echarts.min.js</span></span><br></pre></td></tr></table></figure></li></ol></div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2023-01-22 [1.1.1 -&gt; 1.1.4]</p></div>        </div>        <div class='timeline-item-content'><ol><li>调整分类统计图中，“# 文章分类”为 “✒️文章篇数”   </li><li>更新 <code>moment</code> 到 <code>2.29.4</code></li></ol></div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2021-07-26 <a href="https://www.npmjs.com/package/hexo-butterfly-charts">1.1.0 -&gt; 1.1.1</a></p></div>        </div>        <div class='timeline-item-content'><ol><li>调整README.md，增加Demo页面</li></ol></div>      </div><div class='timeline-item'>        <div class='timeline-item-title'>          <div class='item-circle'><p>2021-07-24 <a href="https://www.npmjs.com/package/hexo-butterfly-charts">1.1.0</a></p></div>        </div>        <div class='timeline-item-content'><ol><li>增加柱状图表横纵坐标轴名称</li><li>适配Butterfly暗色模式，自动切换</li><li>文章发布日历，坐标也换成中文</li><li>各图表标题支持配置</li><li>解决雷达图上，鼠标hover时，超出内容被画布吞掉的问题</li><li>解决分类雷达图未设置画布高度，导致无法显示的bug</li></ol></div>      </div></div><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>请在主题项目根目录下，执行以下命令安装（安装过其他Charts插件，请先卸载）：</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">npm i hexo-butterfly-charts --save</span><br></pre></td></tr></table></figure><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>在主题配置文件<code>_config.butterfly.yml</code>或hexo配置文件<code>_config.yml</code>中增加以下内容：</p><table><thead><tr><th>参数</th><th>默认值</th><th>释义</th></tr></thead><tbody><tr><td>enable</td><td>无</td><td>【必填】开启或关闭，<code>true</code> or <code>false</code></td></tr><tr><td>postsChart.Title</td><td>空</td><td>发布统计的标题</td></tr><tr><td>postsChart.interval</td><td>0</td><td>坐标轴值得间隔数。0表示强制显示所有；可填写0以上的正整数，如1就是横坐标间隔1个再展示</td></tr><tr><td>postsCalendar_Title</td><td>空</td><td>发布日历的标题</td></tr><tr><td>tagsChart.Title</td><td>空</td><td>标签统计的标题</td></tr><tr><td>tagsChart.interval</td><td>0</td><td>坐标轴值得间隔数。0表示强制显示所有；可填写0以上的正整数，如1就是横坐标间隔1个再展示</td></tr><tr><td>categoriesChart_Title</td><td>空</td><td>分类统计的标题</td></tr><tr><td>categoriesRadar_Title</td><td>空</td><td>分类雷达的标题</td></tr><tr><td>echarts_CDN</td><td>baomitu资源</td><td>echarts 自定义 CDN</td></tr></tbody></table><br><figure class="highlight yml"><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 class="comment"># 统计图表，支持发布文章统计、发布日历、Top标签统计、分类统计、分类雷达。</span></span><br><span class="line"><span class="comment"># see https://www.npmjs.com/package/hexo-butterfly-charts</span></span><br><span class="line"><span class="attr">charts:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span> <span class="comment"># 是否启用功能</span></span><br><span class="line">  <span class="attr">postsChart:</span></span><br><span class="line">    <span class="attr">title:</span> <span class="string">文章发布统计</span> <span class="comment"># 设置文章发布统计的标题，默认为空</span></span><br><span class="line">    <span class="attr">interval:</span> <span class="number">1</span> <span class="comment"># 横坐标间隔</span></span><br><span class="line">  <span class="attr">tagsChart:</span></span><br><span class="line">    <span class="attr">title:</span> <span class="string">Top</span> <span class="number">10</span> <span class="string">标签统计</span> <span class="comment"># 设置标签统计的标题，默认为空</span></span><br><span class="line">    <span class="attr">interval:</span> <span class="number">1</span> <span class="comment"># 横坐标间隔</span></span><br><span class="line">  <span class="attr">postsCalendar_Title:</span> <span class="comment">#文章发布日历 # 设置发布日历的标题，默认为空</span></span><br><span class="line">  <span class="attr">categoriesChart_Title:</span> <span class="comment"># 设置分类统计的标题，默认为空</span></span><br><span class="line">  <span class="attr">categoriesRadar_Title:</span> <span class="comment"># 设置分类雷达的标题，默认为空</span></span><br><span class="line">  <span class="attr">echarts_CDN:</span> <span class="comment"># https://lib.baomitu.com/echarts/4.7.0/echarts.min.js</span></span><br></pre></td></tr></table></figure>              </div>            </details><h2 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h2><p>由于标签&#x2F;分类&#x2F;归档页面结构太相似，npm插件配置添加较难实现，因此安装插件后，还需主题源代码中添加节点ID。（好吧 是我菜……）  </p><h3 id="将发布日历添加到-归档-页面"><a href="#将发布日历添加到-归档-页面" class="headerlink" title="将发布日历添加到 归档 页面"></a>将发布日历添加到 归档 页面</h3><details yellow><summary> 点击查看详情 </summary>              <div class='content'>              <p>安装插件后，在<code>/Butterfly/layout/archive.pug</code>文件中，<code>#archive</code>下面添加一行<code>#posts-calendar.js-pjax</code>, 新添加的比上一行多缩进两个空格。</p><p>修改后如下：</p><figure class="highlight plaintext"><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">extends includes/layout.pug</span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line">  include ./includes/mixins/article-sort.pug</span><br><span class="line">  #archive</span><br><span class="line">    #posts-calendar.js-pjax</span><br><span class="line">    .article-sort-title= _p(&#x27;page.articles&#x27;) + &#x27; - &#x27; + site.posts.length</span><br><span class="line">    +articleSort(page.posts)</span><br><span class="line">    include includes/pagination.pug</span><br></pre></td></tr></table></figure><h4 id="其他页面，只需md文件中插入这个标签："><a href="#其他页面，只需md文件中插入这个标签：" class="headerlink" title="其他页面，只需md文件中插入这个标签："></a>其他页面，只需<code>md</code>文件中插入这个标签：</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;posts-calendar&quot;</span> <span class="attr">class</span>=<span class="string">&quot;js-pjax&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>              </div>            </details><h3 id="将-发布统计-添加到-归档-页面"><a href="#将-发布统计-添加到-归档-页面" class="headerlink" title="将 发布统计 添加到 归档 页面"></a>将 发布统计 添加到 归档 页面</h3><details yellow><summary> 点击查看详情 </summary>              <div class='content'>              <p>安装插件后，在<code>/Butterfly/layout/archive.pug</code>文件中，<code>#archive</code>下面添加一行<code>#posts-chart.js-pjax</code>, 新添加的比上一行多缩进两个空格。</p><p>修改后如下：</p><figure class="highlight plaintext"><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">extends includes/layout.pug</span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line">  include ./includes/mixins/article-sort.pug</span><br><span class="line">  #archive</span><br><span class="line">    #posts-chart.js-pjax</span><br><span class="line">    .article-sort-title= _p(&#x27;page.articles&#x27;) + &#x27; - &#x27; + site.posts.length</span><br><span class="line">    +articleSort(page.posts)</span><br><span class="line">    include includes/pagination.pug</span><br></pre></td></tr></table></figure><h4 id="其他页面，只需md文件中插入这个标签："><a href="#其他页面，只需md文件中插入这个标签：" class="headerlink" title="其他页面，只需md文件中插入这个标签："></a>其他页面，只需<code>md</code>文件中插入这个标签：</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;posts-chart&quot;</span> <span class="attr">class</span>=<span class="string">&quot;js-pjax&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>              </div>            </details><h3 id="将-标签统计-插入到-标签-页面"><a href="#将-标签统计-插入到-标签-页面" class="headerlink" title="将 标签统计 插入到 标签 页面"></a>将 标签统计 插入到 标签 页面</h3><details yellow><summary> 点击查看详情 </summary>              <div class='content'>              <p>编辑主题目录<code>/Butterfly/layout/includes/page/tags.pug</code>文件，在开头添加一行<code>#tags-chart(data-length = &quot;10&quot;).js-pjax</code>，<code>data-length = &quot;10&quot;</code>表示显示 Top 10 的标签。</p><p>修改后如下：</p><figure class="highlight plaintext"><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">#tags-chart(data-length = &quot;10&quot;).js-pjax</span><br><span class="line">.tag-cloud-title.is-center= _p(&#x27;page.tag&#x27;)</span><br><span class="line">  |  - </span><br><span class="line">  span.tag-cloud-amount= site.tags.length</span><br><span class="line">.tag-cloud-list.is-center</span><br><span class="line">  !=cloudTags(&#123;source: site.tags, minfontsize: 1.2, maxfontsize: 2.1, limit: 0, unit: &#x27;em&#x27;&#125;)</span><br></pre></td></tr></table></figure><h4 id="其他页面，只需md文件中插入这个标签："><a href="#其他页面，只需md文件中插入这个标签：" class="headerlink" title="其他页面，只需md文件中插入这个标签："></a>其他页面，只需<code>md</code>文件中插入这个标签：</h4><figure class="highlight html"><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 class="comment">&lt;!-- &quot;data-length&quot; = how many tags to show, default 10 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;tags-chart&quot;</span> <span class="attr">data-length</span>=<span class="string">&quot;10&quot;</span> <span class="attr">class</span>=<span class="string">&quot;js-pjax&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>              </div>            </details><h3 id="将-分类统计（无标题）和-分类雷达图（无标题）-添加到-分类-页面。"><a href="#将-分类统计（无标题）和-分类雷达图（无标题）-添加到-分类-页面。" class="headerlink" title="将 分类统计（无标题）和 分类雷达图（无标题） 添加到 分类 页面。"></a>将 分类统计（无标题）和 分类雷达图（无标题） 添加到 分类 页面。</h3><details yellow><summary> 点击查看详情 </summary>              <div class='content'>              <p>编辑主题目录<code>/Butterfly/layout/includes/page/categories.pug</code>文件，在第5行添加<code>#categories-chart.js-pjax</code>和<code>#categories-radar.js-pjax</code>。</p><p>修改后如下：</p><figure class="highlight plaintext"><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">.category-lists</span><br><span class="line">  .category-title.is-center= _p(&#x27;page.category&#x27;)</span><br><span class="line">    |  - </span><br><span class="line">    span.category-amount= site.categories.length</span><br><span class="line">  #categories-chart.js-pjax</span><br><span class="line">  #categories-radar.js-pjax</span><br><span class="line">  div!= list_categories()</span><br></pre></td></tr></table></figure><h4 id="其他页面，只需md文件中插入这个标签："><a href="#其他页面，只需md文件中插入这个标签：" class="headerlink" title="其他页面，只需md文件中插入这个标签："></a>其他页面，只需<code>md</code>文件中插入这个标签：</h4><ul><li><p>分类统计（无标题）</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;categories-chart&quot;</span> <span class="attr">class</span>=<span class="string">&quot;js-pjax&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>分类雷达图（无标题）</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;categories-radar&quot;</span> <span class="attr">class</span>=<span class="string">&quot;js-pjax&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ul><hr>              </div>            </details><h2 id="许可"><a href="#许可" class="headerlink" title="许可"></a>许可</h2><div class="tag link"><a class="link-card" title="Apache License 2.0" href="https://github.com/kuole-o/hexo-butterfly-charts/blob/main/LICENSE"><div class="left"><img class="no-lightbox" src="Apache_License_2.0.jpg"/></div><div class="right"><p class="text">Apache License 2.0</p><p class="url">https://github.com/kuole-o/hexo-butterfly-charts/blob/main/LICENSE</p></div></a></div> ]]></content>
    
    
    <summary type="html">将 Hexo 文章、类别和标签的统计数据呈现到图表中。</summary>
    
    
    
    <category term="NPM插件" scheme="https://blog.guole.fun/categories/NPM%E6%8F%92%E4%BB%B6/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Butterfly美化" scheme="https://blog.guole.fun/tags/Butterfly%E7%BE%8E%E5%8C%96/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>搭建微信通知API实现Twikoo新消息提醒</title>
    <link href="https://blog.guole.fun/posts/626/"/>
    <id>https://blog.guole.fun/posts/626/</id>
    <published>2021-07-19T16:35:32.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>Twikoo目前提供了Server 酱、Qmsg 酱、推送加 3种即时通知方式，可对我而言，总感觉不得劲儿。之前用推送加，却不能直接接收消息，URL也得手动复制查看，烦是不烦。  </p><details blue><summary> 服务对比 </summary>              <div class='content'>              <p><img src="/posts/626/%E5%AF%B9%E6%AF%94.jpg" alt="服务对比"></p>              </div>            </details><h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><details blue><summary> 效果预览 </summary>              <div class='content'>              <p><img src="/posts/626/%E6%95%88%E6%9E%9C.png" alt="自定义消息提醒API效果"></p>              </div>            </details><p>废话少说，自己琢磨清楚，就分享出来。通过本篇，你将获得：<strong>一个属于自己，不被别人卡脖子的Twikoo新评论提醒服务，不限量！！</strong></p><div class="note success flat"><p><strong>注意事项</strong><br><del>本文涉及修改 Twikoo 云函数源代码，请自行评估是否继续。</del> twikoo 1.4.5及以上版本直接配置，开箱即食。</p></div><h2 id="注册企业微信"><a href="#注册企业微信" class="headerlink" title="注册企业微信"></a>注册企业微信</h2><p>该功能通过企业微信的<code>应用</code>实现，注册企业微信太简单了，此处流程省略。  </p><h3 id="企业微信创建一个应用"><a href="#企业微信创建一个应用" class="headerlink" title="企业微信创建一个应用"></a>企业微信创建一个应用</h3><p>在“企业微信——应用管理”最底部的“自建”应用处，新建一个“应用”。名称比如就叫<code>消息通知</code>，配置完成后记录下应用页面的<code>AgentId</code>和<code>Secret</code>。注意，查看<code>Secret</code>需要安装一个企业微信，<strong>查看完可以卸载</strong>。  </p><p>在“企业微信——我的企业”底部，记录下“企业ID”。  </p><p>至此，微信配置完成，开始配置提醒API。</p><h2 id="关注企业微信"><a href="#关注企业微信" class="headerlink" title="关注企业微信"></a>关注企业微信</h2><p>用自己的常用微信，关注上面创建的企业微信。</p><div class="note warning flat"><p>若出现接口请求正常，企业微信接收消息正常，个人微信无法收到通知，请这样排查：  </p><ol><li>进入「我的企业」 → 「微信插件」，拉到最下方，勾选「允许成员在微信插件中接收和回复聊天消息 」</li><li>在企业微信客户端 「我」 → 「设置」 → 「新消息通知」中关闭「仅在企业微信中接受消息」限制条件</li></ol></div><h2 id="Twikoo配置"><a href="#Twikoo配置" class="headerlink" title="Twikoo配置"></a>Twikoo配置</h2><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">Twikoo v1.5.0 及以上版本配置</button><button type="button" class="tab">Twikoo v1.4.5 ~ v1.4.15</button><button type="button" class="tab">Twikoo v1.4.5 以下版本</button></div><div class="tab-contents"><div class="tab-item-content active"><h2 id="配置pushoo"><a href="#配置pushoo" class="headerlink" title="配置pushoo"></a>配置pushoo</h2><p>进入 <code>Twikoo</code>管理面板，在“及时通知”——“PUSHOO_CHANNEL”中，填写<code>wecom</code>，在<code>PUSHOO_TOKEN</code>中配置上文过程中申请到的企业微信构成的<code>PUSHOO_TOKEN</code>。  </p><p><code>PUSHOO_TOKEN</code>组成：  </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></pre></td><td class="code"><pre><span class="line">企业ID#应用Secret#应用ID拼接构成，中间用 “#” 号分隔，如：</span><br><span class="line">&gt; 企业ID#Secret#AgentId</span><br><span class="line">&gt; 例：ww97a01a*****1e5f1#xHapDXmgZtlBgRQQXMb4kfh3y75Ynoubl*****l9ytE#1000005</span><br></pre></td></tr></table></figure><p>至此，配置完成。换一个非博主邮箱，评论一条试试吧。</p></div><div class="tab-item-content"><h2 id="创建API云函数"><a href="#创建API云函数" class="headerlink" title="创建API云函数"></a>创建API云函数</h2><p>首先参考Heo 的教程，创建一个腾讯云或vercel版本的云函数。</p><p>我使用了腾讯云环境（也没多贵，相比vercel更稳定），简单说下过程：  </p><p>可以复用之前 Twikoo 那个云开发环境，直接创建一个新的云函数，名称自定义如<code>weixin-push</code>，选择<code>helloworld 空白模板函数</code>，<code>Python3.6</code>环境，<code>128MB</code>就OK了。下一步粘贴下面的代码，点击创建：  </p><figure class="highlight py"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf8 -*-</span></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">getTocken</span>(<span class="params"><span class="built_in">id</span>,secert,msg,agentId</span>):</span><br><span class="line">    url = <span class="string">&quot;https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=&quot;</span> + <span class="built_in">id</span> + <span class="string">&quot;&amp;corpsecret=&quot;</span> + secert</span><br><span class="line"></span><br><span class="line">    r =requests.get(url)</span><br><span class="line">    tocken_json = json.loads(r.text)</span><br><span class="line">    <span class="comment"># print(tocken_json[&#x27;access_token&#x27;])</span></span><br><span class="line">    sendText(tocken=tocken_json[<span class="string">&#x27;access_token&#x27;</span>],agentId=agentId,msg=msg)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">sendText</span>(<span class="params">tocken,agentId,msg</span>):</span><br><span class="line">    sendUrl = <span class="string">&quot;https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=&quot;</span> + tocken</span><br><span class="line">    <span class="comment"># print(sendUrl)</span></span><br><span class="line">    data = json.dumps(&#123;</span><br><span class="line">        <span class="string">&quot;safe&quot;</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="string">&quot;touser&quot;</span> : <span class="string">&quot;@all&quot;</span>,</span><br><span class="line">        <span class="string">&quot;msgtype&quot;</span> : <span class="string">&quot;text&quot;</span>,</span><br><span class="line">        <span class="string">&quot;agentid&quot;</span> : agentId,</span><br><span class="line">        <span class="string">&quot;text&quot;</span> : &#123;</span><br><span class="line">            <span class="string">&quot;content&quot;</span> : msg</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">    requests.post(sendUrl,data)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>(<span class="params">event, context</span>):</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        apiid=event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;id&#x27;</span>]</span><br><span class="line">        apisecert=event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;secert&#x27;</span>]</span><br><span class="line">        apiagentId = event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;agentId&#x27;</span>]</span><br><span class="line">        apimsg = event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;msg&#x27;</span>]</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        apimsg = <span class="string">&#x27;有必填参数没有填写，请检查是否填写正确和格式是否错误。详情可以参阅：https://blog.zhheo.com/p/1e9f35bc.html&#x27;</span></span><br><span class="line">        status = <span class="number">1</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            <span class="comment"># 执行主程序</span></span><br><span class="line">            getTocken(<span class="built_in">id</span>=apiid,secert=apisecert,msg=apimsg,agentId=apiagentId)</span><br><span class="line">        <span class="keyword">except</span>:</span><br><span class="line">            status = <span class="number">1</span></span><br><span class="line">            apimsg = <span class="string">&#x27;主程序运行时出现错误，请检查参数是否填写正确。详情可以参阅：https://blog.zhheo.com/p/1e9f35bc.html&#x27;</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            status = <span class="number">0</span></span><br><span class="line">    <span class="comment"># print(event)</span></span><br><span class="line">    <span class="comment"># print(&quot;Received event: &quot; + json.dumps(event, indent = 2)) </span></span><br><span class="line">    <span class="comment"># print(&quot;Received context: &quot; + str(context))</span></span><br><span class="line">    <span class="comment"># print(&quot;Hello world&quot;)</span></span><br><span class="line">    status_str = json.dumps(&#123;</span><br><span class="line">            <span class="string">&quot;status&quot;</span>:status,</span><br><span class="line">            <span class="string">&quot;msg&quot;</span>:apimsg</span><br><span class="line">        &#125;)</span><br><span class="line">    <span class="keyword">return</span>(status_str)</span><br></pre></td></tr></table></figure><p>配置好访问服务（如果第一次创建，参考 Twikoo 教程还需要配置安全域名等）：  </p><p><img src="/posts/626/%E4%BA%91%E5%87%BD%E6%95%B0.jpg" alt="配置云函数访问服务"></p><p>至此，云函数创建完成。可以使用下面这样的方式，拼接一个<code>URL</code>，浏览器访问，看看手机微信能不能接收到消息。  </p><p><strong>云函数的访问服务URL + 触发路径 + ?id&#x3D;你的企业微信ID + secert&#x3D;上文记录的secert + Id&#x3D;上文记录的AgentId + &amp;msg&#x3D;随便测试一下吧</strong></p><p>如我下面这样的：</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">https://blogpkly-13278c-1258453354.ap-shanghai.app.tcloudbase.com/weixin-push?id=ww*******&amp;secert=Ne******&amp;agentId=1000003&amp;msg=随便测试一下吧</span><br></pre></td></tr></table></figure><p>浏览器返回以下内容，说明配置完成(msg后的内容，是Unicode编码后的“随便测试一下吧”内容，<a href="https://tool.chinaz.com/tools/unicode.aspx" target="_blank">点击这里可以转换</a> )。  </p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span> <span class="attr">&quot;msg&quot;</span><span class="punctuation">:</span> <span class="string">&quot;\u968f\u4fbf\u6d4b\u8bd5\u4e00\u4e0b\u5427&quot;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>老方法修改云函数源代码方式已经PR给Twikoo，现已合入。  </p><h3 id="升级Twikoo云函数版本"><a href="#升级Twikoo云函数版本" class="headerlink" title="升级Twikoo云函数版本"></a>升级Twikoo云函数版本</h3><p>按照官方教程， 升级Twikoo到 v1.4.5 版本（最新版本）。<a href="https://twikoo.js.org/quick-start.html#%E7%89%88%E6%9C%AC%E6%9B%B4%E6%96%B0" title="Twikoo 中文文档：版本更新">Twikoo 中文文档：版本更新</a>  </p><p>在 Twikoo v1.4.5 及以上版本中，打开控制面板，在上述企业微信API搭建完成后，拼接成下述样式的<code>URL</code>，填写在<code>即时通知</code>——<code>WECOM_API_URL</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">https://blogpkly-13278c-1258453354.ap-shanghai.app.tcloudbase.com/weixin-push?id=企业微信获取&amp;secert=企业微信获取&amp;agentId=企业微信获取&amp;msg=</span><br></pre></td></tr></table></figure><p><img src="/posts/626/twikoo.png"></p><div class="note warning flat"><ol><li>使用自定义API提醒，请将其他Server 酱、Qmsg 酱、推送加 的<code>KEY</code>留空。  </li><li>若升级完云函数，网站前端页面配置面板未出现<code>WECOM_API_URL</code>配置项，Twikoo版本仍为 1.4.5 以下版本，可去主题配置文件<kbd>Ctrl</kbd> + <kbd>F</kbd>定位到<code>comments</code>，将<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">twikoo:</span> <span class="string">https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js</span></span><br></pre></td></tr></table></figure>改为<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">twikoo:</span> <span class="string">https://cdn.jsdelivr.net/npm/twikoo@1.4.5/dist/twikoo.all.min.js</span></span><br></pre></td></tr></table></figure></li></ol></div><p>微信关注自己的企业微信账号，然后用其他非博主邮箱在网站留言，试试即时通知吧！</p></div><div class="tab-item-content"><h2 id="创建API云函数"><a href="#创建API云函数" class="headerlink" title="创建API云函数"></a>创建API云函数</h2><p>首先参考Heo 的教程，创建一个腾讯云或vercel版本的云函数。</p><p>我使用了腾讯云环境（也没多贵，相比vercel更稳定），简单说下过程：  </p><p>可以复用之前 Twikoo 那个云开发环境，直接创建一个新的云函数，名称自定义如<code>weixin-push</code>，选择<code>helloworld 空白模板函数</code>，<code>Python3.6</code>环境，<code>128MB</code>就OK了。下一步粘贴下面的代码，点击创建：  </p><figure class="highlight py"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding: utf8 -*-</span></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">getTocken</span>(<span class="params"><span class="built_in">id</span>,secert,msg,agentId</span>):</span><br><span class="line">    url = <span class="string">&quot;https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=&quot;</span> + <span class="built_in">id</span> + <span class="string">&quot;&amp;corpsecret=&quot;</span> + secert</span><br><span class="line"></span><br><span class="line">    r =requests.get(url)</span><br><span class="line">    tocken_json = json.loads(r.text)</span><br><span class="line">    <span class="comment"># print(tocken_json[&#x27;access_token&#x27;])</span></span><br><span class="line">    sendText(tocken=tocken_json[<span class="string">&#x27;access_token&#x27;</span>],agentId=agentId,msg=msg)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">sendText</span>(<span class="params">tocken,agentId,msg</span>):</span><br><span class="line">    sendUrl = <span class="string">&quot;https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=&quot;</span> + tocken</span><br><span class="line">    <span class="comment"># print(sendUrl)</span></span><br><span class="line">    data = json.dumps(&#123;</span><br><span class="line">        <span class="string">&quot;safe&quot;</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="string">&quot;touser&quot;</span> : <span class="string">&quot;@all&quot;</span>,</span><br><span class="line">        <span class="string">&quot;msgtype&quot;</span> : <span class="string">&quot;text&quot;</span>,</span><br><span class="line">        <span class="string">&quot;agentid&quot;</span> : agentId,</span><br><span class="line">        <span class="string">&quot;text&quot;</span> : &#123;</span><br><span class="line">            <span class="string">&quot;content&quot;</span> : msg</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">    requests.post(sendUrl,data)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>(<span class="params">event, context</span>):</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        apiid=event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;id&#x27;</span>]</span><br><span class="line">        apisecert=event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;secert&#x27;</span>]</span><br><span class="line">        apiagentId = event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;agentId&#x27;</span>]</span><br><span class="line">        apimsg = event[<span class="string">&#x27;queryStringParameters&#x27;</span>][<span class="string">&#x27;msg&#x27;</span>]</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">        apimsg = <span class="string">&#x27;有必填参数没有填写，请检查是否填写正确和格式是否错误。详情可以参阅：https://blog.zhheo.com/p/1e9f35bc.html&#x27;</span></span><br><span class="line">        status = <span class="number">1</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            <span class="comment"># 执行主程序</span></span><br><span class="line">            getTocken(<span class="built_in">id</span>=apiid,secert=apisecert,msg=apimsg,agentId=apiagentId)</span><br><span class="line">        <span class="keyword">except</span>:</span><br><span class="line">            status = <span class="number">1</span></span><br><span class="line">            apimsg = <span class="string">&#x27;主程序运行时出现错误，请检查参数是否填写正确。详情可以参阅：https://blog.zhheo.com/p/1e9f35bc.html&#x27;</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            status = <span class="number">0</span></span><br><span class="line">    <span class="comment"># print(event)</span></span><br><span class="line">    <span class="comment"># print(&quot;Received event: &quot; + json.dumps(event, indent = 2)) </span></span><br><span class="line">    <span class="comment"># print(&quot;Received context: &quot; + str(context))</span></span><br><span class="line">    <span class="comment"># print(&quot;Hello world&quot;)</span></span><br><span class="line">    status_str = json.dumps(&#123;</span><br><span class="line">            <span class="string">&quot;status&quot;</span>:status,</span><br><span class="line">            <span class="string">&quot;msg&quot;</span>:apimsg</span><br><span class="line">        &#125;)</span><br><span class="line">    <span class="keyword">return</span>(status_str)</span><br></pre></td></tr></table></figure><p>配置好访问服务（如果第一次创建，参考 Twikoo 教程还需要配置安全域名等）：  </p><p><img src="/posts/626/%E4%BA%91%E5%87%BD%E6%95%B0.jpg" alt="配置云函数访问服务"></p><p>至此，云函数创建完成。可以使用下面这样的方式，拼接一个<code>URL</code>，浏览器访问，看看手机微信能不能接收到消息。  </p><p><strong>云函数的访问服务URL + 触发路径 + ?id&#x3D;你的企业微信ID + secert&#x3D;上文记录的secert + Id&#x3D;上文记录的AgentId + &amp;msg&#x3D;随便测试一下吧</strong></p><p>如我下面这样的：</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">https://blogpkly-13278c-1258453354.ap-shanghai.app.tcloudbase.com/weixin-push?id=ww*******&amp;secert=Ne******&amp;agentId=1000003&amp;msg=随便测试一下吧</span><br></pre></td></tr></table></figure><p>浏览器返回以下内容，说明配置完成(msg后的内容，是Unicode编码后的“随便测试一下吧”内容，<a href="https://tool.chinaz.com/tools/unicode.aspx" target="_blank">点击这里可以转换</a> )。  </p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;status&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span> <span class="attr">&quot;msg&quot;</span><span class="punctuation">:</span> <span class="string">&quot;\u968f\u4fbf\u6d4b\u8bd5\u4e00\u4e0b\u5427&quot;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>微信关注自己的企业号。  </p><h2 id="修改Twikoo云函数"><a href="#修改Twikoo云函数" class="headerlink" title="修改Twikoo云函数"></a>修改Twikoo云函数</h2><p>找到腾讯云开发<code>云函数/twikoo/函数代码/node_modules/twikoo-func/index.js</code>，在不破坏云函数原本逻辑基础上，总共修改 3 处。  </p><div class="note danger flat"><p>注意：打开云函数在线函数代码查看页面后，切不可直接关闭网页，关闭前点击“函数配置”切换到其他页面，再关闭，否则腾讯云网页抽风，再进入一直提示“拉取代码失败”，就很麻烦。</p></div>  <h3 id="第一处修改"><a href="#第一处修改" class="headerlink" title="第一处修改"></a>第一处修改</h3><p>在<code>云函数/twikoo/函数代码/node_modules/twikoo-func/index.js</code>大约 866 行，可 Ctrl+F 搜索定位到<code>Promise.all</code>在<code>await Promise.all([</code>内容下，增加一行<code>noticeWinxinPush(comment)</code>，改完后如下：  </p><figure class="highlight js"><figcaption><span>8</span></figcaption><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 class="comment">// 发送通知</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">sendNotice</span> (<span class="params">comment</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (comment.<span class="property">isSpam</span> &amp;&amp; config.<span class="property">NOTIFY_SPAM</span> === <span class="string">&#x27;false&#x27;</span>) <span class="keyword">return</span></span><br><span class="line">  <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>([</span><br><span class="line">    <span class="title function_">noticeMaster</span>(comment),</span><br><span class="line">    <span class="title function_">noticeReply</span>(comment),</span><br><span class="line">    <span class="title function_">noticeWeChat</span>(comment),</span><br><span class="line">    <span class="title function_">noticePushPlus</span>(comment),</span><br><span class="line">    <span class="title function_">noticeWinxinPush</span>(comment),<span class="comment">//新增内容</span></span><br><span class="line">    <span class="title function_">noticeQQ</span>(comment)</span><br><span class="line">  ]).<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;邮件通知异常：&#x27;</span>, err)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="第二处修改"><a href="#第二处修改" class="headerlink" title="第二处修改"></a>第二处修改</h3><p>在<code>云函数/twikoo/函数代码/node_modules/twikoo-func/index.js</code>大约 908 行，可 Ctrl+F 搜索定位到<code>const IM_PUSH_CONFIGS = [</code>在<code>&#39;PUSH_PLUS_TOKEN&#39;,</code>内容下，增加一行<code>&#39;WXPUSH_KEY&#39;</code>，改完后如下：  </p><figure class="highlight js"><figcaption><span>8</span></figcaption><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="comment">// 博主通知</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">noticeMaster</span> (<span class="params">comment</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (!transporter) <span class="keyword">if</span> (!<span class="keyword">await</span> <span class="title function_">initMailer</span>()) <span class="keyword">return</span></span><br><span class="line">  <span class="keyword">if</span> (config.<span class="property">BLOGGER_EMAIL</span> === comment.<span class="property">mail</span>) <span class="keyword">return</span></span><br><span class="line">  <span class="keyword">const</span> <span class="variable constant_">IM_PUSH_CONFIGS</span> = [</span><br><span class="line">    <span class="string">&#x27;SC_SENDKEY&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;QM_SENDKEY&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;PUSH_PLUS_TOKEN&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;WXPUSH_KEY&#x27;</span><span class="comment">//新增内容</span></span><br><span class="line">  ]</span><br></pre></td></tr></table></figure><h3 id="第三处修改"><a href="#第三处修改" class="headerlink" title="第三处修改"></a>第三处修改</h3><p>在<code>云函数/twikoo/函数代码/node_modules/twikoo-func/index.js</code>大约 1005 行，可 Ctrl+F 搜索定位到<code>pushplus 通知</code>在适当位置增加以下内容：  </p><figure class="highlight js"><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="comment">// weixin-push 通知</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">noticeWinxinPush</span> (<span class="params">comment</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (config.<span class="property">BLOGGER_EMAIL</span> === comment.<span class="property">mail</span>) <span class="keyword">return</span></span><br><span class="line">  <span class="keyword">const</span> wxContent = config.<span class="property">SITE_NAME</span> + <span class="string">&#x27;有新评论啦！🎉🎉&#x27;</span> + <span class="string">&#x27;\n\n&#x27;</span> + <span class="string">&#x27;@&#x27;</span> + comment.<span class="property">nick</span> + <span class="string">&#x27;说：&#x27;</span> + $(comment.<span class="property">comment</span>).<span class="title function_">text</span>() + <span class="string">&#x27;\n&#x27;</span> + <span class="string">&#x27;E-mail: &#x27;</span> + comment.<span class="property">mail</span> + <span class="string">&#x27;\n&#x27;</span> + <span class="string">&#x27;IP: &#x27;</span> + comment.<span class="property">ip</span> + <span class="string">&#x27;\n&#x27;</span> + <span class="string">&#x27;点此查看完整内容：&#x27;</span> + <span class="title function_">appendHashToUrl</span>(comment.<span class="property">href</span> || <span class="variable constant_">SITE_URL</span> + comment.<span class="property">url</span>, comment.<span class="property">id</span>)</span><br><span class="line">  <span class="keyword">const</span> ppApiContent = <span class="built_in">encodeURIComponent</span>(wxContent)</span><br><span class="line">  <span class="keyword">const</span> ppApiUrl = <span class="string">&#x27;https://blogpkly-13278c-1258453354.ap-shanghai.app.tcloudbase.com/weixin-push?id=ww*******&amp;secert=Ne******&amp;agentId=1000003&amp;msg=&#x27;</span> <span class="comment">//此处填写上文构造的访问URL</span></span><br><span class="line">  <span class="keyword">const</span> sendResult = <span class="keyword">await</span> axios.<span class="title function_">get</span>(ppApiUrl + ppApiContent)</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;WinxinPush 通知结果：&#x27;</span>, sendResult)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="补充一个配置项-WXPUSH-KEY"><a href="#补充一个配置项-WXPUSH-KEY" class="headerlink" title="补充一个配置项 WXPUSH_KEY"></a>补充一个配置项 WXPUSH_KEY</h4><p>接着在<code>云函数/数据库/config</code>中，点击“查看所有”，点击编辑，增加一个字段：  </p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;WXPUSH_KEY&quot;</span><span class="punctuation">:</span><span class="string">&quot;abc123&quot;</span>  <span class="comment">//值的类型为string，值随便一个字符串（因为前端没有这个key配置入口，就添加到这里）</span></span><br></pre></td></tr></table></figure><p><img src="/posts/626/%E6%B7%BB%E5%8A%A0%E5%AD%97%E6%AE%B5.jpg" alt="新增一个WXPUSH_KEY"></p><div class="note warning flat"><p>使用自定义API提醒，请将其他Server 酱、Qmsg 酱、推送加 的<code>KEY</code>留空。  </p></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>大功告成！现在，使用一个非博主的邮箱，去评论一条，看看是不是下面这样：<br><img src="/posts/626/%E6%95%88%E6%9E%9C1.png" alt="自定义消息提醒API效果"></p><p>好用记得点赞~~</p><p><strong>关联阅读：</strong></p><ol><li><a href="/posts/hugo-gongyong-twikoo/" title="Hugo 设置不同页面共用一套 Twikoo 评论">Hugo 设置不同页面共用一套 Twikoo 评论</a></li><li><a href="/posts/62740/" title="自定义Twikoo邮件通知模板">自定义Twikoo邮件通知模板</a></li><li><a href="https://blog.zhheo.com/p/1e9f35bc.html" title="微信菌：利用企业微信搭建微信消息提醒API">微信菌：利用企业微信搭建微信消息提醒API</a></li></ol>]]></content>
    
    
    <summary type="html">使用企业微信插件，自行搭建Twikoo的消息提醒API，像收女朋友微信消息一样接收新评论提醒！</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="找点儿乐子" scheme="https://blog.guole.fun/tags/%E6%89%BE%E7%82%B9%E5%84%BF%E4%B9%90%E5%AD%90/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
    <category term="Twikoo" scheme="https://blog.guole.fun/tags/Twikoo/"/>
    
  </entry>
  
  <entry>
    <title>自定义Twikoo访客通知邮件模板</title>
    <link href="https://blog.guole.fun/posts/62740/"/>
    <id>https://blog.guole.fun/posts/62740/</id>
    <published>2021-07-05T19:28:14.000Z</published>
    <updated>2025-11-01T19:36:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>一时兴起，发现小康的邮件通知模板挺好看的，于是借鉴之。白嫖就是快乐啊。  </p><h2 id="使用-Twikoo-管理面板配置（推荐）"><a href="#使用-Twikoo-管理面板配置（推荐）" class="headerlink" title="使用 Twikoo 管理面板配置（推荐）"></a>使用 Twikoo 管理面板配置（推荐）</h2><details blue><summary> 效果预览 </summary>              <div class='content'>              <p><img src="/posts/62740/%E8%87%AA%E5%AE%9A%E4%B9%89%E9%82%AE%E4%BB%B6%E9%80%9A%E7%9F%A5%E6%A8%A1%E6%9D%BF.jpg" alt="自定义邮件模板效果"><br><strong>略有不足</strong><br>可能受QQ客户端的邮箱样式影响，移动端字体有点大。自己加了移动端样式，但是没生效。</p>              </div>            </details><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">管理面板插入</button><button type="button" class="tab">压缩后的代码</button><button type="button" class="tab">未压缩代码供参考</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>在Twikoo管理面板中插入</strong><br>登录自己的Twikoo管理面板，找到<code>配置管理——邮件通知——MAIL_TEMPLATE</code>，在此处粘贴压缩后的<code>html</code>邮件模板。<br><img src="/posts/62740/%E7%AE%A1%E7%90%86%E9%9D%A2%E6%9D%BF%E6%8F%92%E5%85%A5.jpg" alt="在Twikoo管理面板中插入"></p></div><div class="tab-item-content"><p><strong>直接复制覆盖，接着保存立即生效</strong><br>注意其中我的博客地址、logo什么的，修改为你自己的。  </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;isForwardContent&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;content&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;         background: white;         width: 95%;         max-width: 800px;         margin: auto auto;         border-radius: 5px;         border: #49b1f5 1px solid;         overflow: hidden;         -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);         box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);       &quot;</span>&gt;</span><span class="tag">&lt;<span class="name">header</span> <span class="attr">style</span>=<span class="string">&quot;overflow: hidden&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.guole.fun/img/bg.min.jpg&quot;</span><span class="attr">style</span>=<span class="string">&quot;width: 100%; z-index: 666&quot;</span>/&gt;</span><span class="tag">&lt;/<span class="name">header</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;padding: 5px 20px&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;dear&quot;</span><span class="attr">style</span>=<span class="string">&quot;             position: relative;             color: white;             float: left;             z-index: 999;             background: #49b1f5;             padding: 5px 30px;             margin: -25px auto 0;             box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);           &quot;</span>&gt;</span>Dear $&#123;PARENT_NICK&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="tag">&lt;<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">h3</span>&gt;</span>来自<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span><span class="symbol">&amp;nbsp;</span>的回复<span class="tag">&lt;/<span class="name">h3</span>&gt;</span><span class="tag">&lt;/<span class="name">center</span>&gt;</span><span class="tag">&lt;<span class="name">hr</span> <span class="attr">style</span>=<span class="string">&quot;width:200px;border:0;border-bottom:1px solid #e5e5e5;margin:12px auto;&quot;</span>/&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="symbol">&amp;nbsp;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>您在<span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span><span class="attr">style</span>=<span class="string">&quot;text-decoration: none; color: #49b1f5&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span>$&#123;SITE_NAME&#125;<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span>上发表的评论：<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tk-content&quot;</span><span class="attr">style</span>=<span class="string">&quot; border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 20px; background-color: #eee; margin: 15px 0px; padding-left: 20px; padding-right: 20px; border-top: #ddd 1px solid; border-right: #ddd 1px solid;  padding-top: 20px;&quot;</span>&gt;</span>$&#123;PARENT_COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span><span class="symbol">&amp;nbsp;</span>给您回复啦：<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tk-content&quot;</span><span class="attr">style</span>=<span class="string">&quot; border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 20px; background-color: #eee;  margin: 15px 0px;  padding-left: 20px; padding-right: 20px; border-top: #ddd 1px solid; border-right: #ddd 1px solid; padding-top: 20px; &quot;</span>&gt;</span>$&#123;COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span>欢迎再次光临<span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span><span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>$&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>！<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;chakan&quot;</span><span class="attr">style</span>=<span class="string">&quot;text-align: center;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span><span class="attr">style</span>=<span class="string">&quot;color:#ffffff;text-decoration:none;display:inline-block;min-height:28px;line-height:28px;padding:0 13px;outline:0;background:#3eae5f;font-size:13px;text-align: center;font-weight:400;border:0;border-radius:999em&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>点击去原文查看<span class="symbol">&amp;gt;</span><span class="symbol">&amp;gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;footer-p&quot;</span><span class="attr">style</span>=<span class="string">&quot;text-align: center; margin-top: 5rem; display:block;color:#b3b3b1;text-decoration:none;&quot;</span>&gt;</span><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.guole.fun/logo/guole.fun.png&quot;</span><span class="attr">style</span>=<span class="string">&quot;width:1.8rem; margin:0 auto&quot;</span>/&gt;</span><span class="symbol">&amp;nbsp;</span><span class="tag">&lt;<span class="name">hr</span> <span class="attr">style</span>=<span class="string">&quot;width:165px;border:0;border-bottom:1px solid #e5e5e5;margin:5px auto;&quot;</span>/&gt;</span>©<span class="symbol">&amp;nbsp;</span>2021<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;https://guole.fun/&quot;</span><span class="attr">style</span>=<span class="string">&quot;text-align:center; color: #0da1e6a6&quot;</span><span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>guole.fun<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span>::-webkit-scrollbar&#123;<span class="attribute">display</span>:none&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;cloudAttachStyle&quot;</span><span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span><span class="selector-id">#divNeteaseBigAttach</span>,<span class="selector-class">.qmbox</span><span class="selector-id">#divNeteaseBigAttach_bak</span>&#123;<span class="attribute">display</span>:none&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;blockquoteStyle&quot;</span><span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">blockquote</span>&#123;<span class="attribute">display</span>:none&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">body</span>&#123;<span class="attribute">font-size</span>:<span class="number">14px</span>;<span class="attribute">font-family</span>:arial,verdana,sans-serif;<span class="attribute">line-height</span>:<span class="number">1.666</span>;<span class="attribute">padding</span>:<span class="number">0</span>;<span class="attribute">margin</span>:<span class="number">0</span>;<span class="attribute">overflow</span>:auto;<span class="attribute">white-space</span>:normal;<span class="attribute">word-wrap</span>:break-word;<span class="attribute">min-height</span>:<span class="number">100px</span>&#125;<span class="selector-class">.qmbox</span> <span class="selector-tag">td</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">input</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">button</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">select</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">body</span>&#123;<span class="attribute">font-family</span>:Helvetica,<span class="string">&#x27;Microsoft Yahei&#x27;</span>,verdana&#125;<span class="selector-class">.qmbox</span> pre&#123;<span class="attribute">white-space</span>:pre-wrap;<span class="attribute">white-space</span>:-moz-pre-wrap;<span class="attribute">white-space</span>:-pre-wrap;<span class="attribute">white-space</span>:-o-pre-wrap;<span class="attribute">word-wrap</span>:break-word;<span class="attribute">width</span>:<span class="number">95%</span>&#125;<span class="selector-class">.qmbox</span> <span class="selector-tag">th</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">td</span>&#123;<span class="attribute">font-family</span>:arial,verdana,sans-serif;<span class="attribute">line-height</span>:<span class="number">1.666</span>&#125;<span class="selector-class">.qmbox</span> <span class="selector-tag">img</span>&#123;<span class="attribute">border</span>:<span class="number">0</span>&#125;<span class="selector-class">.qmbox</span> <span class="selector-tag">header</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">footer</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">section</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">aside</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">article</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">nav</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">hgroup</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">figure</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">figcaption</span>&#123;<span class="attribute">display</span>:block&#125;<span class="selector-class">.qmbox</span> <span class="selector-tag">blockquote</span>&#123;<span class="attribute">margin-right</span>:<span class="number">0px</span>&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="keyword">@media</span> screen <span class="keyword">and</span>(<span class="attribute">max-width</span>:<span class="number">1100px</span>)&#123;<span class="selector-id">#content</span> <span class="selector-tag">p</span>&#123;<span class="attribute">font-size</span>:<span class="number">10px</span>&#125;<span class="selector-id">#content</span> <span class="selector-tag">h3</span>&#123;<span class="attribute">font-size</span>:<span class="number">14px</span>&#125;<span class="selector-class">.footer-p</span>&#123;<span class="attribute">font-size</span>:<span class="number">9px</span>&#125;<span class="selector-class">.dear</span>&#123;<span class="attribute">font-size</span>:<span class="number">12px</span>&#125;&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;ntes_link_color&quot;</span><span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">a</span>,<span class="selector-class">.qmbox</span> <span class="selector-tag">td</span> <span class="selector-tag">a</span>&#123;<span class="attribute">color</span>:<span class="number">#236da1</span>&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight html"><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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;isForwardContent&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;         background: white;         width: 95%;         max-width: 800px;         margin: auto auto;         border-radius: 5px;         border: #49b1f5 1px solid;         overflow: hidden;         -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);         box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);       &quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">header</span> <span class="attr">style</span>=<span class="string">&quot;overflow: hidden&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.guole.fun/img/bg.min.jpg&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width: 100%; z-index: 666&quot;</span> /&gt;</span><span class="tag">&lt;/<span class="name">header</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;padding: 5px 20px&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;dear&quot;</span> <span class="attr">style</span>=<span class="string">&quot;             position: relative;             color: white;             float: left;             z-index: 999;             background: #49b1f5;             padding: 5px 30px;             margin: -25px auto 0;             box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);           &quot;</span>&gt;</span>Dear $&#123;PARENT_NICK&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">br</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">center</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">h3</span>&gt;</span>来自<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span><span class="symbol">&amp;nbsp;</span>的回复<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">center</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">hr</span> <span class="attr">style</span>=<span class="string">&quot;width:200px;border:0;border-bottom:1px solid #e5e5e5;margin:12px auto;&quot;</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">br</span> /&gt;</span><span class="symbol">&amp;nbsp;</span> <span class="symbol">&amp;nbsp;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>您在</span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration: none; color: #49b1f5&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span>$&#123;SITE_NAME&#125;<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span>上发表的评论：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tk-content&quot;</span> <span class="attr">style</span>=<span class="string">&quot; border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 20px; background-color: #eee; margin: 15px 0px; padding-left: 20px; padding-right: 20px; border-top: #ddd 1px solid; border-right: #ddd 1px solid;  padding-top: 20px;&quot;</span>&gt;</span>$&#123;PARENT_COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span><span class="symbol">&amp;nbsp;</span>给您回复啦：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tk-content&quot;</span> <span class="attr">style</span>=<span class="string">&quot; border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 20px; background-color: #eee;  margin: 15px 0px;  padding-left: 20px; padding-right: 20px; border-top: #ddd 1px solid; border-right: #ddd 1px solid; padding-top: 20px; &quot;</span>&gt;</span>$&#123;COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>欢迎再次光临</span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>$&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>！<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">br</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;chakan&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align: center;&quot;</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span> <span class="attr">style</span>=<span class="string">&quot;color:#ffffff;text-decoration:none;display:inline-block;min-height:28px;line-height:28px;padding:0 13px;outline:0;background:#3eae5f;font-size:13px;text-align: center;font-weight:400;border:0;border-radius:999em&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>点击去原文查看<span class="symbol">&amp;gt;</span><span class="symbol">&amp;gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;footer-p&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align: center; margin-top: 5rem; display:block;color:#b3b3b1;text-decoration:none;&quot;</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.guole.fun/logo/guole.fun.png&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:1.8rem; margin:0 auto&quot;</span> /&gt;</span><span class="symbol">&amp;nbsp;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">hr</span> <span class="attr">style</span>=<span class="string">&quot;width:165px;border:0;border-bottom:1px solid #e5e5e5;margin:5px auto;&quot;</span> /&gt;</span>©<span class="symbol">&amp;nbsp;</span>2021<span class="symbol">&amp;nbsp;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;https://guole.fun/&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align:center; color: #0da1e6a6&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>guole.fun<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">br</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> ::-webkit-scrollbar &#123; <span class="attribute">display</span>: none; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;cloudAttachStyle&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-id">#divNeteaseBigAttach</span>, <span class="selector-class">.qmbox</span> <span class="selector-id">#divNeteaseBigAttach_bak</span> &#123; <span class="attribute">display</span>: none; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;blockquoteStyle&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">blockquote</span> &#123; <span class="attribute">display</span>: none; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">body</span> &#123; <span class="attribute">font-size</span>: <span class="number">14px</span>; <span class="attribute">font-family</span>: arial, verdana, sans-serif; <span class="attribute">line-height</span>: <span class="number">1.666</span>; <span class="attribute">padding</span>: <span class="number">0</span>; <span class="attribute">margin</span>: <span class="number">0</span>; <span class="attribute">overflow</span>: auto; <span class="attribute">white-space</span>: normal; <span class="attribute">word-wrap</span>: break-word; <span class="attribute">min-height</span>: <span class="number">100px</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">td</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">input</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">button</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">select</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">body</span> &#123; <span class="attribute">font-family</span>: Helvetica, <span class="string">&#x27;Microsoft Yahei&#x27;</span>, verdana; &#125; <span class="selector-class">.qmbox</span> pre &#123; <span class="attribute">white-space</span>: pre-wrap; <span class="attribute">white-space</span>: -moz-pre-wrap; <span class="attribute">white-space</span>: -pre-wrap; <span class="attribute">white-space</span>: -o-pre-wrap; <span class="attribute">word-wrap</span>: break-word; <span class="attribute">width</span>: <span class="number">95%</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">th</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">td</span> &#123; <span class="attribute">font-family</span>: arial, verdana, sans-serif; <span class="attribute">line-height</span>: <span class="number">1.666</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">img</span> &#123; <span class="attribute">border</span>: <span class="number">0</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">header</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">footer</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">section</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">aside</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">article</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">nav</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">hgroup</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">figure</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">figcaption</span> &#123; <span class="attribute">display</span>: block; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">blockquote</span> &#123; <span class="attribute">margin-right</span>: <span class="number">0px</span>; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1100px</span>) &#123;<span class="selector-id">#content</span> <span class="selector-tag">p</span> &#123;<span class="attribute">font-size</span>: <span class="number">10px</span>;&#125; <span class="selector-id">#content</span> <span class="selector-tag">h3</span> &#123;<span class="attribute">font-size</span>: <span class="number">14px</span>;&#125; <span class="selector-class">.footer-p</span> &#123;<span class="attribute">font-size</span>: <span class="number">9px</span>;&#125; <span class="selector-class">.dear</span> &#123;<span class="attribute">font-size</span>: <span class="number">12px</span>;&#125;&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;ntes_link_color&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">a</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">td</span> <span class="selector-tag">a</span> &#123; <span class="attribute">color</span>: <span class="number">#236da1</span>; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>搞定！ </p><h2 id="修改云函数源代码（不推荐）"><a href="#修改云函数源代码（不推荐）" class="headerlink" title="修改云函数源代码（不推荐）"></a>修改云函数源代码（不推荐）</h2><p>找到腾讯云开发<code>云函数/twikoo/函数代码/node_modules/twikoo-func/index.js</code>，Ctrl+F 搜索定位到“同学，您曾发表评论”，修改其中的<code>html</code>邮件模板内容。可直接拿我的：  </p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">修改源代码</button><button type="button" class="tab">原通知模板备份</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>直接复制覆盖，接着保存云函数即可生效</strong><br>注意其中我的博客地址、logo什么的，修改为你自己的。  </p><figure class="highlight html"><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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;isForwardContent&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;         background: white;         width: 95%;         max-width: 800px;         margin: auto auto;         border-radius: 5px;         border: #49b1f5 1px solid;         overflow: hidden;         -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);         box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);       &quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">header</span> <span class="attr">style</span>=<span class="string">&quot;overflow: hidden&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.guole.fun/img/bg.jpg&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width: 100%; z-index: 666&quot;</span> /&gt;</span><span class="tag">&lt;/<span class="name">header</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;padding: 5px 20px&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;dear&quot;</span> <span class="attr">style</span>=<span class="string">&quot;             position: relative;             color: white;             float: left;             z-index: 999;             background: #49b1f5;             padding: 5px 30px;             margin: -25px auto 0;             box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.3);           &quot;</span>&gt;</span>Dear $&#123;PARENT_NICK&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">br</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">center</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">h3</span>&gt;</span>来自<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span><span class="symbol">&amp;nbsp;</span>的回复<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">center</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">hr</span> <span class="attr">style</span>=<span class="string">&quot;width:200px;border:0;border-bottom:1px solid #e5e5e5;margin:12px auto;&quot;</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">br</span> /&gt;</span><span class="symbol">&amp;nbsp;</span> <span class="symbol">&amp;nbsp;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>您在</span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration: none; color: #49b1f5&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span><span class="symbol">&amp;nbsp;</span>$&#123;SITE_NAME&#125;<span class="symbol">&amp;nbsp;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span>上发表的评论：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tk-content&quot;</span> <span class="attr">style</span>=<span class="string">&quot; border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 20px; background-color: #eee; margin: 15px 0px; padding-left: 20px; padding-right: 20px; border-top: #ddd 1px solid; border-right: #ddd 1px solid;  padding-top: 20px;&quot;</span>&gt;</span>$&#123;PARENT_COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span><span class="symbol">&amp;nbsp;</span>给您回复啦：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;tk-content&quot;</span> <span class="attr">style</span>=<span class="string">&quot; border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 20px; background-color: #eee;  margin: 15px 0px;  padding-left: 20px; padding-right: 20px; border-top: #ddd 1px solid; border-right: #ddd 1px solid; padding-top: 20px; &quot;</span>&gt;</span>$&#123;COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">p</span>&gt;</span>欢迎再次光临</span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>$&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>！<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">br</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;chakan&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align: center;&quot;</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span> <span class="attr">style</span>=<span class="string">&quot;color:#ffffff;text-decoration:none;display:inline-block;min-height:28px;line-height:28px;padding:0 13px;outline:0;background:#3eae5f;font-size:13px;text-align: center;font-weight:400;border:0;border-radius:999em&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>点击去原文查看<span class="symbol">&amp;gt;</span><span class="symbol">&amp;gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;footer-p&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align: center; margin-top: 5rem; display:block;color:#b3b3b1;text-decoration:none;&quot;</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.guole.fun/logo/guole.fun.png&quot;</span> <span class="attr">style</span>=<span class="string">&quot;width:1.8rem; margin:0 auto&quot;</span> /&gt;</span><span class="symbol">&amp;nbsp;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">hr</span> <span class="attr">style</span>=<span class="string">&quot;width:165px;border:0;border-bottom:1px solid #e5e5e5;margin:5px auto;&quot;</span> /&gt;</span>©<span class="symbol">&amp;nbsp;</span>2021<span class="symbol">&amp;nbsp;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;https://guole.fun/&quot;</span> <span class="attr">style</span>=<span class="string">&quot;text-align:center; color: #0da1e6a6&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>guole.fun<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">              <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">br</span> /&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> ::-webkit-scrollbar &#123; <span class="attribute">display</span>: none; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;cloudAttachStyle&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-id">#divNeteaseBigAttach</span>, <span class="selector-class">.qmbox</span> <span class="selector-id">#divNeteaseBigAttach_bak</span> &#123; <span class="attribute">display</span>: none; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;blockquoteStyle&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">blockquote</span> &#123; <span class="attribute">display</span>: none; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">body</span> &#123; <span class="attribute">font-size</span>: <span class="number">14px</span>; <span class="attribute">font-family</span>: arial, verdana, sans-serif; <span class="attribute">line-height</span>: <span class="number">1.666</span>; <span class="attribute">padding</span>: <span class="number">0</span>; <span class="attribute">margin</span>: <span class="number">0</span>; <span class="attribute">overflow</span>: auto; <span class="attribute">white-space</span>: normal; <span class="attribute">word-wrap</span>: break-word; <span class="attribute">min-height</span>: <span class="number">100px</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">td</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">input</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">button</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">select</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">body</span> &#123; <span class="attribute">font-family</span>: Helvetica, <span class="string">&#x27;Microsoft Yahei&#x27;</span>, verdana; &#125; <span class="selector-class">.qmbox</span> pre &#123; <span class="attribute">white-space</span>: pre-wrap; <span class="attribute">white-space</span>: -moz-pre-wrap; <span class="attribute">white-space</span>: -pre-wrap; <span class="attribute">white-space</span>: -o-pre-wrap; <span class="attribute">word-wrap</span>: break-word; <span class="attribute">width</span>: <span class="number">95%</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">th</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">td</span> &#123; <span class="attribute">font-family</span>: arial, verdana, sans-serif; <span class="attribute">line-height</span>: <span class="number">1.666</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">img</span> &#123; <span class="attribute">border</span>: <span class="number">0</span>; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">header</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">footer</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">section</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">aside</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">article</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">nav</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">hgroup</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">figure</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">figcaption</span> &#123; <span class="attribute">display</span>: block; &#125; <span class="selector-class">.qmbox</span> <span class="selector-tag">blockquote</span> &#123; <span class="attribute">margin-right</span>: <span class="number">0px</span>; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">1100px</span>) &#123;<span class="selector-id">#content</span> <span class="selector-tag">p</span> &#123;<span class="attribute">font-size</span>: <span class="number">10px</span>;&#125; <span class="selector-id">#content</span> <span class="selector-tag">h3</span> &#123;<span class="attribute">font-size</span>: <span class="number">14px</span>;&#125; <span class="selector-class">.footer-p</span> &#123;<span class="attribute">font-size</span>: <span class="number">9px</span>;&#125; <span class="selector-class">.dear</span> &#123;<span class="attribute">font-size</span>: <span class="number">12px</span>;&#125;&#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">style</span> <span class="attr">id</span>=<span class="string">&quot;ntes_link_color&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/css&quot;</span>&gt;</span><span class="language-css"><span class="selector-class">.qmbox</span> <span class="selector-tag">a</span>, <span class="selector-class">.qmbox</span> <span class="selector-tag">td</span> <span class="selector-tag">a</span> &#123; <span class="attribute">color</span>: <span class="number">#236da1</span>; &#125;</span><span class="tag">&lt;/<span class="name">style</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></div><div class="tab-item-content"><figure class="highlight html"><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="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h2</span> <span class="attr">style</span>=<span class="string">&quot;border-bottom:1px solid #dddddd;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;&quot;</span>&gt;</span>您在</span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none;color: #12ADDB;&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>$&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>上的评论有了新的回复<span class="tag">&lt;/<span class="name">h2</span>&gt;</span>$&#123;PARENT_NICK&#125; 同学，您曾发表评论：</span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;padding:0 12px 0 12px;margin-top:18px&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;&quot;</span>&gt;</span>$&#123;PARENT_COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">strong</span>&gt;</span>$&#123;NICK&#125;<span class="tag">&lt;/<span class="name">strong</span>&gt;</span>回复说：<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">style</span>=<span class="string">&quot;background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;&quot;</span>&gt;</span>$&#123;COMMENT&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>您可以点击</span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;POST_URL&#125;&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>查看回复的完整內容<span class="tag">&lt;/<span class="name">a</span>&gt;</span>， 欢迎再次光临</span><br><span class="line">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">style</span>=<span class="string">&quot;text-decoration:none; color:#12addb&quot;</span> <span class="attr">href</span>=<span class="string">&quot;$&#123;SITE_URL&#125;&quot;</span> <span class="attr">target</span>=<span class="string">&quot;_blank&quot;</span>&gt;</span>$&#123;SITE_NAME&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span>。</span><br><span class="line">      <span class="tag">&lt;<span class="name">br</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>收工！ </p><h4 id="参考内容"><a href="#参考内容" class="headerlink" title="参考内容"></a>参考内容</h4><p><a href="https://www.antmoe.com/" target="_blank">小康博客</a>  </p>]]></content>
    
    
    <summary type="html">借鉴某大佬的邮件通知样式，自定义一个twikoo的邮件通知模板。</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.guole.fun/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="教程" scheme="https://blog.guole.fun/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Hexo" scheme="https://blog.guole.fun/tags/Hexo/"/>
    
    <category term="Twikoo" scheme="https://blog.guole.fun/tags/Twikoo/"/>
    
  </entry>
  
</feed>
