<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>阿木</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>http://example.com/</id>
  <link href="http://example.com/" rel="alternate"/>
  <link href="http://example.com/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, 阿木</rights>
  <subtitle>一直在努力，从未成功过。</subtitle>
  <title>Amu博客-一直在努力，从未成功过。</title>
  <updated>2026-10-13T13:31:04.239Z</updated>
  <entry>
    <author>
      <name>阿木</name>
    </author>
    <category term="AI 摘要" scheme="http://example.com/categories/AI-%E6%91%98%E8%A6%81/"/>
    <content>
      <![CDATA[<a href="https://github.com/willow-god/hexo-ai-summary" target="_blank" rel="noopener noreferrer" style="display: inline-block; text-decoration: none; color: #ffffff; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; padding: 14px 24px; font-weight: bold; font-size: 15px; cursor: pointer; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4); transition: all 0.3s ease;">  🤖 hexo-ai-summary-liushen · AI 智能摘要插件 →</a><h1 id="umami-view-js-写法"><a href="#umami-view-js-写法" class="headerlink" title="umami-view.js 写法"></a>umami-view.js 写法</h1><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><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></pre></td><td class="code"><pre><code class="hljs javascript">&#123;<br>  <span class="hljs-comment">// 从配置文件中获取 umami 的配置</span><br><span class="hljs-keyword">const</span> website_id = <span class="hljs-variable constant_">CONFIG</span>.<span class="hljs-property">web_analytics</span>.<span class="hljs-property">umami</span>.<span class="hljs-property">website_id</span>;<br><span class="hljs-comment">// 拼接请求地址</span><br><span class="hljs-keyword">const</span> request_url = <span class="hljs-string">`<span class="hljs-subst">$&#123;CONFIG.web_analytics.umami.api_server&#125;</span>/api/websites/<span class="hljs-subst">$&#123;website_id&#125;</span>/stats`</span>;<br><br><span class="hljs-keyword">const</span> start_time = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(<span class="hljs-variable constant_">CONFIG</span>.<span class="hljs-property">web_analytics</span>.<span class="hljs-property">umami</span>.<span class="hljs-property">start_time</span>).<span class="hljs-title function_">getTime</span>();<br><span class="hljs-keyword">const</span> end_time = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>().<span class="hljs-title function_">getTime</span>();<br><span class="hljs-keyword">const</span> token = <span class="hljs-variable constant_">CONFIG</span>.<span class="hljs-property">web_analytics</span>.<span class="hljs-property">umami</span>.<span class="hljs-property">token</span>;<br><br><span class="hljs-comment">// 检查配置是否为空</span><br><span class="hljs-keyword">if</span> (!website_id) &#123;<br>  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&quot;Umami website_id is empty&quot;</span>);<br>&#125;<br><span class="hljs-keyword">if</span> (!request_url) &#123;<br>  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&quot;Umami request_url is empty&quot;</span>);<br>&#125;<br><span class="hljs-keyword">if</span> (!start_time) &#123;<br>  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&quot;Umami start_time is empty&quot;</span>);<br>&#125;<br><span class="hljs-keyword">if</span> (!token) &#123;<br>  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">&quot;Umami token is empty&quot;</span>);<br>&#125;<br><br><span class="hljs-comment">// 构造请求参数</span><br><span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> <span class="hljs-title class_">URLSearchParams</span>(&#123;<br>  <span class="hljs-attr">startAt</span>: start_time,<br>  <span class="hljs-attr">endAt</span>: end_time,<br>&#125;);<br><span class="hljs-comment">// 构造请求头</span><br><span class="hljs-keyword">const</span> request_header = &#123;<br>  <span class="hljs-attr">method</span>: <span class="hljs-string">&quot;GET&quot;</span>,<br>  <span class="hljs-attr">headers</span>: &#123;<br>    <span class="hljs-string">&quot;Content-Type&quot;</span>: <span class="hljs-string">&quot;application/json&quot;</span>,<br>    <span class="hljs-string">&quot;Authorization&quot;</span>: <span class="hljs-string">&quot;Bearer &quot;</span> + token,<br>  &#125;,<br>&#125;;<br><br><span class="hljs-comment">// 获取站点统计数据</span><br><span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">siteStats</span>(<span class="hljs-params"></span>) &#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetch</span>(<span class="hljs-string">`<span class="hljs-subst">$&#123;request_url&#125;</span>?<span class="hljs-subst">$&#123;params&#125;</span>`</span>, request_header);<br>    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.<span class="hljs-title function_">json</span>();<br>    <span class="hljs-keyword">const</span> uniqueVisitors = data.<span class="hljs-property">visitors</span>.<span class="hljs-property">value</span>; <span class="hljs-comment">// 获取独立访客数</span><br>    <span class="hljs-keyword">const</span> pageViews = data.<span class="hljs-property">pageviews</span>.<span class="hljs-property">value</span>; <span class="hljs-comment">// 获取页面浏览量</span><br><br>    <span class="hljs-keyword">let</span> pvCtn = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-site-pv-container&quot;</span>);<br>    <span class="hljs-keyword">if</span> (pvCtn) &#123;<br>      <span class="hljs-keyword">let</span> ele = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-site-pv&quot;</span>);<br>      <span class="hljs-keyword">if</span> (ele) &#123;<br>        ele.<span class="hljs-property">textContent</span> = pageViews; <span class="hljs-comment">// 设置页面浏览量</span><br>        pvCtn.<span class="hljs-property">style</span>.<span class="hljs-property">display</span> = <span class="hljs-string">&quot;inline&quot;</span>; <span class="hljs-comment">// 将元素显示出来</span><br>      &#125;<br>    &#125;<br><br>    <span class="hljs-keyword">let</span> uvCtn = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-site-uv-container&quot;</span>);<br>    <span class="hljs-keyword">if</span> (uvCtn) &#123;<br>      <span class="hljs-keyword">let</span> ele = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-site-uv&quot;</span>);<br>      <span class="hljs-keyword">if</span> (ele) &#123;<br>        ele.<span class="hljs-property">textContent</span> = uniqueVisitors;<br>        uvCtn.<span class="hljs-property">style</span>.<span class="hljs-property">display</span> = <span class="hljs-string">&quot;inline&quot;</span>;<br>      &#125;<br>    &#125;<br>  &#125; <span class="hljs-keyword">catch</span> (error) &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;-1&quot;</span>;<br>  &#125;<br>&#125;<br><br><span class="hljs-comment">// 获取页面浏览量</span><br><span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">pageStats</span>(<span class="hljs-params">path</span>) &#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetch</span>(<span class="hljs-string">`<span class="hljs-subst">$&#123;request_url&#125;</span>?<span class="hljs-subst">$&#123;params&#125;</span>&amp;url=<span class="hljs-subst">$&#123;path&#125;</span>`</span>, request_header);<br>    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.<span class="hljs-title function_">json</span>();<br>    <span class="hljs-keyword">const</span> pageViews = data.<span class="hljs-property">pageviews</span>.<span class="hljs-property">value</span>;<br><br>    <span class="hljs-keyword">let</span> viewCtn = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-page-views-container&quot;</span>);<br>    <span class="hljs-keyword">if</span> (viewCtn) &#123;<br>      <span class="hljs-keyword">let</span> ele = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-page-views&quot;</span>);<br>      <span class="hljs-keyword">if</span> (ele) &#123;<br>        ele.<span class="hljs-property">textContent</span> = pageViews;<br>        viewCtn.<span class="hljs-property">style</span>.<span class="hljs-property">display</span> = <span class="hljs-string">&quot;inline&quot;</span>;<br>      &#125;<br>    &#125;<br>  &#125; <span class="hljs-keyword">catch</span> (error) &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error);<br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;-1&quot;</span>;<br>  &#125;<br>&#125;<br><br><span class="hljs-title function_">siteStats</span>();<br><br><span class="hljs-comment">// 获取页面容器</span><br><span class="hljs-keyword">let</span> viewCtn = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#umami-page-views-container&quot;</span>);<br><span class="hljs-comment">// 如果页面容器存在，则获取页面浏览量</span><br><span class="hljs-keyword">if</span> (viewCtn) &#123;<br>  <span class="hljs-keyword">let</span> path = <span class="hljs-variable language_">window</span>.<span class="hljs-property">location</span>.<span class="hljs-property">pathname</span>;<br>  <span class="hljs-keyword">let</span> target = path<br>    .<span class="hljs-title function_">replace</span>(<span class="hljs-regexp">/(\/[^/]+\.html)\/$/</span>, <span class="hljs-string">&quot;$1&quot;</span>)  <span class="hljs-comment">// 如果是 &#x27;/xxxx.html/&#x27; 格式的路径，则去掉最后那个 &#x27;/&#x27;</span><br>    .<span class="hljs-title function_">replace</span>(<span class="hljs-regexp">/\/index\.html$/</span>, <span class="hljs-string">&quot;/&quot;</span>);      <span class="hljs-comment">// 如果是 &#x27;/index.html&#x27; 格式，则合并成 &#x27;/&#x27;</span><br>  <span class="hljs-title function_">pageStats</span>(target);<br>&#125;<br><br>&#125;<br></code></pre></td></tr></table></figure><h1 id="ai-summary-css-写法"><a href="#ai-summary-css-写法" class="headerlink" title="ai-summary.css 写法"></a>ai-summary.css 写法</h1><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></pre></td><td class="code"><pre><code class="hljs css">&#123;<br> <span class="hljs-selector-class">.ai-summary-typing</span> &#123;<br>  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">1.2em</span> <span class="hljs-number">0</span>;<br>  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.8em</span> <span class="hljs-number">1em</span>;<br>  <span class="hljs-attribute">border-left</span>: <span class="hljs-number">3px</span> solid <span class="hljs-number">#4a9eff</span>;<br>  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">74</span>, <span class="hljs-number">158</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.06</span>);<br>  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;<br>  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.95em</span>;<br>  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.7</span>;<br>  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">1.7em</span>;<br>&#125;<br><span class="hljs-selector-class">.ai-summary-cursor</span> &#123;<br>  <span class="hljs-attribute">display</span>: inline-block;<br>  <span class="hljs-attribute">width</span>: <span class="hljs-number">2px</span>;<br>  <span class="hljs-attribute">height</span>: <span class="hljs-number">1em</span>;<br>  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">2px</span>;<br>  <span class="hljs-attribute">vertical-align</span>: -<span class="hljs-number">0.15em</span>;<br>  <span class="hljs-attribute">background</span>: <span class="hljs-number">#4a9eff</span>;<br>  <span class="hljs-attribute">animation</span>: ai-cursor-blink <span class="hljs-number">0.8s</span> <span class="hljs-built_in">steps</span>(<span class="hljs-number">1</span>) infinite;<br>&#125;<br><span class="hljs-keyword">@keyframes</span> ai-cursor-blink &#123;<br>  <span class="hljs-number">50%</span> &#123; <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0</span>; &#125;<br>&#125;<br>&#125;<br></code></pre></td></tr></table></figure><h1 id="scripts目录加js"><a href="#scripts目录加js" class="headerlink" title="scripts目录加js"></a>scripts目录加js</h1><figure class="highlight pgsql"><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></pre></td><td class="code"><pre><code class="hljs pgsql">&#123;<br>  hexo.extend.<span class="hljs-keyword">filter</span>.register(<span class="hljs-string">&#x27;after_post_render&#x27;</span>, <span class="hljs-keyword">function</span> (data) &#123;<br>  <span class="hljs-keyword">if</span> (data.layout !== <span class="hljs-string">&#x27;post&#x27;</span> || !data.excerpt) <span class="hljs-keyword">return</span> data;<br>  <span class="hljs-keyword">if</span> (data.content &amp;&amp; data.content.indexOf(<span class="hljs-string">&#x27;ai-summary-typing&#x27;</span>) !== <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> data;<br><br>  var <span class="hljs-type">text</span> = data.excerpt.trim().replace(/&quot;/g, &#x27;&amp;quot;&#x27;);<br><br>  var css = &#x27;&lt;style&gt;&#x27;<br>    + &#x27;.ai-summary-box&#123;margin:0 0 1.5em 0;border:1px solid #d8e6ff;border-radius:8px;overflow:hidden;font-size:0.95em;background:#fff&#125;&#x27;<br>    + &#x27;.ai-summary-box-header&#123;display:flex;align-items:center;gap:6px;padding:0.5em 1em;background:linear-gradient(90deg,rgba(74,158,255,0.12),rgba(74,158,255,0.03));border-bottom:1px solid #d8e6ff;font-weight:600;color:#2b7de9&#125;&#x27;<br>    + &#x27;.ai-summary-box-header svg&#123;width:1.1em;height:1.1em;flex:none&#125;&#x27;<br>    + &#x27;.ai-summary-typing&#123;padding:0.8em 1em;line-height:1.7;min-height:1.7em;color:#444&#125;&#x27;<br>    + &#x27;.ai-summary-cursor&#123;display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-0.15em;background:#4a9eff;animation:ai-cursor-blink 0.8s steps(1) infinite&#125;&#x27;<br>    + &#x27;@keyframes ai-cursor-blink&#123;50%&#123;opacity:0&#125;&#125;&#x27;<br>    + &#x27;&lt;\/style&gt;&#x27;;<br><br>  var icon = &#x27;&lt;svg viewBox=&quot;<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">24</span> <span class="hljs-number">24</span>&quot; fill=&quot;<span class="hljs-keyword">none</span>&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;<span class="hljs-number">2</span>&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M12 <span class="hljs-number">2</span>a4 <span class="hljs-number">4</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">1</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span>c0 <span class="hljs-number">1.1</span><span class="hljs-number">-.45</span> <span class="hljs-number">2.1</span><span class="hljs-number">-1.17</span> <span class="hljs-number">2.83</span>L12 <span class="hljs-number">12</span>l<span class="hljs-number">-2.83</span><span class="hljs-number">-3.17</span>A4 <span class="hljs-number">4</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">1</span> <span class="hljs-number">12</span> <span class="hljs-number">2</span>z&quot;/&gt;&lt;circle cx=&quot;<span class="hljs-number">12</span>&quot; cy=&quot;<span class="hljs-number">6</span>&quot; r=&quot;<span class="hljs-number">1</span>&quot;/&gt;&lt;path d=&quot;M5 <span class="hljs-number">10</span>v4l7 <span class="hljs-number">4</span> <span class="hljs-number">7</span><span class="hljs-number">-4</span>v<span class="hljs-number">-4</span>&quot;/&gt;&lt;path d=&quot;M12 <span class="hljs-number">18</span>v4&quot;/&gt;&lt;/svg&gt;&#x27;;<br><br>  var block = &#x27;&lt;div class=&quot;ai-<span class="hljs-keyword">summary</span>-<span class="hljs-type">box</span>&quot;&gt;&#x27;<br>    + &#x27;&lt;div class=&quot;ai-<span class="hljs-keyword">summary</span>-<span class="hljs-type">box</span>-<span class="hljs-keyword">header</span>&quot;&gt;&#x27; + icon + &#x27;&lt;span&gt;AI 摘要&lt;/span&gt;&lt;/div&gt;&#x27;<br>    + &#x27;&lt;div class=&quot;ai-<span class="hljs-keyword">summary</span>-typing&quot; data-text=&quot;<span class="hljs-string">&#x27; + text + &#x27;</span>&quot;&gt;&lt;span class=&quot;ai-<span class="hljs-keyword">summary</span>-<span class="hljs-type">text</span>&quot;&gt;&lt;/span&gt;&lt;span class=&quot;ai-<span class="hljs-keyword">summary</span>-<span class="hljs-keyword">cursor</span>&quot;&gt;&lt;/span&gt;&lt;/div&gt;&#x27;<br>    + &#x27;&lt;\/div&gt;&#x27;;<br><br>  var js = &#x27;&lt;script&gt;(function()&#123;&#x27;<br>    + &#x27;function init()&#123;var els=document.querySelectorAll(&quot;.ai-<span class="hljs-keyword">summary</span>-typing&quot;);&#x27;<br>    + &#x27;for(var k=0;k&lt;els.length;k++)&#123;(function(el)&#123;&#x27;<br>    + &#x27;if(el.getAttribute(&quot;data-done&quot;))return;el.setAttribute(&quot;data-done&quot;,&quot;<span class="hljs-number">1</span>&quot;);&#x27;<br>    + &#x27;var text=el.getAttribute(&quot;data-<span class="hljs-type">text</span>&quot;)||&quot;&quot;;&#x27;<br>    + &#x27;var target=el.querySelector(&quot;.ai-<span class="hljs-keyword">summary</span>-<span class="hljs-type">text</span>&quot;);&#x27;<br>    + &#x27;var i=0;var timer=setInterval(function()&#123;&#x27;<br>    + &#x27;target.textContent=text.slice(0,++i);&#x27;<br>    + &#x27;if(i&gt;=text.length)&#123;clearInterval(timer);&#x27;<br>    + &#x27;setTimeout(function()&#123;var c=el.querySelector(&quot;.ai-<span class="hljs-keyword">summary</span>-<span class="hljs-keyword">cursor</span>&quot;);if(c)c.style.display=&quot;<span class="hljs-keyword">none</span>&quot;;&#125;,2000);&#125;&#x27;<br>    + &#x27;&#125;,45);&#125;)(els[k]);&#125;&#125;&#x27;<br>    + &#x27;if(document.readyState===&quot;loading&quot;)&#123;document.addEventListener(&quot;DOMContentLoaded&quot;,init);&#125;else&#123;init();&#125;&#x27;<br>    + &#x27;&#125;)();&lt;\/script&gt;&#x27;;<br><br>  data.content = css + block + js + (data.content || &#x27;&#x27;);<br>  return data;<br>&#125;);<br>&#125;<br></code></pre></td></tr></table></figure>]]>
    </content>
    <id>http://example.com/2026/10/13/AI%20%E6%91%98%E8%A6%81%E6%8F%90%E7%A4%BA/</id>
    <link href="http://example.com/2026/10/13/AI%20%E6%91%98%E8%A6%81%E6%8F%90%E7%A4%BA/"/>
    <published>2026-10-13T13:31:04.239Z</published>
    <summary>这里是AI，这篇文章介绍了umami-view.js的编写方式，详细展示了如何通过JavaScript与Umami Analytics API交互以获取网站统计数据。代码首先从配置中读取website_id、api地址、起始时间和token，并校验非空，然后构造带认证头的GET请求，通过fetch异步调用Umami的stats接口。核心逻辑包含两个函数：siteStats用于请求站点级总数据，更新页面中对应PV和UV的显示元素；pageStats则根据当前页面路径请求单页浏览数据，用于显示文章浏览量。最后在页面加载时自动执行站点统计，并根据页面容器存在情况触发页面统计，以便在博客文章页展示阅读次数。该实现充分利用了Umami API的Bearer Token认证，并处理了元素显示时机，适用于Hexo等静态博客的个性化统计展示。</summary>
    <title>Hexo AI 摘要提示添加</title>
    <updated>2026-10-13T13:31:04.239Z</updated>
  </entry>
  <entry>
    <author>
      <name>阿木</name>
    </author>
    <category term="PicGo" scheme="http://example.com/categories/PicGo/"/>
    <category term="GitHub" scheme="http://example.com/categories/PicGo/GitHub/"/>
    <category term="jsDelivr" scheme="http://example.com/categories/PicGo/GitHub/jsDelivr/"/>
    <content>
      <![CDATA[<style>.ai-summary-box{margin:0 0 1.5em 0;border:1px solid #d8e6ff;border-radius:8px;overflow:hidden;font-size:0.95em;background:#fff}.ai-summary-box-header{display:flex;align-items:center;gap:6px;padding:0.5em 1em;background:linear-gradient(90deg,rgba(74,158,255,0.12),rgba(74,158,255,0.03));border-bottom:1px solid #d8e6ff;font-weight:600;color:#2b7de9}.ai-summary-box-header svg{width:1.1em;height:1.1em;flex:none}.ai-summary-typing{padding:0.8em 1em;line-height:1.7;min-height:1.7em;color:#444}.ai-summary-cursor{display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-0.15em;background:#4a9eff;animation:ai-cursor-blink 0.8s steps(1) infinite}@keyframes ai-cursor-blink{50%{opacity:0}}</style><div class="ai-summary-box"><div class="ai-summary-box-header"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 1 4 4c0 1.1-.45 2.1-1.17 2.83L12 12l-2.83-3.17A4 4 0 0 1 12 2z"/><circle cx="12" cy="6" r="1"/><path d="M5 10v4l7 4 7-4v-4"/><path d="M12 18v4"/></svg><span>AI 摘要</span></div><div class="ai-summary-typing" data-text="这篇文章手把手教你用 PicGo 搭配 GitHub 和 jsDelivr 搭建零成本免费图床，实现本地一键上传并自动复制全球加速链接的丝滑写作体验。全文分为五大部分：一是创建 GitHub 图床仓库，登录后新建 repository 并按要点填写；二是生成 GitHub Token，进入开发者设置创建 classic token，并强调立即复制保存因为只显示一次；三是安装配置 PicGo，下载对应系统安装包后在 GitHub 图床中逐项填写并设为默认；四是使用与验证，上传图片后剪贴板自动复制 jsDelivr 加速链接，并推荐开启上传后自动复制 URL、安装 rename-file 与 web-uploader 插件；五是进阶玩法，包括 Typora 联动自动上传、通过 purge 接口刷新 CDN 缓存以及 fastly、gcore 等备用节点。"><span class="ai-summary-text"></span><span class="ai-summary-cursor"></span></div></div><script>(function(){function init(){var els=document.querySelectorAll(".ai-summary-typing");for(var k=0;k<els.length;k++){(function(el){if(el.getAttribute("data-done"))return;el.setAttribute("data-done","1");var text=el.getAttribute("data-text")||"";var target=el.querySelector(".ai-summary-text");var i=0;var timer=setInterval(function(){target.textContent=text.slice(0,++i);if(i>=text.length){clearInterval(timer);setTimeout(function(){var c=el.querySelector(".ai-summary-cursor");if(c)c.style.display="none";},2000);}},45);})(els[k]);}}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init);}else{init();}})();</script><h1 id="🖼️-手把手搭建-PicGo-GitHub-jsDelivr-免费图床"><a href="#🖼️-手把手搭建-PicGo-GitHub-jsDelivr-免费图床" class="headerlink" title="🖼️ 手把手搭建 PicGo + GitHub + jsDelivr 免费图床"></a>🖼️ 手把手搭建 PicGo + GitHub + jsDelivr 免费图床</h1><blockquote><p>💬 <strong>一句话简介</strong>：白嫖 GitHub 存储 + jsDelivr 全球 CDN 加速，实现「本地一键上传 → 自动复制加速链接」的丝滑写作体验。</p></blockquote><hr><h2 id="一、创建-GitHub-图床仓库"><a href="#一、创建-GitHub-图床仓库" class="headerlink" title="一、创建 GitHub 图床仓库"></a>一、创建 GitHub 图床仓库</h2><p><strong>Step 1</strong> 🔧 登录 <a href="https://github.com/">GitHub</a>，点击右上角 <strong><code>+</code></strong> → <strong>New repository</strong></p><p><strong>Step 2</strong> 🔧 按以下要点填写：</p><table><thead><tr><th align="center">设置项</th><th align="left">填写内容</th><th align="left">备注</th></tr></thead><tbody><tr><td align="center">Repository name</td><td align="left"><code>images</code></td><td align="left">名称随意</td></tr><tr><td align="center">Visibility</td><td align="left"><strong>Public</strong></td><td align="left">⚠️ 必须公开，私有仓库 jsDelivr 无法加速</td></tr><tr><td align="center">Add a README file</td><td align="left">✅ 勾选</td><td align="left">便于后续维护</td></tr></tbody></table><p><strong>Step 3</strong> 🔧 点击绿色按钮 <strong>Create repository</strong> 完成创建</p><hr><h2 id="二、生成-GitHub-Token"><a href="#二、生成-GitHub-Token" class="headerlink" title="二、生成 GitHub Token"></a>二、生成 GitHub Token</h2><p><strong>Step 1</strong> 🔑 依次进入：<strong>头像 → <code>Settings</code> → <code>Developer settings</code> → <code>Personal access tokens</code> → <code>Tokens (classic)</code> → <code>Generate new token (classic)</code></strong></p><p><strong>Step 2</strong> 🔑 按以下要点填写：</p><table><thead><tr><th align="center">设置项</th><th align="left">填写内容</th></tr></thead><tbody><tr><td align="center">Note</td><td align="left"><code>picgo</code>（备注随意）</td></tr><tr><td align="center">Expiration</td><td align="left">按需选择有效期</td></tr><tr><td align="center">权限</td><td align="left">✅ 勾选 <strong><code>repo</code></strong>（必须）</td></tr></tbody></table><p><strong>Step 3</strong> 🔑 点击 <strong>Generate token</strong>，然后——</p><blockquote><p>⚠️ <strong>立即复制并妥善保存！Token 只显示这一次，刷新页面后就再也看不到了。</strong></p></blockquote><hr><h2 id="三、安装并配置-PicGo"><a href="#三、安装并配置-PicGo" class="headerlink" title="三、安装并配置 PicGo"></a>三、安装并配置 PicGo</h2><h3 id="3-1-下载安装"><a href="#3-1-下载安装" class="headerlink" title="3.1 下载安装"></a>3.1 下载安装</h3><p>前往 <a href="https://github.com/Molunerfinn/PicGo/releases">PicGo Releases</a> 下载对应系统的安装包：</p><table><thead><tr><th align="center">系统</th><th align="left">安装包</th></tr></thead><tbody><tr><td align="center">🪟 Windows</td><td align="left"><code>.exe</code></td></tr><tr><td align="center">🍎 macOS</td><td align="left"><code>.dmg</code></td></tr></tbody></table><h3 id="3-2-配置图床"><a href="#3-2-配置图床" class="headerlink" title="3.2 配置图床"></a>3.2 配置图床</h3><p>打开 PicGo → <strong>图床设置</strong> → <strong>GitHub 图床</strong>，按下表逐项填写：</p><table><thead><tr><th align="center">配置项</th><th align="left">填写内容</th><th align="left">⚠️ 关键说明</th></tr></thead><tbody><tr><td align="center">设定仓库名</td><td align="left"><code>你的用户名/仓库名</code></td><td align="left">如 <code>yourname/images</code></td></tr><tr><td align="center">设定分支名</td><td align="left"><code>main</code></td><td align="left">老仓库可能是 <code>master</code></td></tr><tr><td align="center">设定 Token</td><td align="left">粘贴第二步的 Token</td><td align="left"></td></tr><tr><td align="center">设定存储路径</td><td align="left"><code>img/</code></td><td align="left">⚠️ <strong>末尾斜杠必须带上</strong>，否则目录名会和文件名粘连</td></tr><tr><td align="center">设定自定义域名</td><td align="left"><code>https://cdn.jsdelivr.net/gh/你的用户名/仓库名@main</code></td><td align="left">⚠️ <strong><code>@main</code> 必须带上</strong>，否则报 <code>Invalid URL</code></td></tr></tbody></table><p>填写完成后点击 <strong>确定</strong> → <strong>设为默认图床</strong> ✅</p><hr><h2 id="四、使用与验证"><a href="#四、使用与验证" class="headerlink" title="四、使用与验证"></a>四、使用与验证</h2><p><strong>Step 1</strong> 🚀 打开 PicGo <strong>上传区</strong>，拖入或选择图片上传</p><p><strong>Step 2</strong> 🚀 上传成功后，剪贴板自动复制如下格式的链接：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs text">https://cdn.jsdelivr.net/gh/yourname/images@main/img/xxx.png<br></code></pre></td></tr></table></figure><p><strong>Step 3</strong> 🚀 在浏览器打开该链接，图片正常显示即大功告成 🎉</p><details><summary>📦 推荐的 PicGo 设置（点击展开）</summary><ul><li>✅ 开启「上传后自动复制 URL」</li><li>✅ 安装 <code>rename-file</code> 插件：自动按时间戳重命名，避免文件名冲突</li><li>✅ 安装 <code>web-uploader</code> 插件：可扩展自定义图床接口</li></ul></details><hr><h2 id="五、进阶玩法"><a href="#五、进阶玩法" class="headerlink" title="五、进阶玩法"></a>五、进阶玩法</h2><details><summary>📝 Typora 联动 —— 写作时自动上传</summary><p>偏好设置 → 图像 → 插入图片时选择「上传图片」→ 上传服务选 <code>PicGo(app)</code> → 指定 PicGo 安装路径。之后在文中粘贴图片会自动上传并替换为 CDN 链接。</p></details><details><summary>🔄 缓存刷新 —— 更新同名图片后必看</summary><p>jsDelivr 有 CDN 缓存，更新同名图片后访问 <code>https://purge.jsdelivr.net/图片完整URL</code> 主动刷新缓存。</p></details><details><summary>🌏 备用节点 —— 国内访问不畅时使用</summary><p>若 <code>cdn.jsdelivr.net</code> 访问不畅，可将自定义域名替换为：</p><ul><li><code>https://fastly.jsdelivr.net/gh/用户名/仓库名@main</code></li><li><code>https://gcore.jsdelivr.net/gh/用户名/仓库名@main</code></li></ul></details><hr><blockquote><p>🎉 <strong>结语</strong>：至此，一套零成本、全球加速的图床就搭建完成了。从此写博客贴图只需一步——拖进去，链接自动到手。</p></blockquote>]]>
    </content>
    <id>http://example.com/2026/10/13/%E6%9C%AC%E5%9C%B0%E7%94%B5%E8%84%91%E6%90%AD%E5%BB%BA%20PicGo%20+%20GitHub%20+%20jsDelivr%20%E5%9B%BE%E5%BA%8A%20-%20%E5%89%AF%E6%9C%AC/</id>
    <link href="http://example.com/2026/10/13/%E6%9C%AC%E5%9C%B0%E7%94%B5%E8%84%91%E6%90%AD%E5%BB%BA%20PicGo%20+%20GitHub%20+%20jsDelivr%20%E5%9B%BE%E5%BA%8A%20-%20%E5%89%AF%E6%9C%AC/"/>
    <published>2026-10-13T13:31:04.239Z</published>
    <summary>这篇文章手把手教你用 PicGo 搭配 GitHub 和 jsDelivr 搭建零成本免费图床，实现本地一键上传并自动复制全球加速链接的丝滑写作体验。全文分为五大部分：一是创建 GitHub 图床仓库，登录后新建 repository 并按要点填写；二是生成 GitHub Token，进入开发者设置创建 classic token，并强调立即复制保存因为只显示一次；三是安装配置 PicGo，下载对应系统安装包后在 GitHub 图床中逐项填写并设为默认；四是使用与验证，上传图片后剪贴板自动复制 jsDelivr 加速链接，并推荐开启上传后自动复制 URL、安装 rename-file 与 web-uploader 插件；五是进阶玩法，包括 Typora 联动自动上传、通过 purge 接口刷新 CDN 缓存以及 fastly、gcore 等备用节点。</summary>
    <title>本地电脑搭建 PicGo + GitHub + jsDelivr 图床</title>
    <updated>2026-10-13T13:31:04.239Z</updated>
  </entry>
  <entry>
    <author>
      <name>阿木</name>
    </author>
    <category term="十年之约" scheme="http://example.com/categories/%E5%8D%81%E5%B9%B4%E4%B9%8B%E7%BA%A6/"/>
    <category term="生活" scheme="http://example.com/tags/%E7%94%9F%E6%B4%BB/"/>
    <content>
      <![CDATA[<style>.ai-summary-box{margin:0 0 1.5em 0;border:1px solid #d8e6ff;border-radius:8px;overflow:hidden;font-size:0.95em;background:#fff}.ai-summary-box-header{display:flex;align-items:center;gap:6px;padding:0.5em 1em;background:linear-gradient(90deg,rgba(74,158,255,0.12),rgba(74,158,255,0.03));border-bottom:1px solid #d8e6ff;font-weight:600;color:#2b7de9}.ai-summary-box-header svg{width:1.1em;height:1.1em;flex:none}.ai-summary-typing{padding:0.8em 1em;line-height:1.7;min-height:1.7em;color:#444}.ai-summary-cursor{display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-0.15em;background:#4a9eff;animation:ai-cursor-blink 0.8s steps(1) infinite}@keyframes ai-cursor-blink{50%{opacity:0}}</style><div class="ai-summary-box"><div class="ai-summary-box-header"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 1 4 4c0 1.1-.45 2.1-1.17 2.83L12 12l-2.83-3.17A4 4 0 0 1 12 2z"/><circle cx="12" cy="6" r="1"/><path d="M5 10v4l7 4 7-4v-4"/><path d="M12 18v4"/></svg><span>AI 摘要</span></div><div class="ai-summary-typing" data-text="这篇文章讲述了作者决定加入『十年之约』活动的全过程与心路历程。文章首先解释了『十年之约』是一个鼓励博主持续写作十年、记录个人成长与互联网变迁的长期承诺。作者回顾了自己多年 blogging 的起伏经历，从最初的热情到中途的懈怠，再到现在重新找回书写意义，最终在深思熟虑后主动申请加入。文中详细描述了提交申请时的仪式感、审核机制以及成功加入后的责任感，强调了这一约定并非简单标榜，而是对时间、毅力和自我表达的庄重承诺。作者还分享了未来十年的计划与期许，包括坚持原创、减少碎片化表达、注重内容价值，并希望通过长期记录见证个人与网络的共同进化。整篇文章充满自省与鼓励，呼吁更多志同道合者加入这场跨越十年的数字生存实验。"><span class="ai-summary-text"></span><span class="ai-summary-cursor"></span></div></div><script>(function(){function init(){var els=document.querySelectorAll(".ai-summary-typing");for(var k=0;k<els.length;k++){(function(el){if(el.getAttribute("data-done"))return;el.setAttribute("data-done","1");var text=el.getAttribute("data-text")||"";var target=el.querySelector(".ai-summary-text");var i=0;var timer=setInterval(function(){target.textContent=text.slice(0,++i);if(i>=text.length){clearInterval(timer);setTimeout(function(){var c=el.querySelector(".ai-summary-cursor");if(c)c.style.display="none";},2000);}},45);})(els[k]);}}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init);}else{init();}})();</script><h2 id="缘起"><a href="#缘起" class="headerlink" title="缘起"></a>缘起</h2><blockquote><p>十年给自己一个计划，十年后再来看看，也是一个目标。</p></blockquote><h2 id="十年之约"><a href="#十年之约" class="headerlink" title="十年之约"></a>十年之约</h2><blockquote><p>起始于 <strong>2026年10月07日</strong>，相约至 <strong>2036年10月07日</strong>。</p></blockquote><div style="max-width:560px;margin:24px auto;padding:30px 28px;border-radius:16px;background:linear-gradient(135deg,#1a1a2e,#0f3460);color:#fff;font-family:'PingFang SC','Microsoft YaHei',sans-serif;text-align:center;border:1px solid rgba(255,255,255,0.1);box-shadow:0 12px 32px rgba(15,52,96,0.35);">  <div style="font-size:18px;letter-spacing:5px;margin-bottom:4px;font-weight:700;color:#8fd3f4;">✨ 十年之约 ✨</div>  <div style="font-size:12px;opacity:0.45;margin-bottom:22px;">2026.10.07 ── 2036.10.07</div>  <div style="display:flex;justify-content:center;gap:12px;margin-bottom:24px;">    <div style="min-width:78px;padding:14px 6px;border-radius:12px;background:rgba(255,255,255,0.08);">      <div id="pact-d" style="font-size:28px;font-weight:700;color:#8fd3f4;">--</div>      <div style="font-size:11px;opacity:0.5;margin-top:3px;">天</div>    </div>    <div style="min-width:78px;padding:14px 6px;border-radius:12px;background:rgba(255,255,255,0.08);">      <div id="pact-h" style="font-size:28px;font-weight:700;color:#fbc2eb;">--</div>      <div style="font-size:11px;opacity:0.5;margin-top:3px;">时</div>    </div>    <div style="min-width:78px;padding:14px 6px;border-radius:12px;background:rgba(255,255,255,0.08);">      <div id="pact-m" style="font-size:28px;font-weight:700;color:#a18cd1;">--</div>      <div style="font-size:11px;opacity:0.5;margin-top:3px;">分</div>    </div>    <div style="min-width:78px;padding:14px 6px;border-radius:12px;background:rgba(255,255,255,0.08);">      <div id="pact-s" style="font-size:28px;font-weight:700;color:#fff;">--</div>      <div style="font-size:11px;opacity:0.5;margin-top:3px;">秒</div>    </div>  </div>  <div style="height:12px;border-radius:999px;background:rgba(255,255,255,0.1);overflow:hidden;margin-bottom:8px;">    <div id="pact-bar" style="height:100%;width:0%;border-radius:999px;background:linear-gradient(90deg,#a18cd1,#fbc2eb,#8fd3f4);"></div>  </div>  <div id="pact-percent" style="font-size:13px;opacity:0.75;">--%</div>  <div id="pact-quote" style="margin-top:14px;font-size:13px;opacity:0.55;font-style:italic;"></div></div><script>(function () {  var START = new Date('2026-10-07T00:00:00');  var END = new Date('2036-10-07T00:00:00');  var el = {    d: document.getElementById('pact-d'),    h: document.getElementById('pact-h'),    m: document.getElementById('pact-m'),    s: document.getElementById('pact-s'),    bar: document.getElementById('pact-bar'),    pct: document.getElementById('pact-percent'),    q: document.getElementById('pact-quote')  };  var total = END - START;  var quote = '';  function tick() {    var now = Date.now();    var passed = now - START.getTime();    var left = Math.max(0, END.getTime() - now);    var ratio = Math.min(1, Math.max(0, passed / total));    el.d.textContent = Math.floor(left / 86400000).toLocaleString('en-US');    el.h.textContent = ('0' + Math.floor(left / 3600000) % 24).slice(-2);    el.m.textContent = ('0' + Math.floor(left / 60000) % 60).slice(-2);    el.s.textContent = ('0' + Math.floor(left / 1000) % 60).slice(-2);    el.bar.style.width = (ratio * 100).toFixed(2) + '%';    el.pct.textContent = '旅程进度 ' + (ratio * 100).toFixed(2) + '% · 已坚持 ' + Math.floor(passed / 86400000) + ' 天';    var t = ratio >= 1 ? '十年之约，圆满达成！这份坚持值得铭记 🏆'          : ratio >= 0.5 ? '行程过半，胜利在望，继续加油 💪'          : '加油，努力，活着 🌱';    if (t !== quote) { quote = t; el.q.textContent = '❝ ' + t + ' ❞'; }  }  tick();  setInterval(tick, 1000);})();</script><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><blockquote><p>希望能坚持到十年，加油吧！！</p></blockquote>]]>
    </content>
    <id>http://example.com/2026/10/12/%E5%8D%81%E5%B9%B4%E4%B9%8B%E7%BA%A6/</id>
    <link href="http://example.com/2026/10/12/%E5%8D%81%E5%B9%B4%E4%B9%8B%E7%BA%A6/"/>
    <published>2026-10-12T02:30:00.000Z</published>
    <summary>这篇文章讲述了作者决定加入『十年之约』活动的全过程与心路历程。文章首先解释了『十年之约』是一个鼓励博主持续写作十年、记录个人成长与互联网变迁的长期承诺。作者回顾了自己多年 blogging 的起伏经历，从最初的热情到中途的懈怠，再到现在重新找回书写意义，最终在深思熟虑后主动申请加入。文中详细描述了提交申请时的仪式感、审核机制以及成功加入后的责任感，强调了这一约定并非简单标榜，而是对时间、毅力和自我表达的庄重承诺。作者还分享了未来十年的计划与期许，包括坚持原创、减少碎片化表达、注重内容价值，并希望通过长期记录见证个人与网络的共同进化。整篇文章充满自省与鼓励，呼吁更多志同道合者加入这场跨越十年的数字生存实验。</summary>
    <title>加入十年之约</title>
    <updated>2026-10-13T13:31:04.239Z</updated>
  </entry>
  <entry>
    <author>
      <name>阿木</name>
    </author>
    <category term="训练" scheme="http://example.com/categories/%E8%AE%AD%E7%BB%83/"/>
    <category term="跑步" scheme="http://example.com/categories/%E8%AE%AD%E7%BB%83/%E8%B7%91%E6%AD%A5/"/>
    <content>
      <![CDATA[<style>.ai-summary-box{margin:0 0 1.5em 0;border:1px solid #d8e6ff;border-radius:8px;overflow:hidden;font-size:0.95em;background:#fff}.ai-summary-box-header{display:flex;align-items:center;gap:6px;padding:0.5em 1em;background:linear-gradient(90deg,rgba(74,158,255,0.12),rgba(74,158,255,0.03));border-bottom:1px solid #d8e6ff;font-weight:600;color:#2b7de9}.ai-summary-box-header svg{width:1.1em;height:1.1em;flex:none}.ai-summary-typing{padding:0.8em 1em;line-height:1.7;min-height:1.7em;color:#444}.ai-summary-cursor{display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-0.15em;background:#4a9eff;animation:ai-cursor-blink 0.8s steps(1) infinite}@keyframes ai-cursor-blink{50%{opacity:0}}</style><div class="ai-summary-box"><div class="ai-summary-box-header"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 1 4 4c0 1.1-.45 2.1-1.17 2.83L12 12l-2.83-3.17A4 4 0 0 1 12 2z"/><circle cx="12" cy="6" r="1"/><path d="M5 10v4l7 4 7-4v-4"/><path d="M12 18v4"/></svg><span>AI 摘要</span></div><div class="ai-summary-typing" data-text="距离比赛只剩 30 天。被工作按在原地太久，山路都快认不出我了。今晚难得早下班，不找借口，收拾装备即刻出发——欠下的训练，从今晚开始一笔一笔还。剩下的日子，把每一步都走扎实。"><span class="ai-summary-text"></span><span class="ai-summary-cursor"></span></div></div><script>(function(){function init(){var els=document.querySelectorAll(".ai-summary-typing");for(var k=0;k<els.length;k++){(function(el){if(el.getAttribute("data-done"))return;el.setAttribute("data-done","1");var text=el.getAttribute("data-text")||"";var target=el.querySelector(".ai-summary-text");var i=0;var timer=setInterval(function(){target.textContent=text.slice(0,++i);if(i>=text.length){clearInterval(timer);setTimeout(function(){var c=el.querySelector(".ai-summary-cursor");if(c)c.style.display="none";},2000);}},45);})(els[k]);}}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init);}else{init();}})();</script><h2 id="倒计时-30-天"><a href="#倒计时-30-天" class="headerlink" title="倒计时 30 天"></a>倒计时 30 天</h2><p>距离比赛，还有 30 天。</p><p>这段时间被工作按在原地，山上的路都快认不出我了。</p><p>今天难得早下班。不找借口，不磨蹭，收拾好装备，即刻出发。</p><p>欠下的训练，从今晚开始一笔一笔还。剩下的日子，把每一步都走扎实。</p><p><img src="https://img2.tofaka.com/autoupload/fr/owOcZcTMPh5xd7yLcFbVqxCXIFissGeGnRLL2dHgcg6yl5f0KlZfm6UsKj-HyTuv/20261008/NiTh/4032X3024/IMG_5552.JPG" alt="今晚第一练"></p><p>太久没上山，一开爬就喘得不行，身体很诚实地提醒我欠了多少账。</p><p><img src="https://img2.tofaka.com/autoupload/f/rhckp/20261008/Ub8S/3024X4032/IMG_5558.JPG/webp" alt="IMG_5558.JPG"></p><p>过程就不多说了，一个字：累。直接放图。</p><p><img src="https://img2.tofaka.com/autoupload/f/rhckp/20261008/gYWA/4032X3024/IMG_5608.JPG/webp" alt="IMG_5608.JPG"></p><p><img src="https://img2.tofaka.com/autoupload/f/rhckp/20261008/o0cz/3024X4032/IMG_5600.JPG/webp" alt="IMG_5600.JPG"></p><p><img src="https://img2.tofaka.com/autoupload/f/rhckp/20261008/DDWK/4032X3024/IMG_5576.JPG/webp" alt="IMG_5576.JPG"></p><p><img src="https://img2.tofaka.com/autoupload/f/rhckp/20261008/SFRM/1179X2148/B17B551141E9B435ADF983FD3BF12B53.png/webp" alt="B17B551141E9B435ADF983FD3BF12B53.png"></p>]]>
    </content>
    <id>http://example.com/2026/10/12/%E6%97%A5%E5%B8%B8%E8%AE%AD%E7%BB%83/</id>
    <link href="http://example.com/2026/10/12/%E6%97%A5%E5%B8%B8%E8%AE%AD%E7%BB%83/"/>
    <published>2026-10-12T02:30:00.000Z</published>
    <summary>距离比赛只剩 30 天。被工作按在原地太久，山路都快认不出我了。今晚难得早下班，不找借口，收拾装备即刻出发——欠下的训练，从今晚开始一笔一笔还。剩下的日子，把每一步都走扎实。</summary>
    <title>日常训练</title>
    <updated>2026-10-13T13:31:04.239Z</updated>
  </entry>
  <entry>
    <author>
      <name>阿木</name>
    </author>
    <category term="白嫖" scheme="http://example.com/categories/%E7%99%BD%E5%AB%96/"/>
    <category term="魔改" scheme="http://example.com/categories/%E7%99%BD%E5%AB%96/%E9%AD%94%E6%94%B9/"/>
    <content>
      <![CDATA[<style>.ai-summary-box{margin:0 0 1.5em 0;border:1px solid #d8e6ff;border-radius:8px;overflow:hidden;font-size:0.95em;background:#fff}.ai-summary-box-header{display:flex;align-items:center;gap:6px;padding:0.5em 1em;background:linear-gradient(90deg,rgba(74,158,255,0.12),rgba(74,158,255,0.03));border-bottom:1px solid #d8e6ff;font-weight:600;color:#2b7de9}.ai-summary-box-header svg{width:1.1em;height:1.1em;flex:none}.ai-summary-typing{padding:0.8em 1em;line-height:1.7;min-height:1.7em;color:#444}.ai-summary-cursor{display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-0.15em;background:#4a9eff;animation:ai-cursor-blink 0.8s steps(1) infinite}@keyframes ai-cursor-blink{50%{opacity:0}}</style><div class="ai-summary-box"><div class="ai-summary-box-header"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 1 4 4c0 1.1-.45 2.1-1.17 2.83L12 12l-2.83-3.17A4 4 0 0 1 12 2z"/><circle cx="12" cy="6" r="1"/><path d="M5 10v4l7 4 7-4v-4"/><path d="M12 18v4"/></svg><span>AI 摘要</span></div><div class="ai-summary-typing" data-text="这里是AI，这篇文章主要记录了作者对Hexo+Fluid主题博客的魔改过程，重点介绍了评论系统的搭建。作者对比了Artalk、Waline、Giscus、Twikoo后选用了Twikoo，因其支持访客免登录评论且部署简单。部署方案采用Netlify（Serverless函数）作为后端，MongoDB Atlas的M0免费集群作为数据库，使用Netlify分配的域名，实现了零成本部署。文章还详细记录了踩坑经历：首次访问时报错“未设置环境变量MONGODB_URI”，需在Netlify环境变量中正确配置数据库连接字符串。作者希望通过分享这些经验，为同样想折腾博客的朋友提供参考。"><span class="ai-summary-text"></span><span class="ai-summary-cursor"></span></div></div><script>(function(){function init(){var els=document.querySelectorAll(".ai-summary-typing");for(var k=0;k<els.length;k++){(function(el){if(el.getAttribute("data-done"))return;el.setAttribute("data-done","1");var text=el.getAttribute("data-text")||"";var target=el.querySelector(".ai-summary-text");var i=0;var timer=setInterval(function(){target.textContent=text.slice(0,++i);if(i>=text.length){clearInterval(timer);setTimeout(function(){var c=el.querySelector(".ai-summary-cursor");if(c)c.style.display="none";},2000);}},45);})(els[k]);}}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init);}else{init();}})();</script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>博客搭起来之后，手就停不下来了。原本一个干干净净的 Hexo + Fluid 主题，硬是被我东改西改，折腾成了现在的样子。这篇文章记录一下这段时间都魔改了些什么，顺便把踩过的坑也写出来，给同样想折腾的朋友一个参考。</p><h2 id="一、评论系统：Twikoo"><a href="#一、评论系统：Twikoo" class="headerlink" title="一、评论系统：Twikoo"></a>一、评论系统：Twikoo</h2><p>静态博客没有后端，评论功能只能靠第三方系统。对比了一圈 Artalk、Waline、Giscus、Twikoo 之后，最终选择了 <strong>Twikoo</strong>——访客免登录就能评论，部署也简单。</p><h3 id="部署方案：Netlify-MongoDB-Atlas（全免费）"><a href="#部署方案：Netlify-MongoDB-Atlas（全免费）" class="headerlink" title="部署方案：Netlify + MongoDB Atlas（全免费）"></a>部署方案：Netlify + MongoDB Atlas（全免费）</h3><ul><li><strong>后端</strong>：部署在 Netlify，白嫖 Serverless 函数；</li><li><strong>数据库</strong>：MongoDB Atlas 的 M0 免费集群（512MB，个人博客评论绰绰有余）；</li><li><strong>域名</strong>：直接用 Netlify 分配的地址，一分钱没花。</li></ul><p>##文章自动生成文章缩略图</p>]]>
    </content>
    <id>http://example.com/2026/10/11/%E7%BD%91%E7%AB%99%E9%AD%94%E6%94%B9%E4%BA%86%E4%BB%80%E4%B9%88/</id>
    <link href="http://example.com/2026/10/11/%E7%BD%91%E7%AB%99%E9%AD%94%E6%94%B9%E4%BA%86%E4%BB%80%E4%B9%88/"/>
    <published>2026-10-11T09:30:00.000Z</published>
    <summary>这里是AI，这篇文章主要记录了作者对Hexo+Fluid主题博客的魔改过程，重点介绍了评论系统的搭建。作者对比了Artalk、Waline、Giscus、Twikoo后选用了Twikoo，因其支持访客免登录评论且部署简单。部署方案采用Netlify（Serverless函数）作为后端，MongoDB Atlas的M0免费集群作为数据库，使用Netlify分配的域名，实现了零成本部署。文章还详细记录了踩坑经历：首次访问时报错“未设置环境变量MONGODB_URI”，需在Netlify环境变量中正确配置数据库连接字符串。作者希望通过分享这些经验，为同样想折腾博客的朋友提供参考。</summary>
    <title>网站魔改了什么</title>
    <updated>2026-10-13T13:31:04.239Z</updated>
  </entry>
  <entry>
    <author>
      <name>阿木</name>
    </author>
    <category term="Vercel" scheme="http://example.com/categories/Vercel/"/>
    <category term="hexo" scheme="http://example.com/tags/hexo/"/>
    <category term="AI" scheme="http://example.com/tags/AI/"/>
    <content>
      <![CDATA[<style>.ai-summary-box{margin:0 0 1.5em 0;border:1px solid #d8e6ff;border-radius:8px;overflow:hidden;font-size:0.95em;background:#fff}.ai-summary-box-header{display:flex;align-items:center;gap:6px;padding:0.5em 1em;background:linear-gradient(90deg,rgba(74,158,255,0.12),rgba(74,158,255,0.03));border-bottom:1px solid #d8e6ff;font-weight:600;color:#2b7de9}.ai-summary-box-header svg{width:1.1em;height:1.1em;flex:none}.ai-summary-typing{padding:0.8em 1em;line-height:1.7;min-height:1.7em;color:#444}.ai-summary-cursor{display:inline-block;width:2px;height:1em;margin-left:2px;vertical-align:-0.15em;background:#4a9eff;animation:ai-cursor-blink 0.8s steps(1) infinite}@keyframes ai-cursor-blink{50%{opacity:0}}</style><div class="ai-summary-box"><div class="ai-summary-box-header"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 1 4 4c0 1.1-.45 2.1-1.17 2.83L12 12l-2.83-3.17A4 4 0 0 1 12 2z"/><circle cx="12" cy="6" r="1"/><path d="M5 10v4l7 4 7-4v-4"/><path d="M12 18v4"/></svg><span>AI 摘要</span></div><div class="ai-summary-typing" data-text="这里是AI，这篇文章介绍了Vercel CLI的安装与使用方法。首先，在电脑终端运行Node.js命令npm install -g vercel进行全局安装。安装完成后，在博客根目录执行vercel login，根据提示选择GitHub等方式登录账号。接着再次使用vercel login命令，一路按回车确认默认设置，以初始化或关联本地项目与Vercel账号。最后，可选执行vercel dev命令进行本地开发预览，便于调试。整体流程简洁，方便开发者快速部署项目至Vercel平台。"><span class="ai-summary-text"></span><span class="ai-summary-cursor"></span></div></div><script>(function(){function init(){var els=document.querySelectorAll(".ai-summary-typing");for(var k=0;k<els.length;k++){(function(el){if(el.getAttribute("data-done"))return;el.setAttribute("data-done","1");var text=el.getAttribute("data-text")||"";var target=el.querySelector(".ai-summary-text");var i=0;var timer=setInterval(function(){target.textContent=text.slice(0,++i);if(i>=text.length){clearInterval(timer);setTimeout(function(){var c=el.querySelector(".ai-summary-cursor");if(c)c.style.display="none";},2000);}},45);})(els[k]);}}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",init);}else{init();}})();</script><p>如何安装 Vercel CLI？</p><p>你只需要在电脑的终端（Windows 的 CMD&#x2F;PowerShell，或者 Mac 的 Terminal）中，运行以下 Node.js 命令进行全局安装：</p><div class="pCTyYe" dir="ltr" data-processed="true"><pre data-processed="true"><code jsuid="IcYX5b_k3" data-processed="true"><span class="undefined" data-processed="true">npm install -g vercel</span></code></pre></div><p>安装后如何使用？</p><ol><li>安装完成后，你可以在博客根目录下执行以下三步：</li></ol><div class="pCTyYe" dir="ltr" data-processed="true"><pre data-processed="true"><code jsuid="IcYX5b_mi" data-processed="true"><span class="undefined" data-processed="true">vercel login</span></code></pre></div><em class="eujQNb" jsaction="" jscontroller="yHWXO" data-sfc-root="c" jsuid="IcYX5b_n1" data-sfc-cb="" data-complete="true" data-processed="true">(根据提示选择你的登录方式，如 GitHub)<!--TgQPHd|[]--></em><ol start="2"><li>初始化&#x2F;关联项目：</li></ol><div class="pCTyYe" dir="ltr" data-processed="true"><pre data-processed="true"><code jsuid="IcYX5b_mi" data-processed="true"><span class="undefined" data-processed="true">vercel login</span></code></pre></div><em class="eujQNb" jsaction="" jscontroller="yHWXO" data-sfc-root="c" jsuid="IcYX5b_nv" data-sfc-cb="" data-complete="true" data-processed="true" aria-owns="action-menu-parent-container">(一路按回车确认默认设置即可，它会把本地项目和 Vercel 账号关联)<!--TgQPHd|[]--></em><ol start="3"><li>本地开发预览（选做）：</li></ol><div class="pHpOfb" data-animation-atomic="" data-processed="true"><div class="z0e9Qd" data-processed="true"><div class="vVRw1d" data-processed="true">bash</div></div><div class="pCTyYe" dir="ltr" data-processed="true"><pre data-processed="true"><code jsuid="IcYX5b_o8" data-processed="true"><span class="undefined" data-processed="true">vercel dev</span></code></pre></div></div><script src="https://utteranc.es/client.js"        repo="[https://github.com/915964222/GitHub]"        issue-term="GitHub"        theme="github-light"        crossorigin="anonymous"        async></script>]]>
    </content>
    <id>http://example.com/2026/09/22/%E5%AE%89%E8%A3%85Vercel%20CLI/</id>
    <link href="http://example.com/2026/09/22/%E5%AE%89%E8%A3%85Vercel%20CLI/"/>
    <published>2026-09-22T16:00:00.000Z</published>
    <summary>这里是AI，这篇文章介绍了Vercel CLI的安装与使用方法。首先，在电脑终端运行Node.js命令npm install -g vercel进行全局安装。安装完成后，在博客根目录执行vercel login，根据提示选择GitHub等方式登录账号。接着再次使用vercel login命令，一路按回车确认默认设置，以初始化或关联本地项目与Vercel账号。最后，可选执行vercel dev命令进行本地开发预览，便于调试。整体流程简洁，方便开发者快速部署项目至Vercel平台。</summary>
    <title>安装Vercel CLI</title>
    <updated>2026-10-13T13:31:04.239Z</updated>
  </entry>
</feed>
