<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>林泽凯的小站</title>
    <link>http://www.linzekai.cn/</link>
    <language>zh-CN</language>
    <copyright>All rights reserved 2026, 林泽凯</copyright>
    <lastBuildDate>Wed, 24 Jun 2026 16:29:43 GMT</lastBuildDate>
    <generator>Hexo</generator>
    <atom:link href="http://www.linzekai.cn/atom.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>兜兜转转归来还是wordpress</title>
      <link>http://www.linzekai.cn/posts/699621e4/</link>
      <description>
        <![CDATA[<div class="note note-info">
            <p>新网站已上线 <a href="https://www.linzekai.cn" target="_blank" style="color: inherit; text-decoration:]]>
      </description>
      <author>林泽凯</author>
      <pubDate>Sat, 20 Jun 2026 07:18:45 GMT</pubDate>
      <content:encoded>
        <![CDATA[<div class="note note-info">            <p>新网站已上线 <a href="https://www.linzekai.cn" target="_blank" style="color: inherit; text-decoration: underline;">点此访问</a></p>          </div><p>虽然我写下的文字不多，但是我换的博客系统很多，写过的博客配置文件比我目前所有已发布文章的字数加起来多几倍。Hexo、Hugo、Ghost、Typecho、wordpress…</p><p>最开始就是wordpress承载了我的文章，其次用的最久的是Hexo。成人之际，我又把博客系统换回了wordpress。首要理由当然是买得起服务器啦。</p><p>作为一个表现欲很强的人，自然是要为我的兽设打造一套适配他的主题，很高兴它现在已经初具雏形了，现已将主题开源，感兴趣的可以去仓库看看。</p><p>扯远了，总之，当下最适合我的系统是wordpress，即使它笨重、古老、被攻击者青睐，但它很省心，适合折腾劲已经消磨殆尽的我。至于主题，那是我给自己在高考后的空虚时光里找的填充物：把个性烙进代码里，然后开源，仅仅是为了逼自己把这件事做完，毕竟仓库都公开了，总不好只写一个README就逃跑。</p><p>折腾博客系统的那几年，我一直误以为自己在寻找“最适合写作的环境”，后来才明白，最适合写作的环境就是写完了还能接着写第二个的环境。 WordPress 够成熟，成熟到不再令我有探索的冲动，只剩下使用的惯性。当工具失去“可玩性”，写作才恢复“必要性”。</p><p>兜兜转转，归来仍是wordpress。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>高考后</title>
      <link>http://www.linzekai.cn/posts/3be9e641/</link>
      <description>
        <![CDATA[<p>高考最后十五分钟铃响的时候，我已经答完所有题目，坐在位子上回忆我的十二年求学经历。说是求学，其实更倾向于被推着学，热情在初二那年烧成了灰，后面几年全靠惯性前进。十五分钟的沉思，足够我理一理”我从哪里来”，却远远不够我想明白”我要到哪里去”。</p>
<p>考完试，我并没有想]]>
      </description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E9%9A%8F%E7%AC%94/">随笔</category>
      <category domain="http://www.linzekai.cn/tags/%E9%AB%98%E8%80%83/">高考</category>
      <pubDate>Sun, 14 Jun 2026 03:32:14 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>高考最后十五分钟铃响的时候，我已经答完所有题目，坐在位子上回忆我的十二年求学经历。说是求学，其实更倾向于被推着学，热情在初二那年烧成了灰，后面几年全靠惯性前进。十五分钟的沉思，足够我理一理”我从哪里来”，却远远不够我想明白”我要到哪里去”。</p><p>考完试，我并没有想象中如释重负的感觉，像一场漫长的雨终于停了，可你还站在屋檐下，不知道该往哪儿走。高考结束的十几天里本应是我人生中最自由的时光，没有课业，没有定时定点的生活，但是每当听到有关高考的讯息，心头还是忍不住震颤，决定我接下来去哪里的三位数正在某个服务器里生成，它跟我隔了层层内网，却要替我决定下一步，而我能做的只有等待。</p><p>等是一件很奇怪的事情。它把时间拉得很长，又把日子过得很碎。</p><p>凌晨三点，兄弟发来一句：</p><blockquote><p>我日兄弟&#x2F;他妈的好焦虑啊&#x2F;就剩10天能活了&#x2F;感觉这回又要骚缸了&#x2F;真的难受兄弟。</p></blockquote><p>我盯着屏幕想了几秒，回了”先享受啊肯定是”。打完之后觉得有点空，又加了一句：”真骚刚了我们也不会有多好，天塌下来肯定是一起扛啊。”发出去，忽然觉得刚才那几句话好像谁都能说，换个人发给他效果是一样的，不是不真心，只是我手里也没有别的东西可以给他了。</p><p>不知道为什么会突然想到初中的语文老师。那是个很有福气的女教师。她嗓门特别大，上课从来不用小蜜蜂。她年轻时还追过摇滚乐队，跟我们说是”指南针”，毕业回学校聊天的时候还说”你们别看我长这样，我年轻的时候也是在livehouse里蹦过的人”。</p><p>她喜欢范仲淹，这事全班都知道。有一回讲到一半突然停下来，跟我们说：”范仲淹是我的偶像。”范仲淹一生被贬了好几次，有一回他又被贬了，朋友们都替他难过，跑去送他，说了很多宽慰的话。范仲淹却笑着说——</p><blockquote><p>不以物喜，不以己悲。</p></blockquote><p>她说范仲淹讲这话的时候，是在被贬的路上，别人替他委屈，他却在想洞庭湖的事。</p><p>当时我不太懂，只是觉得这人有点傻。不过隐约觉得，一个人能在一片灰暗里看出光景来，这件事情本身就很厉害。外面天还是黑的，我在等一个三位数，范仲淹在等他的贬谪通知书。他等了那么多年，我这才十几天。我的语文老师，从摇滚乐迷变成了讲范仲淹的人，她大概也等过很多东西吧。</p><p>高考后第三天，我开了股票账户。第一笔交易，我填错了买入价4.893，这个数字我想我会记住很久。买入那一秒我还没反应过来，等到成交明细弹出来，才发现自己比市价高了一大截。510300，当场，账面浮亏1.9元。</p><p>亏了1.9元，好像也没什么大不了的。天塌下来也分很多种，有的天是一起扛的，有的天是1.9元。</p><p>雨停了之后不一定立刻就有太阳，可能还要阴一阵子，路面上还有积水，突起的方砖踩下去还是会喷出水来。但雨确实是停了。范仲淹说”不以物喜，不以己悲”，并不是说人不会焦虑，不会难过，只是那些东西来了就来了，走了就走了，心里那条路还是得自己走。</p><p>或许焦虑的原因是：以前我们早早就选定了到哪去的目标，但是这个问题，其实可以一边往前走一边想。就像初中语文老师，谁能想到一个追指南针乐队的女孩，后来长成了胖胖的很有福气的样子，站在讲台上用最大的嗓门讲范仲淹。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>让 Hexo Fluid 友链页每次刷新都随机排序</title>
      <link>http://www.linzekai.cn/posts/a12b31b0/</link>
      <description>
        <![CDATA[<p>友链页每次打开都是同样的顺序，排在前面的朋友曝光率永远最高，排在后面的则几乎不会被注意到。于是我决定给友链页加一点小小的随机性：<strong>每次刷新，卡片顺序都不一样</strong>。</p>
<h2 id="思路"><a href="#思路" class="head]]>
      </description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/Fluid/">Fluid</category>
      <pubDate>Mon, 23 Feb 2026 09:58:15 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>友链页每次打开都是同样的顺序，排在前面的朋友曝光率永远最高，排在后面的则几乎不会被注意到。于是我决定给友链页加一点小小的随机性：<strong>每次刷新，卡片顺序都不一样</strong>。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>Hexo 是静态博客，页面在 <code>hexo g</code> 时就已经生成好了，所以”随机”只能发生在浏览器端，也就是用 JavaScript 在页面加载后动态打乱卡片顺序。</p><h2 id="用-Fluid-的自定义-JS-注入"><a href="#用-Fluid-的自定义-JS-注入" class="headerlink" title="用 Fluid 的自定义 JS 注入"></a>用 Fluid 的自定义 JS 注入</h2><p>Fluid 提供了全局注入自定义 JS 文件的配置项。</p><p><strong>第一步</strong>，在 <code>source/js/</code> 目录下新建 <code>random-links.js</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></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-variable language_">document</span>.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">&#x27;DOMContentLoaded&#x27;</span>, <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) &#123;<br>  <span class="hljs-comment">// 只在友链页执行，避免影响其他页面</span><br>  <span class="hljs-keyword">if</span> (!<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&#x27;.links&#x27;</span>)) <span class="hljs-keyword">return</span>;<br><br>  <span class="hljs-keyword">const</span> container = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&#x27;.row.links&#x27;</span>);<br>  <span class="hljs-keyword">if</span> (!container) <span class="hljs-keyword">return</span>;<br><br>  <span class="hljs-keyword">const</span> cards = <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(container.<span class="hljs-title function_">querySelectorAll</span>(<span class="hljs-string">&#x27;:scope &gt; .card&#x27;</span>));<br><br>  <span class="hljs-comment">// Fisher-Yates 洗牌算法</span><br>  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = cards.<span class="hljs-property">length</span> - <span class="hljs-number">1</span>; i &gt; <span class="hljs-number">0</span>; i--) &#123;<br>    <span class="hljs-keyword">const</span> j = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">floor</span>(<span class="hljs-title class_">Math</span>.<span class="hljs-title function_">random</span>() * (i + <span class="hljs-number">1</span>));<br>    container.<span class="hljs-title function_">insertBefore</span>(cards[j], cards[i]);<br>    [cards[i], cards[j]] = [cards[j], cards[i]];<br>  &#125;<br>&#125;);<br></code></pre></td></tr></table></figure><p>这里用的是经典的 Fisher-Yates 洗牌算法，时间复杂度 O(n)，每张卡片出现在任意位置的概率完全相等，比 <code>sort(() =&gt; Math.random() - 0.5)</code> 那种写法严谨得多。</p><p><strong>第二步</strong>，在 <code>_config.fluid.yml</code> 中注册这个文件：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">custom_js:</span><br>  <span class="hljs-bullet">-</span> <span class="hljs-string">/js/random-links.js</span><br></code></pre></td></tr></table></figure><p><strong>第三步</strong>，重新部署。</p><h2 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h2><p>现在每次打开或刷新<a href="https://www.linzekai.cn/links">友链页</a>，卡片顺序都会重新洗牌，每个朋友的博客都有机会出现在第一位。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>从wordpress到hexo</title>
      <link>http://www.linzekai.cn/posts/8f8c4cfa/</link>
      <description>
        <![CDATA[<p>我第一次搭博客，用的是 WordPress。</p>
<p>原因现在想起来其实挺好笑的。那时候还是初中生，就喜欢那种立刻能看到效果的东西。装个主题，刷新一下页面，一个“看起来很炫酷的网站”就出来了，反馈来得特别快，快到我甚至没想过后台是什么、代码怎么写，就觉得自己已经是个“]]>
      </description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E9%9A%8F%E7%AC%94/">随笔</category>
      <category domain="http://www.linzekai.cn/tags/wordpress/">wordpress</category>
      <category domain="http://www.linzekai.cn/tags/hexo/">hexo</category>
      <pubDate>Mon, 23 Feb 2026 06:09:50 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>我第一次搭博客，用的是 WordPress。</p><p>原因现在想起来其实挺好笑的。那时候还是初中生，就喜欢那种立刻能看到效果的东西。装个主题，刷新一下页面，一个“看起来很炫酷的网站”就出来了，反馈来得特别快，快到我甚至没想过后台是什么、代码怎么写，就觉得自己已经是个“会搭网站的人”了。</p><p>但这股热情也没撑多久。文章写了两篇，一篇是“Hello World”，一篇是“我的第一篇博客”。然后，就没有然后了。三分钟热度一过，就再也没打开过后台。回头看，会觉得这事本身就挺 WordPress 的——东西来得太容易，也就走得很快。</p><p>真正的转折点，其实挺狼狈的，是某天我突然发现网站被黑了。数据被删得干干净净，也是在那一刻我第一次认真地想：如果我只是想写点东西，真的有必要这么复杂吗？</p><p>后来接触到 Hexo，没有后台，写作就是 Markdown。那种感觉很微妙，更像是在写作，而不是在维护一个系统。</p><p>可控、干净，所有东西都在我的掌控范围内。至于是不是和我master属性有关，那便不得而知了。<br>当然，也完全不是因为便宜，对吧。</p><p>Hexo 当然也不省心。主题结构复杂，很多功能要自己拼，文档有时候也不太友好。但奇怪的是，我并不讨厌这些折腾。因为我很清楚自己在干嘛，想把这个地方一点点改成我愿意长期用下去的样子。</p><p>现在回头看，我反而会把 Hexo 推荐给很多人。简单模板对个人博客来说已经完全够用了，如果你愿意折腾，它也不会限制你重来造轮子。</p><p>从 WordPress 换到 Hexo，对我来说其实不是什么技术升级。只是慢慢意识到一件事：<br>功能越少，我反而越容易坚持下去。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Vercel 部署的 Twikoo 对接自定义 Chevereto V4 图床</title>
      <link>http://www.linzekai.cn/posts/db3e042c/</link>
      <description>本文记录了在 Hexo Fluid 主题 + Twikoo（Vercel 部署）的环境下，成功对接第三方 Chevereto V4 图床的完整过程，踩了不少坑，整理成教程供参考。</description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/Fluid/">Fluid</category>
      <category domain="http://www.linzekai.cn/tags/Twikoo/">Twikoo</category>
      <category domain="http://www.linzekai.cn/tags/Chevereto/">Chevereto</category>
      <category domain="http://www.linzekai.cn/tags/Vercel/">Vercel</category>
      <pubDate>Sun, 22 Feb 2026 05:02:05 GMT</pubDate>
      <content:encoded>
        <![CDATA[<div style="background: #f8d7da; border-left: 4px solid #dc3545; color: #721c24; padding: 12px 16px; border-radius: 4px; margin: 16px 0;">  <strong>⚠ 警告：</strong>请更新twikoo版本，本代码已合并至twikoo新版本中 ~ </div><h2 id="环境说明"><a href="#环境说明" class="headerlink" title="环境说明"></a>环境说明</h2><ul><li>博客框架：Hexo Fluid 主题</li><li>评论系统：Twikoo 1.6.44（Vercel 部署）</li><li>图床：<a href="https://loveloli.me/">MoePic</a> 提供的 Chevereto V4 图床</li></ul><h2 id="核心思路"><a href="#核心思路" class="headerlink" title="核心思路"></a>核心思路</h2><p>Twikoo 1.6.44 的前端图片上传逻辑完全由后端控制。Twikoo 后端内置支持的图床有限，不支持 Chevereto。</p><p>因此方案分两步：</p><ol><li>在 Vercel 上创建一个代理接口 <code>/api/upload</code>，负责接收前端图片并转发到 Chevereto V4</li><li>在前端直接 hook Twikoo 的 Vue 组件方法 <code>onSelectImage</code>，拦截图片上传，改为调用自己的代理接口</li></ol><hr><h2 id="第一步：创建-Vercel-代理接口"><a href="#第一步：创建-Vercel-代理接口" class="headerlink" title="第一步：创建 Vercel 代理接口"></a>第一步：创建 Vercel 代理接口</h2><p>在你的 Twikoo Vercel 项目根目录创建 <code>api/upload.js</code>：</p><p><img src="https://s1.loveloli.me/hi168-27201-2582wulz/2026/02/23/image.png" alt="在github创建js"></p><p><img src="https://s1.loveloli.me/hi168-27201-2582wulz/2026/02/23/imagebc3e0fa3f4a6bdc9.png" alt="编辑js文件"></p><details><summary>点击展开代码</summary><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></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> axios = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;axios&#x27;</span>);<br><span class="hljs-keyword">const</span> <span class="hljs-title class_">FormData</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;form-data&#x27;</span>);<br><span class="hljs-keyword">const</span> <span class="hljs-title class_">Busboy</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;busboy&#x27;</span>);<br><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = <span class="hljs-title function_">async</span> (req, res) =&gt; &#123;<br>  res.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">&#x27;Access-Control-Allow-Origin&#x27;</span>, <span class="hljs-string">&#x27;*&#x27;</span>);<br>  res.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">&#x27;Access-Control-Allow-Methods&#x27;</span>, <span class="hljs-string">&#x27;POST, OPTIONS&#x27;</span>);<br>  res.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">&#x27;Access-Control-Allow-Headers&#x27;</span>, <span class="hljs-string">&#x27;Content-Type&#x27;</span>);<br><br>  <span class="hljs-keyword">if</span> (req.<span class="hljs-property">method</span> === <span class="hljs-string">&#x27;OPTIONS&#x27;</span>) <span class="hljs-keyword">return</span> res.<span class="hljs-title function_">status</span>(<span class="hljs-number">200</span>).<span class="hljs-title function_">end</span>();<br>  <span class="hljs-keyword">if</span> (req.<span class="hljs-property">method</span> !== <span class="hljs-string">&#x27;POST&#x27;</span>) <span class="hljs-keyword">return</span> res.<span class="hljs-title function_">status</span>(<span class="hljs-number">405</span>).<span class="hljs-title function_">json</span>(&#123; <span class="hljs-attr">error</span>: <span class="hljs-string">&#x27;Method not allowed&#x27;</span> &#125;);<br><br>  <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">CHEVERETO_URL</span> = process.<span class="hljs-property">env</span>.<span class="hljs-property">CHEVERETO_URL</span>;<br>  <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">CHEVERETO_KEY</span> = process.<span class="hljs-property">env</span>.<span class="hljs-property">CHEVERETO_API_KEY</span>;<br><br>  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> &#123;<br>    <span class="hljs-keyword">const</span> busboy = <span class="hljs-title class_">Busboy</span>(&#123; <span class="hljs-attr">headers</span>: req.<span class="hljs-property">headers</span> &#125;);<br>    <span class="hljs-keyword">let</span> fileData = <span class="hljs-literal">null</span>;<br><br>    busboy.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;file&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">fieldname, file, info</span>) =&gt;</span> &#123;<br>      <span class="hljs-keyword">const</span> &#123; filename, mimeType &#125; = info;<br>      <span class="hljs-keyword">const</span> chunks = [];<br>      file.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;data&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">chunk</span>) =&gt;</span> chunks.<span class="hljs-title function_">push</span>(chunk));<br>      file.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;end&#x27;</span>, <span class="hljs-function">() =&gt;</span> &#123;<br>        fileData = &#123;<br>          <span class="hljs-attr">buffer</span>: <span class="hljs-title class_">Buffer</span>.<span class="hljs-title function_">concat</span>(chunks),<br>          <span class="hljs-attr">filename</span>: filename || <span class="hljs-string">&#x27;image.jpg&#x27;</span>,<br>          <span class="hljs-attr">mimeType</span>: mimeType || <span class="hljs-string">&#x27;image/jpeg&#x27;</span>,<br>        &#125;;<br>      &#125;);<br>    &#125;);<br><br>    busboy.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;finish&#x27;</span>, <span class="hljs-title function_">async</span> () =&gt; &#123;<br>      <span class="hljs-keyword">if</span> (!fileData) &#123;<br>        res.<span class="hljs-title function_">status</span>(<span class="hljs-number">400</span>).<span class="hljs-title function_">json</span>(&#123; <span class="hljs-attr">error</span>: <span class="hljs-string">&#x27;没有收到文件&#x27;</span> &#125;);<br>        <span class="hljs-keyword">return</span> <span class="hljs-title function_">resolve</span>();<br>      &#125;<br><br>      <span class="hljs-keyword">try</span> &#123;<br>        <span class="hljs-comment">// Chevereto V4 使用 multipart 直接传二进制</span><br>        <span class="hljs-keyword">const</span> form = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FormData</span>();<br>        form.<span class="hljs-title function_">append</span>(<span class="hljs-string">&#x27;source&#x27;</span>, fileData.<span class="hljs-property">buffer</span>, &#123;<br>          <span class="hljs-attr">filename</span>: fileData.<span class="hljs-property">filename</span>,<br>          <span class="hljs-attr">contentType</span>: fileData.<span class="hljs-property">mimeType</span>,<br>          <span class="hljs-attr">knownLength</span>: fileData.<span class="hljs-property">buffer</span>.<span class="hljs-property">length</span>,<br>        &#125;);<br>        form.<span class="hljs-title function_">append</span>(<span class="hljs-string">&#x27;format&#x27;</span>, <span class="hljs-string">&#x27;json&#x27;</span>);<br><br>        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.<span class="hljs-title function_">post</span>(<br>          <span class="hljs-string">`<span class="hljs-subst">$&#123;CHEVERETO_URL&#125;</span>/api/1/upload`</span>,<br>          form,<br>          &#123;<br>            <span class="hljs-attr">headers</span>: &#123;<br>              ...form.<span class="hljs-title function_">getHeaders</span>(),<br>              <span class="hljs-string">&#x27;X-API-Key&#x27;</span>: <span class="hljs-variable constant_">CHEVERETO_KEY</span>, <span class="hljs-comment">// V4 用 Header 认证</span><br>            &#125;,<br>            <span class="hljs-attr">timeout</span>: <span class="hljs-number">20000</span>,<br>            <span class="hljs-attr">maxContentLength</span>: <span class="hljs-title class_">Infinity</span>,<br>            <span class="hljs-attr">maxBodyLength</span>: <span class="hljs-title class_">Infinity</span>,<br>          &#125;<br>        );<br><br>        <span class="hljs-keyword">const</span> imageUrl = response.<span class="hljs-property">data</span>?.<span class="hljs-property">image</span>?.<span class="hljs-property">url</span>;<br>        <span class="hljs-keyword">if</span> (!imageUrl) &#123;<br>          res.<span class="hljs-title function_">status</span>(<span class="hljs-number">500</span>).<span class="hljs-title function_">json</span>(&#123; <span class="hljs-attr">error</span>: <span class="hljs-string">&#x27;未返回图片URL&#x27;</span>, <span class="hljs-attr">detail</span>: response.<span class="hljs-property">data</span> &#125;);<br>          <span class="hljs-keyword">return</span> <span class="hljs-title function_">resolve</span>();<br>        &#125;<br><br>        res.<span class="hljs-title function_">status</span>(<span class="hljs-number">200</span>).<span class="hljs-title function_">json</span>(&#123; <span class="hljs-attr">url</span>: imageUrl &#125;);<br>        <span class="hljs-title function_">resolve</span>();<br>      &#125; <span class="hljs-keyword">catch</span> (err) &#123;<br>        <span class="hljs-keyword">if</span> (err.<span class="hljs-property">response</span>) &#123;<br>          res.<span class="hljs-title function_">status</span>(<span class="hljs-number">500</span>).<span class="hljs-title function_">json</span>(&#123;<br>            <span class="hljs-attr">error</span>: err.<span class="hljs-property">message</span>,<br>            <span class="hljs-attr">chevereto_status</span>: err.<span class="hljs-property">response</span>.<span class="hljs-property">status</span>,<br>            <span class="hljs-attr">chevereto_detail</span>: err.<span class="hljs-property">response</span>.<span class="hljs-property">data</span>,<br>          &#125;);<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>          res.<span class="hljs-title function_">status</span>(<span class="hljs-number">500</span>).<span class="hljs-title function_">json</span>(&#123; <span class="hljs-attr">error</span>: err.<span class="hljs-property">message</span> &#125;);<br>        &#125;<br>        <span class="hljs-title function_">resolve</span>();<br>      &#125;<br>    &#125;);<br><br>    busboy.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;error&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> &#123;<br>      res.<span class="hljs-title function_">status</span>(<span class="hljs-number">500</span>).<span class="hljs-title function_">json</span>(&#123; <span class="hljs-attr">error</span>: <span class="hljs-string">&#x27;Busboy错误: &#x27;</span> + err.<span class="hljs-property">message</span> &#125;);<br>      <span class="hljs-title function_">resolve</span>();<br>    &#125;);<br><br>    req.<span class="hljs-title function_">pipe</span>(busboy);<br>  &#125;);<br>&#125;;<br></code></pre></td></tr></table></figure></details><h3 id="添加依赖"><a href="#添加依赖" class="headerlink" title="添加依赖"></a>添加依赖</h3><p>确认 <code>package.json</code> 中包含以下依赖：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><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><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;dependencies&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;twikoo-vercel&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;latest&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;axios&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;^1.6.0&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;busboy&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;^1.6.0&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;form-data&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;^4.0.0&quot;</span><br>  <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure><h3 id="配置-Vercel-环境变量"><a href="#配置-Vercel-环境变量" class="headerlink" title="配置 Vercel 环境变量"></a>配置 Vercel 环境变量</h3><p>在 Vercel → 你的项目 → Settings → Environment Variables 中添加：</p><table><thead><tr><th>变量名</th><th>值</th></tr></thead><tbody><tr><td><code>CHEVERETO_URL</code></td><td><code>https://你的图床域名</code>（不带末尾斜杠）</td></tr><tr><td><code>CHEVERETO_API_KEY</code></td><td>你的 Chevereto V4 API Key</td></tr></tbody></table><blockquote><p>⚠️ <strong>注意</strong>：不要设置 <code>IMAGE_CDN</code>、<code>IMAGE_CDN_URL</code>、<code>IMAGE_CDN_TOKEN</code> 这三个环境变量，否则 Twikoo 会启用内置图床逻辑并报错。</p></blockquote><h3 id="获取-Chevereto-V4-API-Key"><a href="#获取-Chevereto-V4-API-Key" class="headerlink" title="获取 Chevereto V4 API Key"></a>获取 Chevereto V4 API Key</h3><p>登录 Chevereto 后台 → Dashboard → Settings → API，确认 API 已启用，复制 API V1 Key。</p><hr><h2 id="第二步：Hook-前端-Vue-组件"><a href="#第二步：Hook-前端-Vue-组件" class="headerlink" title="第二步：Hook 前端 Vue 组件"></a>第二步：Hook 前端 Vue 组件</h2><h3 id="为什么不能用普通-DOM-事件拦截"><a href="#为什么不能用普通-DOM-事件拦截" class="headerlink" title="为什么不能用普通 DOM 事件拦截"></a>为什么不能用普通 DOM 事件拦截</h3><p>Twikoo 的上传按钮是 Vue 组件渲染的，使用 <code>on:{change:e.onSelectImage}</code> 绑定事件。即使用 <code>cloneNode</code> 替换元素，Vue 仍会重新绑定事件。必须直接覆盖 Vue 实例上的 <code>onSelectImage</code> 方法。</p><h3 id="创建注入脚本"><a href="#创建注入脚本" class="headerlink" title="创建注入脚本"></a>创建注入脚本</h3><p>在 Hexo 博客根目录的 <code>scripts/</code> 文件夹下创建 <code>inject-twikoo.js</code>：</p><details><summary>点击展开代码</summary><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></pre></td><td class="code"><pre><code class="hljs javascript">hexo.<span class="hljs-property">extend</span>.<span class="hljs-property">injector</span>.<span class="hljs-title function_">register</span>(<span class="hljs-string">&#x27;body_end&#x27;</span>, <span class="hljs-string">`</span><br><span class="hljs-string">&lt;script&gt;</span><br><span class="hljs-string">(function() &#123;</span><br><span class="hljs-string">  var UPLOAD_API = &#x27;https://你的twikoo.vercel.app/api/upload&#x27;;</span><br><span class="hljs-string"></span><br><span class="hljs-string">  function hookVueComponent() &#123;</span><br><span class="hljs-string">    var input = document.querySelector(&#x27;input.tk-input-image&#x27;);</span><br><span class="hljs-string">    if (!input) &#123;</span><br><span class="hljs-string">      setTimeout(hookVueComponent, 500);</span><br><span class="hljs-string">      return;</span><br><span class="hljs-string">    &#125;</span><br><span class="hljs-string"></span><br><span class="hljs-string">    // 向上遍历父元素，找到有 onSelectImage 方法的 Vue 实例</span><br><span class="hljs-string">    var el = input;</span><br><span class="hljs-string">    while (el) &#123;</span><br><span class="hljs-string">      var vue = el.__vue__;</span><br><span class="hljs-string">      if (vue &amp;&amp; typeof vue.onSelectImage === &#x27;function&#x27;) &#123;</span><br><span class="hljs-string">        console.log(&#x27;找到 Vue 实例，准备 hook onSelectImage&#x27;);</span><br><span class="hljs-string"></span><br><span class="hljs-string">        vue.onSelectImage = async function(e) &#123;</span><br><span class="hljs-string">          var file = e.target.files[0];</span><br><span class="hljs-string">          if (!file) return;</span><br><span class="hljs-string"></span><br><span class="hljs-string">          try &#123;</span><br><span class="hljs-string">            var fd = new FormData();</span><br><span class="hljs-string">            fd.append(&#x27;file&#x27;, file);</span><br><span class="hljs-string">            var res = await fetch(UPLOAD_API, &#123; method: &#x27;POST&#x27;, body: fd &#125;);</span><br><span class="hljs-string">            var data = await res.json();</span><br><span class="hljs-string">            if (!data.url) throw new Error(data.error || &#x27;未返回URL&#x27;);</span><br><span class="hljs-string"></span><br><span class="hljs-string">            // 将图片 Markdown 插入评论框</span><br><span class="hljs-string">            var textarea = document.querySelector(&#x27;.tk-input .el-textarea__inner&#x27;)</span><br><span class="hljs-string">                        || document.querySelector(&#x27;.tk-input textarea&#x27;);</span><br><span class="hljs-string">            if (textarea) &#123;</span><br><span class="hljs-string">              var pos = textarea.selectionStart !== undefined</span><br><span class="hljs-string">                ? textarea.selectionStart</span><br><span class="hljs-string">                : textarea.value.length;</span><br><span class="hljs-string">              var imgMd = &#x27;![](&#x27; + data.url + &#x27;)&#x27;;</span><br><span class="hljs-string">              var val = textarea.value;</span><br><span class="hljs-string">              textarea.value = val.slice(0, pos) + imgMd + val.slice(pos);</span><br><span class="hljs-string">              textarea.dispatchEvent(new Event(&#x27;input&#x27;, &#123; bubbles: true &#125;));</span><br><span class="hljs-string">            &#125;</span><br><span class="hljs-string">            console.log(&#x27;图片上传成功:&#x27;, data.url);</span><br><span class="hljs-string">          &#125; catch(err) &#123;</span><br><span class="hljs-string">            console.error(&#x27;上传失败:&#x27;, err);</span><br><span class="hljs-string">            alert(&#x27;图片上传失败: &#x27; + err.message);</span><br><span class="hljs-string">          &#125;</span><br><span class="hljs-string"></span><br><span class="hljs-string">          e.target.value = &#x27;&#x27;;</span><br><span class="hljs-string">        &#125;;</span><br><span class="hljs-string"></span><br><span class="hljs-string">        console.log(&#x27;Twikoo Vue onSelectImage 已接管&#x27;);</span><br><span class="hljs-string">        return;</span><br><span class="hljs-string">      &#125;</span><br><span class="hljs-string">      el = el.parentElement;</span><br><span class="hljs-string">    &#125;</span><br><span class="hljs-string"></span><br><span class="hljs-string">    setTimeout(hookVueComponent, 500);</span><br><span class="hljs-string">  &#125;</span><br><span class="hljs-string"></span><br><span class="hljs-string">  // 等待评论区 DOM 出现后再 hook</span><br><span class="hljs-string">  var observer = new MutationObserver(function() &#123;</span><br><span class="hljs-string">    if (document.querySelector(&#x27;input.tk-input-image&#x27;)) &#123;</span><br><span class="hljs-string">      observer.disconnect();</span><br><span class="hljs-string">      setTimeout(hookVueComponent, 300);</span><br><span class="hljs-string">    &#125;</span><br><span class="hljs-string">  &#125;);</span><br><span class="hljs-string">  observer.observe(document.body, &#123; childList: true, subtree: true &#125;);</span><br><span class="hljs-string">&#125;)();</span><br><span class="hljs-string">&lt;/script&gt;</span><br><span class="hljs-string">`</span>, <span class="hljs-string">&#x27;default&#x27;</span>);<br></code></pre></td></tr></table></figure></details><p><strong>注意</strong>：将 <code>https://你的twikoo.vercel.app/api/upload</code> 替换为你的 Vercel 域名。</p><h2 id="第三步：部署"><a href="#第三步：部署" class="headerlink" title="第三步：部署"></a>第三步：部署</h2><p>这就不用我废话了吧，祝你成功！</p><h2 id="我踩的坑"><a href="#我踩的坑" class="headerlink" title="我踩的坑"></a>我踩的坑</h2><p><strong>坑1：Chevereto V4 认证方式变了</strong><br>V3 用表单字段 <code>key</code> 认证，V4 改为 HTTP Header <code>X-API-Key</code>，混用会返回 400。</p><p><strong>坑2：base64 传输会损坏</strong><br>用 <code>URLSearchParams</code> 传 base64 Data URL 时，<code>+</code> 和 <code>/</code> 字符被 URL 编码破坏，导致 Chevereto 报 <code>Invalid base64 string</code>。应直接用 multipart 传二进制。</p><p><strong>坑3：Twikoo 内置图床环境变量干扰</strong><br>设置了 <code>IMAGE_CDN=lskypro</code> 等变量后，Twikoo 后端会用内置逻辑处理上传，完全绕过自定义代理，且会把 <code>IMAGE_CDN_URL</code> 的值当成 Bearer Token 发出去。。</p><p><strong>坑4：cloneNode 无法移除 Vue 事件</strong><br>Twikoo 使用 Vue 绑定 <code>change</code> 事件，<code>cloneNode</code> 替换元素后 Vue 会重新渲染并重新绑定，必须直接覆盖 Vue 实例的 <code>onSelectImage</code> 方法。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Hexo Fluid 中 Twikoo 部署与 Cloudflare IP 修正</title>
      <link>http://www.linzekai.cn/posts/7c8b5791/</link>
      <description>记录在 Fluid 主题中部署 Twikoo 时的两个关键配置：前端资源镜像切换，以及在 Cloudflare 代理下正确获取访客真实 IP。</description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/Fluid/">Fluid</category>
      <category domain="http://www.linzekai.cn/tags/Twikoo/">Twikoo</category>
      <pubDate>Fri, 20 Feb 2026 16:02:28 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>Fluid 默认集成了 Twikoo，但版本略微落后最新版。</p><p>这篇记录两个坑：</p><ol><li><p><strong>手动指定 Twikoo 前端资源地址</strong></p></li><li><p><strong>在 Cloudflare 代理下正确获取访客真实 IP</strong></p></li></ol><h2 id="一、更新-Fluid-中的-Twikoo-资源链接"><a href="#一、更新-Fluid-中的-Twikoo-资源链接" class="headerlink" title="一、更新 Fluid 中的 Twikoo 资源链接"></a>一、更新 Fluid 中的 Twikoo 资源链接</h2><p>由于网络环境原因，直接使用官方 CDN 可能会出现加载缓慢或失败的情况。<br>这里选择使用 <strong>npmmirror 镜像</strong>，手动指定 Twikoo 的前端资源路径。</p><p>只需要在<code>_config.fluid.yml</code>中修改对应字段即可。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">twikoo:</span> <span class="hljs-string">https://registry.npmmirror.com/twikoo/1.6.44/files/dist/twikoo.all.min.js</span><br></code></pre></td></tr></table></figure><h2 id="二、Cloudflare-下获取真实访客-IP"><a href="#二、Cloudflare-下获取真实访客-IP" class="headerlink" title="二、Cloudflare 下获取真实访客 IP"></a>二、Cloudflare 下获取真实访客 IP</h2><p>当 Twikoo 使用了 Cloudflare cdn 之后，服务端默认只能拿到 Cloudflare 的代理 IP，而不是真实访客地址。</p><p>Twikoo 提供了 <code>TWIKOO_IP_HEADERS</code> 环境变量，用来显式指定可信请求头。</p><p>在 Cloudflare 环境下，应使用 <code>[&quot;headers.cf-connecting-ip&quot;]</code>。<br><strong>注意：必须带 <code>[&quot;&quot;]</code>, 然后重新deploy该函数。</strong></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>写作中，变得多余的福瑞设定</title>
      <link>http://www.linzekai.cn/posts/d235e19c/</link>
      <description>写在正式动笔前的一点自省：为什么有些福瑞设定看起来成立，却在叙事中慢慢变得多余。</description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E9%9A%8F%E7%AC%94/">随笔</category>
      <category domain="http://www.linzekai.cn/tags/%E7%A6%8F%E7%91%9E/">福瑞</category>
      <category domain="http://www.linzekai.cn/tags/%E5%86%99%E4%BD%9C/">写作</category>
      <pubDate>Thu, 19 Feb 2026 06:46:14 GMT</pubDate>
      <content:encoded>
        <![CDATA[<div class="note note-info">            <p>这篇思考，源于和<a href="https://kiream.xyz/">lxxxzl</a>的一次探讨。</p>          </div><p>我不是一个小说作者。至少现在还不是。</p><p>这些话写在正式动笔之前，写给未来那个终于开始写第一个故事、第一段情节、第一个角色的自己。</p><p>提醒他有些坑，别再掉进去了。</p><h2 id="存在，却没有被用到的设定"><a href="#存在，却没有被用到的设定" class="headerlink" title="存在，却没有被用到的设定"></a>存在，却没有被用到的设定</h2><p>读别人作品时，我遇到过一种挺微妙的情况：</p><p>福瑞设定没有出错——没有OOC，没有逻辑漏洞，没有让人出戏的硬伤。角色成立，情绪成立，故事也能顺利推进。</p><p>但我就是觉得不对劲。</p><p>不是违和，也不是失败，而是一种更难说清的感觉：这个设定，<strong>好像只是“在”，而不是“被用到”。</strong></p><p>它没碍事，但也没真正做事。</p><p>如果一个角色在关键时刻的选择与物种无关；<br>如果冲突的形成、情绪的积累，在拿掉物种设定后依然完整——<br>那么这个设定就在叙事中可有可无。它仍然存在，却不再影响结构，只是徒有其表。</p><h2 id="《疯狂动物城1》为什么成立"><a href="#《疯狂动物城1》为什么成立" class="headerlink" title="《疯狂动物城1》为什么成立"></a>《疯狂动物城1》为什么成立</h2><p>说到这里，我想起一个把福瑞设定用好了的例子。</p><p>《疯狂动物城》里，朱迪只乡下兔子，尼克是一只靠骗术维生的城市狐狸。如果把他们替换成人类——一个乡下女孩和一个城市骗子——故事还能成立吗？</p><p>能，但会是完全不同的故事。</p><p>因为朱迪的兔子身份不只是外观：</p><ul><li>她体型小，所以在警局被同事看不起——这是生理差异直接造成的冲突</li><li>大家都觉得“兔子就该胆小”，可她偏想当警察——这种反差让打破标签变成了角色自己的事</li><li>她最后抓到罪犯，靠的就是“体型小、跑得快”——这不是“人类角色碰巧长了兔子耳朵”，是只有兔子才能做到的事</li></ul><p>尼克的狐狸身份也一样：</p><ul><li>他从小因为物种被欺负，这是<strong>创伤的来源</strong></li><li>他选择做骗子，某种程度上是“既然你们都觉得狐狸狡猾，那我就狡猾给你们看”——这是<strong>物种标签扭曲了身份认同</strong></li><li>朱迪一开始对他有戒备，后来才意识到那是偏见，这偏见<strong>必须建立在“狐狸&#x3D;狡猾”的社会共识上</strong></li></ul><p>这就是“被用上”的样子，设定成了故事的一部分，而不是贴在表面的装饰。</p><h2 id="三条写作层面的自我要求"><a href="#三条写作层面的自我要求" class="headerlink" title="三条写作层面的自我要求"></a>三条写作层面的自我要求</h2><p>意识到这点后，我开始在构思中对自己提出一些要求，留给未来的自己。</p><h3 id="1-角色层面：追问“非他不可”的理由"><a href="#1-角色层面：追问“非他不可”的理由" class="headerlink" title="1. 角色层面：追问“非他不可”的理由"></a>1. 角色层面：追问“非他不可”的理由</h3><p>刻意回避那种只停留在性格修辞上的动物性描写，可以时常问问自己：</p><blockquote><p>如果他不是这个物种，这个判断还会发生吗？</p></blockquote><p>如果答案是肯定的，那这段情节其实不怎么需要这个设定。</p><h3 id="2-冲突层面：检验物种是否参与矛盾"><a href="#2-冲突层面：检验物种是否参与矛盾" class="headerlink" title="2. 冲突层面：检验物种是否参与矛盾"></a>2. 冲突层面：检验物种是否参与矛盾</h3><p>如果一个冲突，把物种差异拿掉之后照样能成立，只是恰好发生在长着动物外形的角色身上，那么福瑞设定在这里只是装饰。</p><p>反过来，只要有一部分冲突必须靠生理差异、族群关系、或者由这些衍生出来的社会结构才能成立，就足以让设定真正进入叙事。</p><h3 id="3-世界观层面：寻找不可替换的维度"><a href="#3-世界观层面：寻找不可替换的维度" class="headerlink" title="3. 世界观层面：寻找不可替换的维度"></a>3. 世界观层面：寻找不可替换的维度</h3><p>不要求世界观足够复杂，而是要求它在<strong>某一个维度上的不可替换</strong>。</p><p>如果一个社会在运行方式上与现实几乎一致，那么即使居民是福瑞，叙事也不会因此获得新可能。设定不需要全面重构，但至少要在某个节点上迫使故事改变走向。</p><hr><h2 id="实用的自检方法"><a href="#实用的自检方法" class="headerlink" title="实用的自检方法"></a>实用的自检方法</h2><p>写完一段情节，尝试把角色和世界观整体替换成人类版本。</p><ul><li>如果这一版本在情绪强度和逻辑自洽上<strong>几乎没有损失</strong>——那么原本的福瑞设定很可能并未被真正使用。</li><li>反之，如果替换后出现<strong>明显不适、断裂或需要做出额外解释</strong>——说明它已介入叙事。</li></ul><blockquote><p>用《疯狂动物城》测试：把朱迪和尼克换成人类女孩和人类骗子——整个关于偏见、刻板印象、体型差异的叙事都会崩塌。这就是设定被用到的证据。</p></blockquote><p>这套判断方式不能保证作品更好，但它至少能帮我分清：<strong>什么时候福瑞只是存在，什么时候它仍在发挥作用。</strong></p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>这些话，写给未来的自己。</p><blockquote><p>与其反复意淫福瑞元素在文中的出现，我更希望你在每一次落笔时记得问自己：<strong>这一段，我到底有没有用到它？</strong></p><p>有些设定之所以显得多余，不是因为它们不好，<br>而是因为你还没找到<strong>非它不可的写法</strong>。</p></blockquote>]]>
      </content:encoded>
    </item>
    <item>
      <title>Hexo Fluid 实现文章过期提示（非侵入式方案）</title>
      <link>http://www.linzekai.cn/posts/1b963265/</link>
      <description>记录一种基于 Hexo + Fluid 的文章过期提示实现方案，通过主题注入机制在不修改主题源码的前提下，按单篇文章自动计算发布时间差并显示过期提醒，升级安全且易于维护。</description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/Fluid/">Fluid</category>
      <pubDate>Tue, 17 Feb 2026 10:20:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>在维护博客时，经常会遇到一个问题：<strong>一些早期文章在搜索引擎或首页依然能被访问，但其中的内容已经不完全适用于当前环境。</strong></p><p>于是决定给这些文章一个 <strong>「过期提示」</strong></p><p>本文记录一种 <strong>完全非侵入式</strong> 的实现方案</p><h2 id="一、实现效果"><a href="#一、实现效果" class="headerlink" title="一、实现效果"></a>一、实现效果</h2><p>当文章满足条件时，在正文顶部显示提示：</p>  <div class="post-expired-warning">    这是一篇发布于    <strong>x 年 x 天</strong>    前的文章，部分信息可能已发生改变，请注意甄别。  </div><p>特性包括：</p><ul><li>不到 1 年显示：<code>X 天</code>, 超过 1 年显示：<code>X 年 X 天</code></li><li>可手动或按日期自动触发</li><li>不影响 Fluid 升级  </li><li>单篇文章控制</li></ul><h2 id="二、方案说明"><a href="#二、方案说明" class="headerlink" title="二、方案说明"></a>二、方案说明</h2><p>Fluid 提供了官方的 <strong>主题注入（theme_inject）机制</strong>，允许在不修改主题文件的前提下，将自定义内容插入到指定位置。</p><p>整体思路如下：</p><ol><li>使用 <code>scripts/</code> 注册注入位置  </li><li>将过期提示写成独立的 EJS 模板  </li><li>从文章 front-matter 中读取 <code>date / expired / expire_date</code>  </li><li>构建时自动计算并渲染</li></ol><p>整个过程 <strong>不接触 <code>themes/fluid</code> 目录</strong>，升级安全。</p><h2 id="三、文章-Front-matter-用法"><a href="#三、文章-Front-matter-用法" class="headerlink" title="三、文章 Front-matter 用法"></a>三、文章 Front-matter 用法</h2><p>在需要控制的文章中添加字段：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs text">---<br>title: 示例文章<br>date: 2023-02-10 12:28:33<br>expired: true (可选，默认为false)<br>expire_date: 2024-01-01 (可选)<br>---<br></code></pre></td></tr></table></figure><h3 id="字段说明"><a href="#字段说明" class="headerlink" title="字段说明"></a>字段说明</h3><ul><li><code>date</code>:文章发布时间（Hexo 默认字段），用于计算“距今多久”。</li><li><code>expired: true</code>:强制显示过期提示，不受日期影响。</li><li><code>expire_date</code>:指定一个过期时间，当当前时间晚于该日期时自动显示提示。</li></ul><h4 id="使用策略示例"><a href="#使用策略示例" class="headerlink" title="使用策略示例"></a>使用策略示例</h4><table><thead><tr><th>写法</th><th>行为</th></tr></thead><tbody><tr><td>什么都不写</td><td>永不显示</td></tr><tr><td><code>expired: true</code></td><td>强制显示</td></tr><tr><td>仅写 <code>expire_date</code></td><td>到期后显示</td></tr></tbody></table><h2 id="四、实现"><a href="#四、实现" class="headerlink" title="四、实现"></a>四、实现</h2><p>在根目录下，新建<code>scripts</code>目录（如果尚不存在）。</p><p>在该目录中创建一个用于注册注入的脚本文件<code>inject-expired.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></pre></td><td class="code"><pre><code class="hljs js">hexo.<span class="hljs-property">extend</span>.<span class="hljs-property">filter</span>.<span class="hljs-title function_">register</span>(<span class="hljs-string">&#x27;theme_inject&#x27;</span>, <span class="hljs-function"><span class="hljs-params">injects</span> =&gt;</span> &#123;<br>  injects.<span class="hljs-property">postMarkdownBegin</span>.<span class="hljs-title function_">file</span>(<br>    <span class="hljs-string">&#x27;expired-warning&#x27;</span>,<br>    <span class="hljs-string">&#x27;source/_inject/expired-warning.ejs&#x27;</span><br>  );<br>&#125;);<br></code></pre></td></tr></table></figure><p>真正显示提示的内容放在一个独立的 EJS 模板中，位于<code>source/_inject</code>目录。</p><p>新建文件<code>expired-warning.ejs</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><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></pre></td><td class="code"><pre><code class="hljs ejs">&lt;%<br>  // 当前时间<br>  const now = new Date();<br><br>  // 文章发布时间（来自 front-matter 的 date）<br>  const postDate = new Date(page.date);<br><br>  // 相差毫秒<br>  const diffTime = now - postDate;<br><br>  // 相差天数<br>  const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));<br><br>  // 年 / 天拆分<br>  const years = Math.floor(diffDays / 365);<br>  const days = diffDays % 365;<br><br>  // 显示用文本<br>  let ageText = &#x27;&#x27;;<br>  if (years &gt; 0) &#123;<br>    ageText = `$&#123;years&#125; 年 $&#123;days&#125; 天`;<br>  &#125; else &#123;<br>    ageText = `$&#123;diffDays&#125; 天`;<br>  &#125;<br><br>  // 是否显示过期提示<br>  const expireDate = page.expire_date ? new Date(page.expire_date) : null;<br>  const showExpired =<br>    diffDays &gt; 0 &amp;&amp;<br>    (page.expired || (expireDate &amp;&amp; now &gt; expireDate));<br>%&gt;<br><br>&lt;% if (showExpired) &#123; %&gt;<br>  &lt;div class=&quot;post-expired-warning&quot;&gt;<br>    这是一篇发布于<br>    &lt;strong&gt;&lt;%= ageText %&gt;&lt;/strong&gt;<br>    前的文章，部分信息可能已发生改变，请注意甄别。<br>  &lt;/div&gt;<br>&lt;% &#125; %&gt;<br></code></pre></td></tr></table></figure><p>这个模板主要做了几件事：</p><ul><li>从 page.date 读取文章发布时间  </li><li>获取当前构建时间  </li><li>计算两者之间相差的天数  </li><li>将天数拆分为「年 + 天」的形式  </li><li>根据 expired 或 expire_date 判断是否需要显示</li></ul><p>当文章发布时间不足一天时，不显示提示，避免出现「0 天前」这种无意义信息。</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Hexo Fluid 实现日夜模式 Banner 图片切换</title>
      <link>http://www.linzekai.cn/posts/5665d9c4/</link>
      <description>记录在 Hexo Fluid 主题中实现日夜模式 Banner 图片切换的实践过程，解决了首页默认被排除及遮罩处理粗糙的问题，通过 JavaScript 改造实现统一生效且更自然的视觉效果。</description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/Fluid/">Fluid</category>
      <category domain="http://www.linzekai.cn/tags/%E6%97%A5%E5%A4%9C%E6%A8%A1%E5%BC%8F/">日夜模式</category>
      <pubDate>Mon, 16 Feb 2026 08:06:43 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>在使用 Hexo 的 Fluid 主题时，我参考了<a href="https://4rozen.github.io/posts/60191.html">这篇文章</a>来实现<strong>日夜模式切换 Banner 图片</strong></p><p>原方案思路是对的，也能跑通，但在实际使用中我遇到了两个<strong>明显痛点</strong>：</p><ol><li><strong>首页默认被排除，无法切换 Banner 图片</strong></li><li><strong>直接删除遮罩（mask）后，视觉效果很丑</strong></li></ol><p>本文记录我针对这两个问题的解决方案，供同样使用 Fluid 主题的朋友参考。</p><h2 id="一、原方案的问题分析"><a href="#一、原方案的问题分析" class="headerlink" title="一、原方案的问题分析"></a>一、原方案的问题分析</h2><h3 id="问题-1：首页不支持切换-Banner"><a href="#问题-1：首页不支持切换-Banner" class="headerlink" title="问题 1：首页不支持切换 Banner"></a>问题 1：首页不支持切换 Banner</h3><p>原文中通过一个 <code>isExcludedPage</code> 方法来判断是否启用日夜切换逻辑</p><p>而在默认逻辑里，<strong>首页 <code>/</code>是被排除的</strong>，也就是说首页不执行切换</p><p>这对我来说是不可接受的，因为首页 Banner 恰恰是最需要日夜区分的地方。</p><h3 id="问题-2：直接移除遮罩，画面观感很差"><a href="#问题-2：直接移除遮罩，画面观感很差" class="headerlink" title="问题 2：直接移除遮罩，画面观感很差"></a>问题 2：直接移除遮罩，画面观感很差</h3><p>原方案中对 Banner 遮罩的处理方式是直接将遮罩透明化</p><p>这样做的结果是：</p><ul><li><p>图片亮度失控</p></li><li><p>字体对比度不足</p></li><li><p>页面“素”得很明显</p></li></ul><p><strong>遮罩不该被移除，而应该被“设计”</strong></p><h2 id="二、问题一的解决：让首页参与日夜切换"><a href="#二、问题一的解决：让首页参与日夜切换" class="headerlink" title="二、问题一的解决：让首页参与日夜切换"></a>二、问题一的解决：让首页参与日夜切换</h2><p>对<code>backgroundize.js</code>的<code>isExcludedPage</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></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">const</span> <span class="hljs-title function_">isExcludedPage</span> = (<span class="hljs-params">path</span>) =&gt; &#123;<br>  <span class="hljs-keyword">if</span> (path === <span class="hljs-string">&quot;/&quot;</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; <span class="hljs-comment">// true改为false启用首页切换</span><br>  <span class="hljs-keyword">return</span> <span class="hljs-variable constant_">PAGE_EXCLUSIONS</span>.<span class="hljs-title function_">some</span>(<span class="hljs-function">(<span class="hljs-params">excluded</span>) =&gt;</span> path.<span class="hljs-title function_">startsWith</span>(excluded));<br>&#125;;<br></code></pre></td></tr></table></figure><h3 id="修改效果"><a href="#修改效果" class="headerlink" title="修改效果"></a>修改效果</h3><table><thead><tr><th>页面</th><th>是否参与日夜切换</th></tr></thead><tbody><tr><td>首页</td><td>✅</td></tr><tr><td>文章页</td><td>✅</td></tr><tr><td>排除页</td><td>❌</td></tr></tbody></table><h2 id="三、问题二的解决：用渐变遮罩代替“删除遮罩”"><a href="#三、问题二的解决：用渐变遮罩代替“删除遮罩”" class="headerlink" title="三、问题二的解决：用渐变遮罩代替“删除遮罩”"></a>三、问题二的解决：用渐变遮罩代替“删除遮罩”</h2><p>相比 CSS 覆盖，我选择了 直接用 <code>JavaScript</code> 接管遮罩层样式，这是目前在 Fluid 中最稳定的方案。</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><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><code class="hljs js"><span class="hljs-keyword">const</span> <span class="hljs-title function_">removeBannerMask</span> = (<span class="hljs-params"></span>) =&gt; &#123;<br>  <span class="hljs-keyword">const</span> mask = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">&quot;#banner .mask&quot;</span>);<br>  <span class="hljs-keyword">if</span> (!mask) <span class="hljs-keyword">return</span>;<br><br>  mask.<span class="hljs-property">style</span>.<span class="hljs-property">background</span> = <span class="hljs-string">`</span><br><span class="hljs-string">    linear-gradient(</span><br><span class="hljs-string">      to bottom,</span><br><span class="hljs-string">      rgba(0, 0, 0, 0.6) 0%,</span><br><span class="hljs-string">      rgba(0, 0, 0, 0.35) 40%,</span><br><span class="hljs-string">      rgba(0, 0, 0, 0.15) 70%,</span><br><span class="hljs-string">      rgba(0, 0, 0, 0) 100%</span><br><span class="hljs-string">    )</span><br><span class="hljs-string">  `</span>;<br>&#125;;<br></code></pre></td></tr></table></figure>]]>
      </content:encoded>
    </item>
    <item>
      <title>Hexo Fluid 一言中添加作者</title>
      <link>http://www.linzekai.cn/posts/f88aa2a0/</link>
      <description>记录一次对 Hexo Fluid 主题首页“一言”打字机效果的修改实践，通过调整 typed.ejs 模板为一言内容补充作者与出处，并处理作者为空时显示为 null 的问题，使首页展示更加完整和美观。</description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/Fluid/">Fluid</category>
      <pubDate>Sun, 12 Feb 2023 07:12:30 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>目前，fluid主题的一言还不支持默认添加作者，所以我们需要修改首页打字机的代码。</p><p>1.打开<strong>主题</strong>根目录下的<code>layout\_partial\plugins</code>文件夹，修改其中的<code>typed.ejs</code>文件</p><p>2.找到以下语句</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js">apiText ? <span class="hljs-title function_">typing</span>(apiText) : <span class="hljs-title function_">typing</span>(text);<br></code></pre></td></tr></table></figure><p>加入出处可在<code>typing(apiText)</code>中加入相应代码，示例：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js">apiText ? <span class="hljs-title function_">typing</span>(<span class="hljs-string">&#x27;『&#x27;</span>+apiText+<span class="hljs-string">&#x27;』&#x27;</span>+ <span class="hljs-string">&#x27;&lt;br /&gt; &lt;h4&gt;&#x27;</span>+ <span class="hljs-string">&#x27;--&#x27;</span> +result[<span class="hljs-string">&#x27;from_who&#x27;</span>]+<span class="hljs-string">&#x27;「&#x27;</span>+result[<span class="hljs-string">&#x27;from&#x27;</span>]+<span class="hljs-string">&#x27;」&#x27;</span>+<span class="hljs-string">&#x27;&lt;/h4&gt;&#x27;</span>) : <span class="hljs-title function_">typing</span>(text);<br></code></pre></td></tr></table></figure><p>显示效果：</p><blockquote><p>『猫是可爱的，狼是很帅的。就是说，孤独又可爱又帅。』<br>–比企谷八幡「我的青春恋爱物语果然有问题」</p></blockquote><p>3.有一些一言并没有设置作者，此时typing会出现这样的情况</p><blockquote><p>『不要在晚上做出任何决定。』<br>–null「互联网」</p></blockquote><p>强迫症落泪。不过还是有解决办法的，我们可以在他的上方添加一个判断，如果<code>result[&#39;from_who&#39;]</code>的值为<code>null</code>，那么替换为空字符。</p><p>在步骤二修改的语句上方添加：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">if</span>(result[<span class="hljs-string">&#x27;from_who&#x27;</span>]===<span class="hljs-literal">null</span>) result[<span class="hljs-string">&#x27;from_who&#x27;</span>]=<span class="hljs-string">&#x27;&#x27;</span>;<br></code></pre></td></tr></table></figure><p>显示效果：</p><blockquote><p>『不要在晚上做出任何决定。』<br>–「互联网」</p></blockquote>]]>
      </content:encoded>
    </item>
    <item>
      <title>希沃冰点还原忘记密码的解决方案</title>
      <link>http://www.linzekai.cn/posts/786d78c9/</link>
      <description>
        <![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>学校电脑教室使用的WPS经常弹出升级弹窗，影响正常教学，因此决定改用微软Office。但负责老师不愿告知电教设备的还原卡密码,于是自己动手那]]>
      </description>
      <author>林泽凯</author>
      <category domain="http://www.linzekai.cn/tags/%E6%95%99%E7%A8%8B/">教程</category>
      <category domain="http://www.linzekai.cn/tags/%E5%B8%8C%E6%B2%83/">希沃</category>
      <category domain="http://www.linzekai.cn/tags/%E5%86%B0%E7%82%B9%E8%BF%98%E5%8E%9F/">冰点还原</category>
      <pubDate>Fri, 10 Feb 2023 04:28:33 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>学校电脑教室使用的WPS经常弹出升级弹窗，影响正常教学，因此决定改用微软Office。但负责老师不愿告知电教设备的还原卡密码,于是自己动手那个丰衣足食。</p><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><h3 id="第一步：降级希沃管家"><a href="#第一步：降级希沃管家" class="headerlink" title="第一步：降级希沃管家"></a>第一步：降级希沃管家</h3><p>新版希沃管家的加密方式有所改变，需要先降级到旧版本：</p><p><strong>下载链接：</strong> <a href="https://appdown.naierchina.com/appfile1/appfileup01/file2/20200819/SeewoServiceSetup_1.1.9.2219.exe">希沃管家旧版安装包</a></p><p>直接运行降级安装包，它会自动覆盖安装（无需密码）！</p><blockquote><p><strong>注意：</strong> 如果按转结束后<strong>不要点重启</strong>，不然你的希沃管家版本又回去了。</p></blockquote><h3 id="第二步：查找还原密码"><a href="#第二步：查找还原密码" class="headerlink" title="第二步：查找还原密码"></a>第二步：查找还原密码</h3><ol><li>进入希沃管家的数据目录：<code>C:\ProgramData\Seewo\SeewoCore</code></li></ol><p><img src="https://pic1.zhimg.com/80/v2-68960eafe5cf5b8b2dfd3f5102689e0e_1440w.webp" alt="鼠标批注的，各位轻喷"></p><p>（ProgramData文件夹默认是隐藏的，需要在文件夹选项中开启”显示隐藏文件”）</p><ol start="2"><li><p>找到并打开 <code>SeewoCore.ini</code> 文件</p></li><li><p>在文件中找到一串32位的字符：</p></li></ol><p><img src="https://picx.zhimg.com/80/v2-ea3b90dd04333287cf79429579f5f8a5_1440w.webp" alt="配置文件中的密码"></p><ol start="4"><li>这串32位字符实际上是MD5加密后的密码，需要解密：</li></ol><ul><li>访问MD5解密网站（如：cmd5.com）</li><li>输入这串32位密文</li><li>得到6位数字密码</li></ul><p><img src="https://picx.zhimg.com/80/v2-cb21ee3560d5ccf1dbc9f771068466d4_1440w.webp" alt="MD5解密结果"></p><h3 id="第三步：成功"><a href="#第三步：成功" class="headerlink" title="第三步：成功"></a>第三步：成功</h3><p>获取密码后，就可以正常卸载希沃管家或修改设置了：</p><p><img src="https://pic1.zhimg.com/80/v2-462f224ab32ab5b94b09d2c44e178f40_1440w.webp" alt="成功界面"></p><hr><blockquote><p><strong>温馨提示：</strong> 此方法仅供解决实际使用中的困难，请勿用于非法用途。</p></blockquote>]]>
      </content:encoded>
    </item>
  </channel>
</rss>
