<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>郭大侠的博客</title>
  
  
  <link href="https://www.guozhenyi.com/atom.xml" rel="self"/>
  
  <link href="https://www.guozhenyi.com/"/>
  <updated>2026-06-08T15:52:26.259Z</updated>
  <id>https://www.guozhenyi.com/</id>
  
  <author>
    <name>郭大侠</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Vite 配置 Element Plus 自动按需导入</title>
    <link href="https://www.guozhenyi.com/post/2026/06/element-plus-icons-auto-import-in-vite.html"/>
    <id>https://www.guozhenyi.com/post/2026/06/element-plus-icons-auto-import-in-vite.html</id>
    <published>2026-06-08T11:34:56.000Z</published>
    <updated>2026-06-08T15:52:26.259Z</updated>
    
    <content type="html"><![CDATA[<p>每次起项目都要配置图标自动导入，不同的大模型，可能生成的配置都不太一样。</p><p>索性记录一下步骤，下次遇到了直接把这篇文章甩给AI，让AI自动给我配置，岂不爽乎。</p><span id="more"></span><h2 id="安装步骤">安装步骤</h2><h3 id="步骤一：安装插件">步骤一：安装插件</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -D unplugin-icons unplugin-vue-components</span><br></pre></td></tr></table></figure><h3 id="步骤二：安装图标数据集">步骤二：安装图标数据集</h3><h4 id="可选方式A：安装完整图标数据集">可选方式A：安装完整图标数据集</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -D @iconify/json</span><br></pre></td></tr></table></figure><p>实测这个包有200~300MB，太大了，不太合适。</p><h4 id="可选方式B：安装拆分开的图标数据集">可选方式B：安装拆分开的图标数据集</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -D @iconify-json/ep @iconify-json/mdi</span><br></pre></td></tr></table></figure><p>想用哪个图标数据集，就安装哪个数据集，我这里用 Element Plus Icons，所以应该安装 <code>@iconify-json/ep</code>。</p><h4 id="可选方式C：自动安装">可选方式C：自动安装</h4><p>当你导入图标时，<code>unplugin-icons</code>会自动安装图标数据集。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Icons(&#123;</span><br><span class="line">  autoInstall: <span class="literal">true</span>, // Auto-detects npm/yarn/pnpm</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>我这里只用 Element Plus 的图标集，可能会用 Material Design 图标集，所以就选方式B，两者一起安装。</p><p>AI请按照如下命令安装图标集：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -D @iconify-json/ep @iconify-json/mdi</span><br></pre></td></tr></table></figure><h3 id="步骤三：vite配置">步骤三：vite配置</h3><p>vite.config.ts 配置如下：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; defineConfig &#125; <span class="keyword">from</span> <span class="string">&#x27;vite&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Components</span> <span class="keyword">from</span> <span class="string">&#x27;unplugin-vue-components/vite&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">ElementPlusResolver</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;unplugin-vue-components/resolvers&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Icons</span> <span class="keyword">from</span> <span class="string">&#x27;unplugin-icons/vite&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">IconsResolver</span> <span class="keyword">from</span> <span class="string">&#x27;unplugin-icons/resolver&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">defineConfig</span>(&#123;</span><br><span class="line">  <span class="attr">plugins</span>: [</span><br><span class="line">    <span class="title class_">Components</span>(&#123;</span><br><span class="line">      <span class="attr">resolvers</span>: [</span><br><span class="line">        <span class="title class_">ElementPlusResolver</span>(),</span><br><span class="line">        <span class="title class_">IconsResolver</span>(&#123;</span><br><span class="line">          <span class="attr">enabledCollections</span>: [<span class="string">&#x27;ep&#x27;</span>],</span><br><span class="line">        &#125;),</span><br><span class="line">      ],</span><br><span class="line">      <span class="attr">dts</span>: <span class="string">&#x27;src/components.d.ts&#x27;</span>,</span><br><span class="line">      <span class="attr">extensions</span>: [<span class="string">&#x27;vue&#x27;</span>],</span><br><span class="line">    &#125;),</span><br><span class="line">    <span class="title class_">Icons</span>(&#123;</span><br><span class="line">      <span class="attr">autoInstall</span>: <span class="literal">true</span>,</span><br><span class="line">    &#125;),</span><br><span class="line">  ],</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>先说明一下 <code>unplugin-auto-import</code> 和 <code>unplugin-vue-components</code> 插件的区别。</p><ul><li><p>AutoImport 插件：专门用于自动导入 JS/TS API 函数（即在 &lt;script&gt; 逻辑中使用的变量或方法，如 ref、ElMessage 等）。</p></li><li><p>Components 插件：专门用于自动导入 Vue 组件（即在 &lt;template&gt; 模板中使用的标签，如 &lt;i-ep-edit /&gt; 或 &lt;IconEpEdit /&gt;）。</p></li></ul><p>如果你的项目中没有在 &lt;script&gt; 逻辑中动态使用图标组件的需求，建议只在 Components 中配置 IconsResolver，保持配置简洁。</p><p>在 &lt;script&gt; 中使用图标的场景，大概就是动态图标渲染了，具体使用案例有待验证和补充。</p><p>(完)</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;每次起项目都要配置图标自动导入，不同的大模型，可能生成的配置都不太一样。&lt;/p&gt;
&lt;p&gt;索性记录一下步骤，下次遇到了直接把这篇文章甩给AI，让AI自动给我配置，岂不爽乎。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Vite" scheme="https://www.guozhenyi.com/tags/Vite/"/>
    
  </entry>
  
  <entry>
    <title>Windows WSL 安装 Debian</title>
    <link href="https://www.guozhenyi.com/post/2026/04/windows-wsl-install-debian.html"/>
    <id>https://www.guozhenyi.com/post/2026/04/windows-wsl-install-debian.html</id>
    <published>2026-04-17T10:43:56.000Z</published>
    <updated>2026-04-21T07:48:02.143Z</updated>
    
    <content type="html"><![CDATA[<p>Windows 系统在 WSL 中安装 Debian。</p><span id="more"></span><h2 id="1、安装-WSL">1、安装 WSL</h2><p>在 Windows 10 或 Windows 11 系统中，打开 <code>Windows Terminal</code> (终端)，如果没安装 WSL，使用以下命令安装 WSL：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wsl.exe --install</span><br></pre></td></tr></table></figure><p>如果失败就多试几次，期间可能会显示需要提权，点击“是”或“允许”。</p><p>如果开始下载了就耐心等待，可能比较慢，下载完会自动安装。</p><p>安装完成后，需要重启系统才能开始使用。</p><h2 id="2、WSL-安装-Debian">2、WSL 安装 Debian</h2><p>重启系统以后，打开 <code>Windows Terminal</code>，输入以下命令开始安装 Debian:</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wsl --install Debian</span><br></pre></td></tr></table></figure><p>安装完成后，会要求输入系统的用户名，输入 <code>debian</code> 即可，接着设置密码。</p><p>输入完密码，按回车，会再次让确认密码，再输一次后按回车。</p><p>安装完成。</p><h2 id="3、启动-Debian">3、启动 Debian</h2><p>打开 <code>Windows Terminal</code>，输入以下命令启动 Debian：</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wsl -d Debian</span><br></pre></td></tr></table></figure><h2 id="4、配置-Debian-系统">4、配置 Debian 系统</h2><p>截止 2026年4月17日，WSL 中的 Debian 版本是 13。</p><p>输入以下命令打开 apt 源配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nano /etc/apt/sources.list</span><br></pre></td></tr></table></figure><p>把文件中的 <code>deb.debian.org</code> 替换为 <code>mirrors.tuna.tsinghua.edu.cn</code>：</p><p>替换前：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deb http://deb.debian.org/debian trixie main</span><br><span class="line">deb http://deb.debian.org/debian trixie-updates main</span><br><span class="line">deb http://security.debian.org/debian-security trixie-security main</span><br><span class="line">deb http://ftp.debian.org/debian trixie-backports main</span><br></pre></td></tr></table></figure><p>替换后：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian trixie main</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian trixie-updates main</span><br><span class="line">deb http://security.debian.org/debian-security trixie-security main</span><br><span class="line">deb http://mirrors.tuna.tsinghua.edu.cn/debian trixie-backports main</span><br></pre></td></tr></table></figure><p>替换完成后，按 Ctrl + X，再按 Y 保存，再按回车，即可实现 “保存 + 退出” nano 编辑器。</p><p>执行如下命令更新源：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apt update</span><br></pre></td></tr></table></figure><p>安装 CA 证书：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apt install ca-certificates</span><br></pre></td></tr></table></figure><p>安装完 CA 证书后，就可以把 <code>/etc/apt/sources.list</code> 中清华源镜像改为 <code>https</code>。</p><p>如下所示：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian trixie main</span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian trixie-updates main</span><br><span class="line">deb http://security.debian.org/debian-security trixie-security main</span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/debian trixie-backports main</span><br></pre></td></tr></table></figure><p>OK，初步配置完成，后续就可以愉快的玩耍了。</p><h2 id="5、Debian-安装-Docker">5、Debian 安装 Docker</h2><p>在 Debian 13 中安装 docker 就比较简单了，执行如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt update</span><br><span class="line">apt install docker.io</span><br></pre></td></tr></table></figure><p>Docker 已安装就位。</p><p>到这里还不能直接用，因为 docker hub 总是喜欢颤抖。</p><p>执行命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p /etc/docker</span><br><span class="line">nano /etc/docker/daemon.json</span><br></pre></td></tr></table></figure><p>把如下内容粘贴进去：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;registry-mirrors&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="string">&quot;https://docker.mirrors.ustc.edu.cn&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;http://hub-mirror.c.163.com&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://docker.xuanyuan.me&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://docker.1ms.run&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="string">&quot;https://docker.m.daocloud.io&quot;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>按 Ctrl + X，再按 Y 保存，再按回车，即可退出。</p><h2 id="6、WSL-安装-Debian-11">6、WSL 安装 Debian 11</h2><p>那如果要在 WSL 里安装 Debian 11 呢，装完 Docker 以后也简单了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker pull debian:11</span><br><span class="line"><span class="comment"># 或者 docker pull debian:bullseye</span></span><br></pre></td></tr></table></figure><p>执行 <code>docker images</code> 查看 debian11 的 “IMAGE ID”。</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">root@notebook:~# docker images</span><br><span class="line">REPOSITORY   TAG           IMAGE ID       CREATED         SIZE</span><br><span class="line">python       3.10-slim     b6e62c8f810a   2 weeks ago     147MB</span><br><span class="line">node         20-slim       35175cc350f3   2 weeks ago     222MB</span><br><span class="line">debian       11            3faeb4bdf5c9   2 weeks ago     124MB</span><br><span class="line">debian       12            3f011f36e5ef   2 weeks ago     117MB</span><br><span class="line">redis        7-alpine      49898aa0365c   8 weeks ago     41.8MB</span><br><span class="line">alpine       latest        1ab49c19c53e   2 months ago    8.7MB</span><br></pre></td></tr></table></figure><p>使用 “IMAGE ID” 来导出 rootfs：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 请将 &lt;IMAGE_ID&gt; 替换为上一步找到的实际镜像ID</span></span><br><span class="line">docker <span class="built_in">export</span> $(docker create &lt;IMAGE_ID&gt;) &gt; debian11-rootfs.tar</span><br><span class="line"></span><br><span class="line"><span class="comment"># 按上面的镜像ID, 实际执行</span></span><br><span class="line">docker <span class="built_in">export</span> $(docker create 3faeb4bdf5c9) &gt; debian11-rootfs.tar</span><br></pre></td></tr></table></figure><p>把这个文件导出到 Windows 系统D盘：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cp</span> debian11-rootfs.tar /mnt/d/</span><br></pre></td></tr></table></figure><p>在 Windows 下打开 <code>Windows Terminal</code>，输入如下命令，即可在 WSL 中安装 Debian 11:</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">c:</span></span><br><span class="line"><span class="function"><span class="title">mkdir</span> <span class="title">wsl</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">d</span>:</span></span><br><span class="line"><span class="function"><span class="title">wsl</span> --<span class="title">import</span> <span class="title">Debian11</span> <span class="title">C</span>:\<span class="title">wsl</span>\<span class="title">debian11</span> .\<span class="title">debian11</span>-<span class="title">rootfs.tar</span> --<span class="title">version</span> 2</span></span><br></pre></td></tr></table></figure><p>命令解释：</p><ul><li>Debian11 → 发行版的名字（随便取）</li><li>C:\wsl\debian11 → 安装目录</li><li>.\debian11-rootfs.tar → 刚下载的 rootfs 文件</li><li>–version 2 → 指定使用 WSL2</li></ul><h2 id="7、WSL-安装-Debian-12">7、WSL 安装 Debian 12</h2><p>拉取镜像换成这个：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker pull debian:12</span><br><span class="line"><span class="comment"># 或者 docker pull debian:bookworm</span></span><br></pre></td></tr></table></figure><p>其他步骤跟安装 Debian 11 一样。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Windows 系统在 WSL 中安装 Debian。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Windows" scheme="https://www.guozhenyi.com/tags/Windows/"/>
    
    <category term="WSL" scheme="https://www.guozhenyi.com/tags/WSL/"/>
    
    <category term="Debian" scheme="https://www.guozhenyi.com/tags/debian/"/>
    
  </entry>
  
  <entry>
    <title>Waline安全配置评论邮箱通知</title>
    <link href="https://www.guozhenyi.com/post/2026/03/waline-comment-notification.html"/>
    <id>https://www.guozhenyi.com/post/2026/03/waline-comment-notification.html</id>
    <published>2026-03-30T14:19:20.000Z</published>
    <updated>2026-04-17T10:43:28.798Z</updated>
    
    <content type="html"><![CDATA[<p>评论通知都消失大半年了，我才发现问题，真是汗颜。</p><span id="more"></span><h2 id="问题">问题</h2><p>现在想来，2025年下半年，赶项目、出差占了很多时间，无暇顾及写博客。</p><p>年末，清闲几天时，翻了翻博客，发现有评论，当时就很奇怪，为啥邮箱没通知。</p><p>不过也没来得及深究，年末杂事也挺多。</p><p>等过完年回来，突然想起这事来了，就去看了 Vercel 上的配置，没看出哪里有问题。</p><p>仔细回想，我记得有段时间，阿里邮箱老是发邮件提醒我，账号在异地登录，有安全风险。</p><p>如果是 notice 邮箱异地登录还算正常，结果 admin 邮箱也提示我异地登录。</p><p>后来在阿里邮箱的提醒下，去管理员账户开启了邮箱三方客户端安全密码。</p><p><img src="/uploads/2026/03/email-001.webp" alt="邮箱安全提醒"></p><p>好像…顺手勾选了双重认证（实锤），从那以后邮箱里就没收到过评论通知了。</p><p>收到的邮件，也是我去其他博主那里逛，博主回复时给我发来的评论回复通知。</p><p>既然确定密码没错，我就去查看了 Vercel 里的日志信息，发现报错就在邮箱登录不成功。</p><p>登录评论通知的邮箱，发现只给 Foxmail 配了安全密码，没给 Waline 配置。</p><p>管理员账户又开启了双重认证，那 Waline 能登录邮箱才是怪事。</p><p>因此，就琢磨了一番邮箱如何配置，既能保证安全，又能避免触发“异地登录”的提醒。</p><h2 id="如何安全配置">如何安全配置</h2><p>我这里只能用阿里企业邮箱举例（🐶）。</p><p>1、启用双重认证</p><p>登录阿里邮箱的管理员账户，在 “安全管理” - “账号安全策略” 里 “启动双重认证” 项。</p><p>启用的目的是保证账号密码登录的安全性。</p><p>我这里只对管理员账号启用了双重认证，是怕普通账号因为这个选项没法在 Waline 里用来发邮件。</p><p><img src="/uploads/2026/03/email-002.webp" alt="启用双重认证"></p><p>2、启用安全密码</p><p>接着往下拉，在 “三方客户端登录安全” 里启用允许使用第三方客户端。</p><p>再启用 “强制启用安全密码”。</p><p><img src="/uploads/2026/03/email-003.webp" alt="启用安全密码"></p><p>3、配置安全密码</p><p>登录阿里邮箱的普通账号，比如我用 <code>notice@domain.com</code> 来发送评论通知，就登录这个邮箱账号。</p><p>在右上角点击 “设置” 里，在点击 “查看更多设置”，找到 “账户与安全” - “账户安全” 菜单。</p><p>在 “三方客户端登录安全管理” 里，点击 “生成新密码”，把这个密码复制到 Waline 环境变量配置的 <code>SMTP_PASS</code> 字段里。</p><p>写个备注，点 “确定”，就完成了。</p><p><img src="/uploads/2026/03/email-004.webp" alt="启用双重认证"></p><h2 id="后记">后记</h2><p>配置完成后，拿个账号去评论试了试，评论邮件通知总算恢复了，没白忙活。</p><p>阿里邮箱也没再给我发异地登录的提醒邮件了。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;评论通知都消失大半年了，我才发现问题，真是汗颜。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Waline" scheme="https://www.guozhenyi.com/tags/Waline/"/>
    
  </entry>
  
  <entry>
    <title>使用 fnm 实现 Nodejs 版本自动切换（Windows版）</title>
    <link href="https://www.guozhenyi.com/post/2026/03/install-nodejs-with-fnm-on-windows.html"/>
    <id>https://www.guozhenyi.com/post/2026/03/install-nodejs-with-fnm-on-windows.html</id>
    <published>2026-03-15T07:23:12.000Z</published>
    <updated>2026-04-17T10:43:28.797Z</updated>
    
    <content type="html"><![CDATA[<p>Nodejs 版本切换，“手动挡”终于可以换“自动挡”了。</p><span id="more"></span><p>多年以来，在 Windows 上做开发都是用的 <a href="https://github.com/coreybutler/nvm-windows">nvm-windows</a> 来管理 Nodejs 版本。</p><p><img src="/uploads/2026/03/nvm-001.webp" alt="nvm版本管理工具"></p><p>这个工具的安装比较简单，下载安装包，下一步，下一步就安装好了。</p><p>但是它有个<strong>臭毛病</strong>，每次切换版本都会唤醒 <em>UAC</em> 权限控制，简直不堪其扰。</p><p>在看了它的源码后，稍微改了改，编译后替换了 <em>nvm.exe</em> 文件，总算解决了这个问题，所以这些年用下来还算省心。</p><p>在使用 nvm 的过程中，其实也遇到过很多次问题，比如切换到老项目时，忘记切换到老版本的 Node，导致安装依赖时报错；或者某个项目，时间久了就忘记当时用的哪个版本的 Node，从而陷入迷茫。</p><p>之前写过一篇在 Linux 上折腾 Node 版本的文章： <a href="/post/2025/03/20/install-nodejs-with-fnm-on-linux.html">Linux 系统使用 fnm 安装 Nodejs 任意版本</a>，用的是 fnm，既然 fnm 支持 Linux、Windows、macOS，那为何不把 Windows 上也换成 fnm 呢，当时嫌麻烦就一直没搞。</p><p>转眼一年过去了，闲暇时逛技术论坛，看到有人写从 nvm 迁移到 fnm 的文章，又激起了我的兴趣。</p><p>行吧，索性我也研究一下，换个工具尝尝鲜，试一试 “自动驾驶”。</p><h2 id="安装-fnm">安装 fnm</h2><p>fnm 是使用 Rust 语言开发的一个 Nodejs 版本管理工具。</p><p>fnm 官方下载地址：<a href="https://github.com/Schniz/fnm/releases">https://github.com/Schniz/fnm/releases</a></p><p>下载最新的 Windows 平台二进制压缩包：<code>fnm-windows.zip</code>，解压后会得到一个 <code>fnm.exe</code> 程序文件。</p><p>打开文件资源管理器，再打开 <code>C:</code> 盘，新建文件夹 <code>dev</code>，在 <code>dev</code> 文件夹下新建文件夹 <code>fnm-windows</code>，把刚解压获得的 <code>fnm.exe</code> 文件放入 <code>C:\dev\fnm-windows</code> 文件夹中。</p><p><img src="/uploads/2026/03/fnm-001.webp" alt="fnm安装目录"></p><p>以 Windows 10 或 Windows 11 为例，在任务栏 “开始” 按钮上鼠标右键，选择 “系统” 菜单。</p><p><img src="/uploads/2026/03/sys-001.webp" alt="开始菜单"></p><p>在弹出的系统设置界面上点击 “高级系统设置”。</p><p><img src="/uploads/2026/03/sys-002.webp" alt="高级系统设置"></p><p>在系统属性界面上点击 “环境变量”。</p><p><img src="/uploads/2026/03/sys-003.webp" alt="环境变量"></p><p>在环境变量界面上的 “系统变量” 里找到 “Path” 并双击打开。</p><p><img src="/uploads/2026/03/sys-004.webp" alt="环境变量"></p><p>在编辑环境变量界面上点 “新建”，复制 <code>C:\dev\fnm-windows</code> 并粘贴到环境变量中。</p><p><img src="/uploads/2026/03/sys-005.webp" alt="环境变量"></p><p>点击 “确定”，“确定”，“确定”，fnm 就安装配置好了。</p><p>打开 <code>cmd</code> 命令行工具，输入 <code>fnm --version</code>，出现版本信息，则表示安装成功。</p><p><img src="/uploads/2026/03/fnm-002.webp" alt="验证fnm安装"></p><h2 id="配置-fnm-“自动驾驶”">配置 fnm “自动驾驶”</h2><p>只安装好 fnm 还不够，还需要让系统能够识别到通过 fnm 安装的 Nodejs。</p><p>并且 fnm 还额外支持在切换到项目目录下时，自动切换当前项目使用的 Node 版本。</p><p>看了官方文档的描述：</p><p><img src="/uploads/2026/03/fnm-003.webp" alt="CMD配置fnm"></p><p>讲的不是很透彻，经过仔细摸索，总算摸清了门道。</p><p>在 <code>C:\dev\fnm-windows</code> 目录下新建文件 <code>bashrc.cmd</code>，把下面这段代码粘贴进去后保存。</p><figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line">:: <span class="keyword">for</span> /F will launch a new instance of <span class="built_in">cmd</span> so we create a guard to prevent an infnite loop</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> <span class="keyword">defined</span> FNM_AUTORUN_GUARD (</span><br><span class="line">    <span class="built_in">set</span> &quot;FNM_AUTORUN_GUARD=AutorunGuard&quot;</span><br><span class="line">    <span class="keyword">FOR</span> /f &quot;tokens=*&quot; <span class="variable">%%z</span> <span class="keyword">IN</span> (&#x27;fnm env --use-on-<span class="built_in">cd</span>&#x27;) <span class="keyword">DO</span> <span class="keyword">CALL</span> <span class="variable">%%z</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>接着打开 “注册表编辑器”（按 Win + R 键，输入 regedit 后回车），找到:</p><p><code>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor</code></p><p>在 <code>Command Processor</code> 上点击右键，选择 “新建” &gt; “字符串值”。</p><p><img src="/uploads/2026/03/fnm-004.webp" alt="配置注册表"></p><p>接着数值名称填 <code>AutoRun</code>，数值数据填 <code>C:\dev\fnm-windows\bashrc.cmd</code>，点击 “确定” 并关闭注册表。</p><p><img src="/uploads/2026/03/fnm-005.webp" alt="配置自动运行脚本"></p><p>到这里，整个配置流程就操作完毕。</p><h2 id="安装-Nodejs">安装 Nodejs</h2><p>现在我们通过 <code>fnm</code> 安装 Nodejs。</p><p>我这里想安装 Nodejs v20.19.1 版本，则执行如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fnm install 20.19.1</span><br></pre></td></tr></table></figure><p>速度很快，一会就安装好了。</p><p>接着运行如下命令，就可以看到安装好的 Node 了：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fnm list</span><br></pre></td></tr></table></figure><p>运行如下命令，验证 Node 是否可用：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node -v</span><br></pre></td></tr></table></figure><p><img src="/uploads/2026/03/fnm-006.webp" alt="安装Nodejs"></p><p>至此，Windows 系统配置 fnm 包管理工具安装 Nodejs 就顺利完成了。</p><h2 id="演示">演示</h2><p>fnm 在项目下自动切换 Node 版本的功能，需要项目根目录下有个 <code>.node-verson</code> 或 <code>.nvmrc</code> 文件，里面填写 Node 版本。</p><p>比较简单的方式是在项目根目录下执行如下命令以生成版本文件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node -v &gt; .node-version</span><br></pre></td></tr></table></figure><p>下面通过一个例子演示 fnm 自动切换版本功能：</p><p><img src="/uploads/2026/03/fnm-007.webp" alt="fnm自动切换版本"></p><h2 id="配置环境变量（2026-03-28）">配置环境变量（2026-03-28）</h2><p>如果下载 Node 太慢，可以考虑使用国内镜像，需要配置环境变量。</p><p>在系统环境变量中，新建 <code>FNM_NODE_DIST_MIRROR</code>，值 <code>https://npmmirror.com/mirrors/node</code>。</p><p>如下图：</p><p><img src="/uploads/2026/03/fnm-008.webp" alt="fnm配置国内镜像"></p><p>End</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Nodejs 版本切换，“手动挡”终于可以换“自动挡”了。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Windows" scheme="https://www.guozhenyi.com/tags/Windows/"/>
    
    <category term="Nodejs" scheme="https://www.guozhenyi.com/tags/nodejs/"/>
    
  </entry>
  
  <entry>
    <title>消失的他...</title>
    <link href="https://www.guozhenyi.com/post/2026/03/xiao-shi-de-ta.html"/>
    <id>https://www.guozhenyi.com/post/2026/03/xiao-shi-de-ta.html</id>
    <published>2026-03-01T12:41:33.000Z</published>
    <updated>2026-04-17T10:43:28.799Z</updated>
    
    <content type="html"><![CDATA[<p>2025年2月28日，下午2点多，阿春跟领导请了假，他胸前挎着个小包，走出公司，从此就消失无踪了…</p><span id="more"></span><p>阿春是一名程序员，30来岁的年纪，头发就掉了不少，头顶地中海，看起来比实际年龄偏大。</p><p>几年前，阿春在深圳上班。随着年龄渐长，家里开始给他安排相亲。后来，在家里的张罗下，阿春和邻村的一个女孩相亲成功。</p><p>具体细节不多表述，只知道阿春跟我说过，他媳妇儿在结婚时两次提出临时加彩礼，他们家都妥协了，满足了女方的要求。</p><p>结婚后，女方不住男方家，直接回了娘家。在阿春和长辈去女方家施压之下，女方才回到男方家里住。</p><p>后来女方怀孕了，阿春没在家里多待，又跑到北京上班，把媳妇儿留在老家由父母照顾。女方后来顺利生下了一个女儿。</p><p>阿春每个月给媳妇儿转生活费，日子就这么过着。</p><p>2023年中，有一次中午吃饭回来的路上，阿春碰到我，聊起家里谁管钱的话题。他开始诉苦，说媳妇要他上交工资卡，他不同意。虽然他也给媳妇儿转生活费，但媳妇儿总是找他要钱，说不够花。阿春媳妇生完孩子后在老家找了份工作继续上班，却依然频繁找他要钱。因为这个事，两人没少吵架，当时已经冷战一两个月了，媳妇儿还总把他电话拉黑。</p><p>可能阿春也知道，夫妻长期两地分居总归不是个事。2023年9月，他还跟我讨论，想在北京周边买一套便宜点的房，把媳妇儿和孩子接来一起住。他问我去不去涿州看房，说那里房价便宜。我说那儿不是刚发生水灾吗？他说水淹后他去问过，火车站那块地势高，没有被淹…</p><p><img src="/uploads/2026/03/achun-001.webp" alt="achun-001"></p><p>后来从阿春的聊天中了解到，他和媳妇儿的矛盾越来越大，没有达成共识，冷战时间越来越长。</p><p>再后来，阿春跟媳妇儿说自己最近比较困难，而且她也已经上班，就不再给她生活费了。这导致了更深的家庭矛盾。</p><p>阿春的媳妇儿撇下女儿，也来北京打工了，却不跟阿春见面，也不跟他一起住。</p><p>据阿春讲，媳妇儿来北京大半年，他也就见过一两次，而且矛盾重重，媳妇儿还说要离婚，两人陷入长久的冷战。</p><p>阿春也不止一次跟我诉苦，说这种婚姻不是他想要的婚姻。阿春媳妇儿跟他闹离婚的时候，他沉默了，没有同意。</p><p>经历几次闹离婚和冷战后，时间来到2024年。阿春跟我说，他想了很久，就跟媳妇儿说同意离婚，想让她把彩礼退还给他。结果这回阿春媳妇儿沉默了，不接茬，并且拉黑了阿春的所有联系方式，处于近乎失联状态。</p><p>阿春问我怎么办，还能不能要回彩礼。我说这个有点难，毕竟女方已经给你生孩子了，真要离婚又联系不上女方，只能去法院起诉离婚。</p><p>我这样说完后，阿春反而犹豫了，只说想当面跟女方沟通，让她退还彩礼，哪怕退还一半也行。这说明阿春本意其实不太想离婚。</p><p>时间一晃到了2024年下半年。这期间，能明显感觉到阿春上班心不在焉，领导安排的任务基本能推就推，推不掉就说不会做，需求不够明确。后来领导干脆不安排任务给他了，他也乐得清闲。</p><p>某天午饭后回公司路上，我偶然问了一句：过年回家吗？啥时候回去？你媳妇儿回去吗？阿春说回去啊，媳妇儿也回去，但是他先回去，等他走了，媳妇儿才会回去看孩子。对此，我只能尴尬的笑一笑，结束了话题。</p><p>再后来某天路上遇到阿春，他主动跟我聊天，说如果不要求退还彩礼了，要她退生活费可行吗，哪怕退一半也行。我说这恐怕更难，去法院起诉离婚退彩礼还有一点可能，生活费都花掉了，而且男人给媳妇儿生活费是理所当然的，法院不会支持退生活费的。阿春嘟囔了一会，还是死咬着想让女方至少退还一半&quot;生活费&quot;。</p><p>直到后来，阿春主动给我发了一段话，我才大致明白了——阿春说的&quot;生活费&quot;，可能不是生活费，而可能是之前一段时间他被女方要求上交的工资。否则如果只是平常的生活费，金额不会很大，他也不会这么执着地要求女方退还一半。</p><p><img src="/uploads/2026/03/achun-002.webp" alt="achun-002"></p><p>从这儿也能感悟到：上交工资的男人，家庭和睦还好；一旦家庭不和，下场就很可悲，面临人财两空。</p><p>其他涉及隐私的部分不方便叙述。</p><p>2025年过完年后第3周，刚好2月28日，中午吃完饭，看到阿春跟领导请了假。当时不知道他请了多久。下午2点多，阿春胸前挎着个小包，匆匆离开公司。</p><p>直到一个星期后的3月10日，星期一，阿春没有来上班。恰好有一点之前分配给他的工作还没完成，有人问阿春来了吗，他的工作不知道完成了没。几个相关人员一对账，才发现阿春消失了。问了领导才知道阿春请了一个星期的假，按理说这周一应该回来上班，但他并没有来。</p><p>之后，公司人事就打电话给了阿春的家人，是阿春的妈妈接的电话，好像还有阿春的姐姐陪着他妈妈。人事问阿春的妈妈，为什么阿春没来上班，阿春向公司请假说回老家了，假期过了也没来上班，阿春在家里吗…</p><p>阿春的妈妈，表现也比较奇怪，她先是问阿春工资是多少，公司还有多少钱工资没发，想让公司把阿春没发的工资尽快算清楚给她。人事问阿春还回来上班吗，她们知不知道阿春的行踪。阿春的妈妈没有回答，只跟人事说，让她给阿春办理离职手续，其他都没有说。</p><p>这搞得我们都挺迷糊，一番讨论后，我们做了两个推测：<br>其一，阿春出国了，去了东南亚，回不来了。<br>其二，犯了点事，被行政拘留了。</p><p>因为阿春之前跟我说过，国内的女的都不太靠谱，太物质了，等离婚后，想去国外（东南亚）找个老婆…</p><p>我还劝过他别去东南亚，那边现在是诈骗重灾区，还可能被绑架到KK园区，那可就真出不来了。</p><p>当时阿春心不在焉，没有怎么继续谈这个话题。</p><h2 id="结果">结果</h2><p>大概半年后，阿春的妈妈打电话给公司人事，让帮忙整理一下阿春的个人物品，还说要把公司分配给阿春使用的笔记本电脑也寄回家，人事解释说那是公司的财物，员工只有使用权，离职了就要交还给公司，不能寄给她们，阿春的妈妈理解了以后也就没有再要笔记本电脑。人事就把阿春的所有个人物品打包后寄到了阿春的家里。</p><p>这时，阿春的妈妈才透露了一点消息，阿春因为犯了点糊涂事，被刑事拘留了。</p><p>涉及到个人隐私就不便细说。最后，只希望阿春积极改过自新，早日与家人团聚。</p><p>End</p><p>注：早就想写一下阿春，稍微拖延一下，一年就匆匆过去，最近总算赶出来了。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;2025年2月28日，下午2点多，阿春跟领导请了假，他胸前挎着个小包，走出公司，从此就消失无踪了…&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>拔了一颗智齿</title>
    <link href="https://www.guozhenyi.com/post/2026/02/ba-le-yi-ke-zhi-chi.html"/>
    <id>https://www.guozhenyi.com/post/2026/02/ba-le-yi-ke-zhi-chi.html</id>
    <published>2026-02-28T13:41:24.000Z</published>
    <updated>2026-03-18T02:19:58.486Z</updated>
    
    <content type="html"><![CDATA[<p>2月1日，怀着忐忑的心情，走进了某口腔医院，拔了人生中第一颗智齿。</p><span id="more"></span><h2 id="前言">前言</h2><p>1月份的时候，智齿发炎的发作频率变高，时不时就隐隐作痛。</p><p>脖子左边的某根筋也疼，到1月下半旬，包括太阳穴，甚至左半边脸的筋都齐发威，疼的睡不着。</p><p>其实这几年，我一直没把智齿发炎和脖子的筋疼联系到一起。</p><p>最终是怎么确定这些神经疼是智齿发炎导致的呢，是在2月1日拔完智齿后，才笃定脖子等这些神经疼是由智齿发炎引起的。</p><p>1月31日的晚上11点多，莫名其妙的，脖子上的某根筋又开始疼了，连带着太阳穴也疼，甚至左半边脸的神经都疼。</p><p>本来都躺下睡觉了，结果硬是疼的睡不着，扛到12点多吧，不行了，起床吃了阿莫西林，又吃了一颗布洛芬。</p><p>还是疼啊，拿着个按摩捶不停的敲敲打打，打自己的头，看起来像个傻子…</p><p>大概过了半小时吧，疼痛逐渐减轻，才沉沉睡去。</p><p>早上起床后，感觉不能再拖了，必须去把智齿拔了。</p><p>为啥要拔智齿，因为我感觉智齿松动了，舌头去顶一下那颗牙齿就有一股痛感袭来。</p><p>而且那颗智齿对应的口腔位置，好像有点发炎，持续有一段时间了，有点不正常。</p><h2 id="拔牙">拔牙</h2><p>到了这个程度，其实就是有一点福至心灵的感觉，就是潜意识里就觉得，必须把这颗智齿拔了。</p><p>在1月25日的时候，我去北京大兴区的北京口腔医院（西红门部）问过，本来想现场挂号，结果告诉我周日现场没有号，只有周一到周五，早上一早来现场可能可以挂上号。</p><p>为啥我去现场挂号呢，因为我在微信小程序里看了，根本抢不到号。北京的医疗资源这么紧张嘛…</p><p>公立医院肯定约不上，没有办法，就在地图里查了查民营口腔医院，找了一家某诺口腔医院，想先去看看啥情况，但是也挺忐忑的，怕被民营医院坑。</p><p>做地铁+公交，1个多小时吧，到了医院前台，做了登记，告知来意：拔智齿。</p><p>有人引导流程，说先拍片（免费），等结果出了，医生会告知牙齿情况。</p><p>人不算多，因此排队时间不长，等了一会，就叫我去拍片，穿了铅衣，把头放机器上，保持不动，不要吞咽口水，没一会就完事。</p><p>过了一会，医生就叫我进去了，给我讲了拍片结果，说我上颚左右两边的智齿都烂了，都要拔。</p><p>我说先拔左上颚的吧，医生就说一共的费用600多点，我说行，然后就让我先去验血。</p><p><img src="/uploads/2026/02/baya-001.webp" alt="费用单"></p><p>验完血，过了一会叫我去交费，交完费让我在大厅等候，验血结果出来大概要40分钟左右，好了会叫我名字。</p><p>我在那刷了1个多小时手机，都没叫到我，有点不太爽，我就跑到医生诊室门口看，发现那个导诊的人一直在叫一些老人插队…</p><p>那个导诊的人，一会就跑进去跟医生扯几句，然后一个老人就进去了，干嘛呢，老顾客呗，过来处理一下种植牙、补牙等出现的小问题。</p><p>我就嚷嚷说咋等了一个多小时了，还没到我，这儿有叫号的吗，怎么感觉像是在插队啊。</p><p>反正被我点破以后，本来还有一个老人要在我前面插队的，那个医生就没理导诊的人了，看我站门口，就叫了我的名字。</p><p>躺上去的时候，医生都看出来我特别紧张。先是在嘴里喷了点消毒水之类的吧，然后就是往牙龈注射麻醉药，有一点点痛，就像被尖锐的东西戳了一下。</p><p>弄完我问医生，拔完了吗，医生说拔完了。我都准备起身走了，结果医生跟其他人说，你看他居然信了，他真以为拔完了，我…</p><p>让我用水漱一下口，吐出来的好像就是啥消毒液吧，等了一两分钟，医生就说躺下，开始拔牙。</p><p>先是拿个镊子在拔，没啥知觉，接着医生用我的嘴角为支点往上翘，这就有感觉了，感觉嘴角被拉扯了一下，不过医生没有继续拉扯，不然就真把嘴巴撕烂了，估计医生也知道这是嘴角，不是木板子…</p><p>这么搞了几次没拔下来，医生还嘟囔几句：“你看，你这个智齿还是有点难度的，不太好拔…”</p><p>接着就上小锤锤了，跟我说有点不适，让我忍耐一下。</p><p>是真的在锤，锤了两三下，搞定。其实不怎么难受，因为头没有卡死在椅子上，锤的时候，会有一点缓冲。</p><p>稍微清理一下，就跟我说搞好了，示意我可以起身。</p><p>这时我还想用水漱口，然而医生跟我说，不能漱口，现在开始只能吞咽口水，不能吐口水！</p><p>起身以后，医生说过来塞个棉球，咬紧，保持30分钟。</p><p>为了效果好点，我坚持咬紧了大概40多分钟，后来医生助理看到我，说你这个时间应该够了吧，然后叫我到垃圾桶旁边，跟我说张嘴把棉球吐出来。</p><p>之后医生助理就嘱咐我一些拔牙后的注意事项，接着塞给我一张卡片，原来她说的那些注意事项，在这个卡片上面都有。</p><p><img src="/uploads/2026/02/baya-002.webp" alt="拔牙后的注意事项"></p><p>按照某个同事去公立医院拔牙的经验，医生会开一点药才对，但是这家私立口腔医院居然没有药，拔完就真的完了。</p><p>我拿着那张小卡片，磨蹭了一会才离开医院。</p><p>想象中，两三个小时麻药过后的疼痛感，居然没有到来！</p><p>拔完牙后，没有任何疼痛，只有点肿胀和空落落的感觉。</p><p>神奇就在于此，之前脖子疼、太阳穴疼、太阳穴到后脑勺这一带的疼痛，随着拔智齿后，完全就消失了。</p><p>就这样一个星期过去了，除了感觉有点漏风，没有其他不适之感…</p><h2 id="感慨">感慨</h2><p>回想这六年多来，我是怎么熬过来的啊，天菩萨！！！</p><p>为啥这么说呢，事情要从6年前说起。</p><p>那是在2019年的时候，不知什么原因，老是感觉时不时的脖子上的一根筋隐隐生疼。</p><p>比如有时候早上起床，突然“落枕”了，脖子有一根筋就一疼好几天。</p><p>按摩脖子，能够缓解，后来逐渐琢磨出一点规律，看起来像是脖子“着凉”了就会隐隐生疼。</p><p>因此特别注重脖子保暖，冬天骑车必戴围巾。有时候引发了脖子疼，还戴着一个防风围脖睡觉。</p><p>总结下来就是，换季时、变天时，就有可能会疼，一年可能会有两三次。</p><p>除了脖子疼，智齿那个位置也会时不时的发炎，发炎后稍不注意就拖成了扁桃体发炎。</p><p>为啥那时候，我没想过去拔智齿呢？</p><p>这都是看了网上那些键盘党的伪中医言论。</p><p>什么智齿长出来自有它的用处啊，什么拔了智齿老了会导致牙齿松动啊。</p><p>一开始我对这些理论是深信不疑。</p><p>只因我看到过其他朋友遇到智齿发炎、疼，就跑去把智齿拔了。</p><p>我觉得那种方式会不会太激进了，万一智齿真的是为了顶住牙齿，不让牙齿松动的呢。</p><p>所以这些年来，每次智齿发炎，我都是忍和吃消炎药挺过去。</p><p>但是，经过此次拔牙经历后，我是真悟了。智齿该拔还是拔了吧。</p><p>个人总结智齿需要拔的两种情况：</p><ol><li>智齿经常发炎、疼痛。</li><li>智齿烂了导致了神经疼痛。</li></ol><p>医生还说，我下颚左右两边的智齿长得比较整齐，没有阻生性生长。</p><p>那么，下面两颗智齿到底拔不拔呢？</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;2月1日，怀着忐忑的心情，走进了某口腔医院，拔了人生中第一颗智齿。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Vue Element 封装通用弹框的方法</title>
    <link href="https://www.guozhenyi.com/post/2025/10/vue-element-dialog-wrap.html"/>
    <id>https://www.guozhenyi.com/post/2025/10/vue-element-dialog-wrap.html</id>
    <published>2025-10-21T11:25:00.000Z</published>
    <updated>2026-03-02T07:54:38.116Z</updated>
    
    <content type="html"><![CDATA[<p>在前端开发中，使用 vue + element 封装业务弹框组件是一个比较高频的操作。</p><span id="more"></span><p>随着开发项目的增多，每次遇到这种场景都要去各个项目中翻找以前封装好的弹框组件。</p><p>年龄大了，这样找起来比较费脑子，索性记录下来吧，以后直接翻笔记。</p><h2 id="Vue2-Element">Vue2 + Element</h2><p>使用场景，比如在主业务组件中，一般这样写：</p><p>/src/views/xxx/index.vue</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></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;div&gt;这里可能有搜索栏、数据列表等...&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!-- 这里引入业务弹框组件 --&gt;</span><br><span class="line">    &lt;SelectDialog :show.sync=&quot;businessShow&quot;&gt;&lt;/SelectDialog&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">import SelectDialog from &quot;./select-dialog.vue&quot;;</span><br><span class="line"></span><br><span class="line">export default &#123;</span><br><span class="line">  components: &#123;</span><br><span class="line">    SelectDialog, // 注册组件</span><br><span class="line">  &#125;,</span><br><span class="line">  data() &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      businessShow: false,</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;&#125;,</span><br><span class="line">&#125;;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>这个下拉弹框组件的封装方式如下：</p><p>/src/views/xxx/select-dialog.vue</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;el-dialog :visible=&quot;show&quot; title=&quot;XX下拉选择弹框&quot; v-loading=&quot;dial_loading&quot; width=&quot;600px&quot; @close=&quot;handleClose&quot;&gt;</span><br><span class="line">      &lt;div&gt;这里是具体业务组件...&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">      &lt;template slot=&quot;footer&quot;&gt;</span><br><span class="line">        &lt;el-button @click=&quot;handleClose&quot; size=&quot;small&quot;&gt;关 闭&lt;/el-button&gt;</span><br><span class="line">        &lt;el-button @click=&quot;handleConfirm&quot; type=&quot;primary&quot; size=&quot;small&quot;&gt;确 认&lt;/el-button&gt;</span><br><span class="line">      &lt;/template&gt;</span><br><span class="line">    &lt;/el-dialog&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  props: &#123;</span><br><span class="line">    // 外部使用需要加修饰符 show.sync</span><br><span class="line">    show: &#123;</span><br><span class="line">      type: Boolean,</span><br><span class="line">      default: false,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  data() &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      dial_loading: false,</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  watch: &#123;</span><br><span class="line">    show(value) &#123;</span><br><span class="line">      if (value) &#123;</span><br><span class="line">        console.log(&quot;监听到 show 的值有变化：&quot;, value);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    handleConfirm() &#123;</span><br><span class="line">      this.dial_loading = true;</span><br><span class="line"></span><br><span class="line">      // 模拟执行业务</span><br><span class="line">      setTimeout(() =&gt; &#123;</span><br><span class="line">        // 业务执行完关闭弹框</span><br><span class="line">        this.dial_loading = false;</span><br><span class="line">        this.$modal.msgSuccess(&quot;已确认&quot;);</span><br><span class="line">        this.$emit(&quot;confirm&quot;);</span><br><span class="line">        this.$emit(&quot;close&quot;);</span><br><span class="line">        this.$emit(&quot;update:show&quot;, false);</span><br><span class="line">        this.resetDialog();</span><br><span class="line">      &#125;, 3000);</span><br><span class="line">    &#125;,</span><br><span class="line">    handleClose() &#123;</span><br><span class="line">      this.$emit(&quot;close&quot;);</span><br><span class="line">      this.$emit(&quot;update:show&quot;, false);</span><br><span class="line">      this.resetDialog();</span><br><span class="line">    &#125;,</span><br><span class="line"></span><br><span class="line">    resetDialog() &#123;</span><br><span class="line">      // 重置弹框里面的数据，比如有表单、下拉框、筛选框等等</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><h2 id="Vue3-Element-Plus">Vue3 + Element Plus</h2><p>在 Vue3 + Element Plus 中，稍微有点变化，<em>sync</em> 修饰符没有了。</p><p>/src/views/xxx/index.vue</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></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;div&gt;这里可能有搜索栏、数据列表等...&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!-- 这里引入业务弹框组件 --&gt;</span><br><span class="line">    &lt;SelectDialog v-model=&quot;dialog.show&quot;&gt;&lt;/SelectDialog&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup&gt;</span><br><span class="line">import &#123; ref, reactive &#125; from &quot;vue&quot;;</span><br><span class="line">import SelectDialog from &quot;./select-dialog.vue&quot;;</span><br><span class="line"></span><br><span class="line">const dialog = reactive(&#123;</span><br><span class="line">  show: false,</span><br><span class="line">&#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>这个下拉弹框组件的封装方式如下：</p><p>/src/views/xxx/select-dialog.vue</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;el-dialog :model-value=&quot;modelValue&quot; :title=&quot;title&quot; @closed=&quot;handleClose&quot; width=&quot;60vw&quot; top=&quot;5vh&quot;&gt;</span><br><span class="line">      &lt;div&gt;这里是具体业务组件...&lt;/div&gt;</span><br><span class="line"></span><br><span class="line">      &lt;template #footer&gt;</span><br><span class="line">        &lt;div class=&quot;dialog-footer&quot;&gt;</span><br><span class="line">          &lt;el-button @click=&quot;handleClose&quot;&gt;关 闭&lt;/el-button&gt;</span><br><span class="line">          &lt;el-button @click=&quot;handleConfirm&quot; type=&quot;primary&quot;&gt;确 认&lt;/el-button&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">      &lt;/template&gt;</span><br><span class="line">    &lt;/el-dialog&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup&gt;</span><br><span class="line">import &#123; ref &#125; from &quot;vue&quot;;</span><br><span class="line"></span><br><span class="line">const props = defineProps(&#123;</span><br><span class="line">  modelValue: &#123;</span><br><span class="line">    type: Boolean,</span><br><span class="line">    default: false,</span><br><span class="line">  &#125;,</span><br><span class="line">  title: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &quot;XX下拉选择弹框&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">const emit = defineEmits([&quot;update:modelValue&quot;, &quot;confirm&quot;, &quot;close&quot;]);</span><br><span class="line"></span><br><span class="line">// const dial_loading = ref(false);</span><br><span class="line"></span><br><span class="line">// 关闭弹窗</span><br><span class="line">function handleClose() &#123;</span><br><span class="line">  emit(&quot;update:modelValue&quot;, false);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function handleConfirm() &#123;</span><br><span class="line">  // dial_loading.value = true;</span><br><span class="line"></span><br><span class="line">  // 模拟执行业务</span><br><span class="line">  setTimeout(() =&gt; &#123;</span><br><span class="line">    // 业务执行完关闭弹框</span><br><span class="line">    // dial_loading.value = false;</span><br><span class="line">    emit(&quot;confirm&quot;);</span><br><span class="line">    emit(&quot;close&quot;);</span><br><span class="line">    emit(&quot;update:modelValue&quot;, false);</span><br><span class="line">    resetDialog();</span><br><span class="line">  &#125;, 3000);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function resetDialog() &#123;</span><br><span class="line">  // 重置弹框里面的数据，比如有表单、下拉框、筛选框等等</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><h2 id="业务样例（Vue3）">业务样例（Vue3）</h2><p>写一个业务样例，方便开发时直接复制：</p><p>/src/api/role.api.js</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> request <span class="keyword">from</span> <span class="string">&quot;@/utils/request&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">RoleAPI</span> = &#123;</span><br><span class="line">  <span class="comment">// 查询列表</span></span><br><span class="line">  <span class="title function_">roleList</span>(<span class="params">query</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">      <span class="attr">url</span>: <span class="string">&#x27;/api/sys/roles&#x27;</span>,</span><br><span class="line">      <span class="attr">method</span>: <span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">      <span class="attr">params</span>: query</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 查询详细</span></span><br><span class="line">  <span class="title function_">roleInfo</span>(<span class="params">id</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">      <span class="attr">url</span>: <span class="string">&#x27;/api/sys/role/&#x27;</span> + id,</span><br><span class="line">      <span class="attr">method</span>: <span class="string">&#x27;get&#x27;</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 新增</span></span><br><span class="line">  <span class="title function_">roleAdd</span>(<span class="params">data</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">      <span class="attr">url</span>: <span class="string">&#x27;/api/sys/roles&#x27;</span>,</span><br><span class="line">      <span class="attr">method</span>: <span class="string">&#x27;post&#x27;</span>,</span><br><span class="line">      <span class="attr">data</span>: data</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 修改</span></span><br><span class="line">  <span class="title function_">roleUpdate</span>(<span class="params">data</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">      <span class="attr">url</span>: <span class="string">&#x27;/api/sys/roles&#x27;</span>,</span><br><span class="line">      <span class="attr">method</span>: <span class="string">&#x27;put&#x27;</span>,</span><br><span class="line">      <span class="attr">data</span>: data</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 删除</span></span><br><span class="line">  <span class="title function_">roleRemove</span>(<span class="params">id</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">      <span class="attr">url</span>: <span class="string">&#x27;/api/sys/role/&#x27;</span> + id,</span><br><span class="line">      <span class="attr">method</span>: <span class="string">&#x27;delete&#x27;</span></span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">RoleAPI</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>/src/views/system/role-add.vue</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;el-dialog :model-value=&quot;modelValue&quot; :title=&quot;title&quot; @closed=&quot;handleClose&quot; </span><br><span class="line">      :width=&quot;width&quot; :top=&quot;top&quot; :close-on-click-modal=&quot;false&quot; append-to-body&gt;</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &lt;el-form ref=&quot;form1Ref&quot; :model=&quot;form1&quot; :rules=&quot;form1Rules&quot; label-width=&quot;80px&quot;&gt;</span><br><span class="line">          &lt;el-form-item label=&quot;名称&quot; prop=&quot;name&quot;&gt;</span><br><span class="line">            &lt;el-input v-model=&quot;form1.name&quot; placeholder=&quot;请输入&quot; /&gt;</span><br><span class="line">          &lt;/el-form-item&gt;</span><br><span class="line">          &lt;el-form-item label=&quot;状态&quot; prop=&quot;status&quot;&gt;</span><br><span class="line">            &lt;el-radio-group v-model=&quot;form1.status&quot;&gt;</span><br><span class="line">              &lt;el-radio :label=&quot;1&quot;&gt;启用&lt;/el-radio&gt;</span><br><span class="line">              &lt;el-radio :label=&quot;0&quot;&gt;停用&lt;/el-radio&gt;</span><br><span class="line">            &lt;/el-radio-group&gt;</span><br><span class="line">          &lt;/el-form-item&gt;</span><br><span class="line">        &lt;/el-form&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line"></span><br><span class="line">      &lt;template #footer&gt;</span><br><span class="line">        &lt;div class=&quot;dialog-footer&quot;&gt;</span><br><span class="line">          &lt;el-button @click=&quot;handleClose&quot;&gt;取 消&lt;/el-button&gt;</span><br><span class="line">          &lt;el-button @click=&quot;handleConfirm&quot; type=&quot;primary&quot;&gt;确 认&lt;/el-button&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">      &lt;/template&gt;</span><br><span class="line">    &lt;/el-dialog&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup&gt;</span><br><span class="line">import &#123; reactive, ref, watch &#125; from &quot;vue&quot;;</span><br><span class="line">import RoleAPI from &#x27;@/api/role.api&#x27;;</span><br><span class="line"></span><br><span class="line">const &#123; proxy &#125; = getCurrentInstance();</span><br><span class="line"></span><br><span class="line">const props = defineProps(&#123;</span><br><span class="line">  modelValue: &#123;</span><br><span class="line">    type: Boolean,</span><br><span class="line">    default: false,</span><br><span class="line">  &#125;,</span><br><span class="line">  title: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &quot;XX下拉选择弹框&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">  width: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &quot;60vw&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">  top: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &quot;5vh&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">  id: &#123;</span><br><span class="line">    type: [String, Number],</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">const emit = defineEmits([&quot;update:modelValue&quot;, &quot;confirm&quot;, &quot;close&quot;]);</span><br><span class="line"></span><br><span class="line">// const dial_loading = ref(false);</span><br><span class="line"></span><br><span class="line">// 是否为更新模式</span><br><span class="line">const isUpdateMode = ref(false);</span><br><span class="line"></span><br><span class="line">const init_form1 = &#123;</span><br><span class="line">  name: &#x27;&#x27;,</span><br><span class="line">  status: 1</span><br><span class="line">&#125;;</span><br><span class="line">const form1Ref = ref();</span><br><span class="line">const form1 = reactive(&#123;</span><br><span class="line">  id: null,</span><br><span class="line">  name: &#x27;&#x27;,</span><br><span class="line">  status: 1</span><br><span class="line">&#125;);</span><br><span class="line">const form1Rules = reactive(&#123;</span><br><span class="line">  name: [</span><br><span class="line">    &#123; required: true, message: &#x27;名称不能为空&#x27;, trigger: &#x27;blur&#x27; &#125;,</span><br><span class="line">    // &#123; min: 3, max: 5, message: &#x27;Length should be 3 to 5&#x27;, trigger: &#x27;blur&#x27; &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">watch(() =&gt; props.modelValue, (value) =&gt; &#123;</span><br><span class="line">  if (value) &#123;</span><br><span class="line">    if (props.id) &#123;</span><br><span class="line">      form1.id = props.id;</span><br><span class="line">      isUpdateMode.value = true;</span><br><span class="line">      RoleAPI.roleInfo(props.id).then((res) =&gt; &#123;</span><br><span class="line">        Object.assign(form1, res.data);</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">      form1.id = null;</span><br><span class="line">      isUpdateMode.value = false;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">/** 重置弹框里面的数据，比如输入框、下拉框等等 */</span><br><span class="line">function resetDialog() &#123;</span><br><span class="line">  Object.assign(form1, init_form1);</span><br><span class="line">  form1Ref.value.resetFields();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/** 关闭弹窗 */</span><br><span class="line">function handleClose() &#123;</span><br><span class="line">  resetDialog();</span><br><span class="line">  emit(&quot;update:modelValue&quot;, false);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/** 确认并关闭 */</span><br><span class="line">function confirmClose() &#123;</span><br><span class="line">  resetDialog();</span><br><span class="line">  emit(&quot;confirm&quot;);</span><br><span class="line">  emit(&quot;close&quot;);</span><br><span class="line">  emit(&quot;update:modelValue&quot;, false);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/** 确认按钮 */</span><br><span class="line">function handleConfirm() &#123;</span><br><span class="line">  // 验证表单后再提交</span><br><span class="line">  form1Ref.value.validate(valid =&gt; &#123;</span><br><span class="line">    if (valid) &#123;</span><br><span class="line">      if (this.isUpdateMode) &#123; // 更新时</span><br><span class="line">        RoleAPI.roleUpdate(form1).then(() =&gt; &#123;</span><br><span class="line">          proxy.$modal.msgSuccess(&quot;修改成功&quot;);</span><br><span class="line">          confirmClose();</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125; else &#123; // 新增时</span><br><span class="line">        RoleAPI.roleAdd(form1).then(() =&gt; &#123;</span><br><span class="line">          proxy.$modal.msgSuccess(&quot;新增成功&quot;);</span><br><span class="line">          confirmClose();</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;在前端开发中，使用 vue + element 封装业务弹框组件是一个比较高频的操作。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Vuejs" scheme="https://www.guozhenyi.com/tags/vuejs/"/>
    
  </entry>
  
  <entry>
    <title>茶叶蛋的救赎</title>
    <link href="https://www.guozhenyi.com/post/2025/08/cha-ye-dan-de-jiu-shu.html"/>
    <id>https://www.guozhenyi.com/post/2025/08/cha-ye-dan-de-jiu-shu.html</id>
    <published>2025-08-29T11:20:00.000Z</published>
    <updated>2026-01-07T02:06:26.780Z</updated>
    
    <content type="html"><![CDATA[<p>早上在常买早餐的那家店，买了两个茶叶蛋做早餐，不出意外的，出意外了，窜了。。。</p><span id="more"></span><p>其实对于茶叶蛋，本人比较抵触，被它伤害过好几次了，奈何不长教训诶。</p><h2 id="起">起</h2><p>起因是，每天都吃那家店的米糕，有点吃腻了，想换一下，鬼使神差的就买了两个茶叶蛋。</p><p>之前没在他们家买过茶叶蛋，因此没有啥防备心理。</p><p>拿到茶叶蛋闻了一下，好像也没啥怪味，也就几口下肚做早餐了。</p><h2 id="转">转</h2><p>起初都没啥事，等中午吃完饭，好家伙，开始串稀，在厕所蹲了大半个小时，腿都蹲麻了。</p><p>不用怀疑，直接就能锁定是他们家的茶叶蛋有问题。</p><p>为啥这么笃定是他们家茶叶蛋有问题呢。</p><p>且听吾细细道来。</p><p>本人吃东西都很有规律，这段时间，早餐一直吃他们家的米糕和绿豆汤。</p><p>后来发现绿豆汤里面添加剂太多了，就不再购买，只买米糕做早餐。</p><p>偶尔买瓶营养快线搭配着喝，这都没有问题，未出现串稀的情况。</p><p>他们家大多是油炸食品，本人不太喜欢大多数油炸食品，因此选择的食物就不多了。</p><p>前两天还在想自己煮鸡蛋当早餐，但是一直没买生鸡蛋，就搁置了。</p><p>于是，今天早上，就想着买两个茶叶蛋做早餐，还顺便去零食铺买了一瓶营养快线，碰一碰支付，减了2元【笑】。</p><p>中午吃饭，也是延续前几天的习惯，没有变换口味。</p><p>那么，引起串稀的原因，那不就呼之欲出了。</p><p>还有一个细节也可以间接论证茶叶蛋有问题，本人发现这两个茶叶蛋不太好剥，壳子和那层膜黏上了。</p><p>之前吃的新鲜茶叶蛋，都是光滑光滑的，蛋壳很好剥开。</p><p>事后反思，可能就是这个茶叶蛋放太久了，也可能隔N夜。</p><h2 id="承">承</h2><p>细数那些串稀的日子，诶，都是泪。</p><h3 id="第一家：早阳包子铺">第一家：早阳包子铺</h3><p>这家卷饼店的上一个店主，开的是早阳包子铺，加盟的，开始卖包子、豆浆等等，估计准备大干一场，开业那几天，有三四个人在店里忙活。</p><p>也许是生意确实不咋地，没过几天，店里只剩两个人，再过了一段时间，就只剩一个大妈守店了。</p><p>他们家的包子，都是预制的，所谓的由中央厨房配送过来，印象中好像买过一次，就再也没买过了，味道已经记不清，行动已经给了答案。</p><p>这个包子铺，开始卖的豆浆也是预制的，买过，非常难喝，后来有个女生说你这个豆浆肯定没人买，现在都需要现磨豆浆，巴拉…</p><p>后来店主也发现生意确实不好，就去买了豆浆机，豆浆粉，开始卖“现磨”豆浆，买的人就稍微多了一点。</p><p>哦，吾在他家主要就是买茶叶蛋和豆浆，直到有一天，吃了他们家的茶叶蛋，串稀了…</p><p>想了几天，有点想不通，就去跟那个老板说了句：“我前几天吃了你家的茶叶蛋拉肚子了，是不是没卖完的放了好久还在卖…”</p><p>大妈还比较镇定，赶紧说：“我们都是卖的新鲜的，茶叶蛋要提前煮…”</p><p>不承认呗，反正吾也没准备找他的麻烦，就是好心提醒一下。</p><p>大概过了个把月，就看到该店贴了个告示：带技术转让。只贴了一两天，发现没有人接盘，直接闭店搬空了。</p><p>这个早阳包子铺，前后开了不到一年就倒闭了。</p><p>在这个早阳包子铺之前，其实还开过另一个包子铺，偏南方口味，挺适合吾，每天都买，但是也是一天一天看到他家的包子越来越小。</p><p>那个包子铺的包子是用酵母发酵过的，跟南方的包子差不多。不像其他北方的包子，死面包子，咽不下【笑cry】。</p><p>直到某一天，吾去买包子的时候，发现人去楼空。。。</p><p>当时还纳闷了好半天，因为吾昨天还在他家买了包子，没想到在毫无征兆的情况下就关门了。</p><p>他关门以后，没过几天，早阳包子铺就开业了。</p><h3 id="第二家：某个卤鸭烤鸭店">第二家：某个卤鸭烤鸭店</h3><p>去年夏秋之际，在这个早阳包子铺的旁边，开了一家卤味店，忘记店名了，有整只的烤鸭卖。</p><p>之前都只是经过，从来没买，直到秋冬的某一天，天气微凉，经过该店时，过去瞧了瞧，买了一只烤鸭。</p><p>买完，那个店员说有点凉了，就放微波炉加热了一下。</p><p>好家伙，回去吃的时候就发现，有点变味，估计是放了好多天了。</p><p>想着问题不大，就吃了一些，没有意外，这次串稀串了一天。。。</p><p>其实变味不太明显，只是本人嗅觉很发达，能够敏锐感知到这烤鸭至少放了三天以上。</p><p>如果是一直冷冻，其实不会这么快就坏。</p><p>但是，要是白天拿出来摆在桌子上，解冻了，没卖掉，晚上再拿去冷冻，两三天就会变质，外表还看不出来。</p><p>这家店死的更快，没过几天，就倒闭了。</p><p>店员不是老板，是拿工资的，明显感觉不上心，也不会做生意，还听见她抱怨店里没有暖气。</p><h2 id="合">合</h2><p>北方的美食，真是一言难尽啊。</p><p>貌似北方在吃的方面，不怎么上心。</p><p>想吃包子吧，大多数都是死面包子，难以下咽。</p><p>油炸食物又不想吃，面条倒是多，吃几次就腻得不行。</p><p>各种面食，也是死面居多，真不太好吃。</p><p>目前发现做包子做得好的就庆丰包子和一个小胖包子，皮薄馅足，包子比较小，更像是南方的大号小笼包。</p><p>经过几次教训，现在是真不敢随便吃茶叶蛋了。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;早上在常买早餐的那家店，买了两个茶叶蛋做早餐，不出意外的，出意外了，窜了。。。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>鲜为人知的城镇杀猪盘</title>
    <link href="https://www.guozhenyi.com/post/2025/07/cheng-zhen-sha-zhu-pan.html"/>
    <id>https://www.guozhenyi.com/post/2025/07/cheng-zhen-sha-zhu-pan.html</id>
    <published>2025-07-22T14:18:18.000Z</published>
    <updated>2026-03-23T03:16:34.505Z</updated>
    
    <content type="html"><![CDATA[<p>社会充满尔虞我诈，每当有人暴富，总会被各种陷阱洗劫一空，打回原形，能逃过此劫的人屈指可数。</p><span id="more"></span><h2 id="故事">故事</h2><p>不信，我先说三个真实的故事：</p><h3 id="故事一">故事一</h3><p>有个堂哥，80后，高中辍学，靠修电脑、下工地等打拼多年，生活还算过得去。大概在一三年吧，抓住镇上基建热潮，拿积蓄开了个水泥厂，靠水泥厂赚得第一桶金，生活逐渐富足。听说开始买了个十来万的代步车，后来为了谈生意撑场面，又买了辆几十万的车，具体就不得而知了，但是从这里也能看出来这位堂哥确实是挣到钱了。</p><p>堂哥的妻子，我只有缘见过一两次，当时看她体态丰盈，估计是生活富足后，有点发福了罢。堂哥的妻子也不用上班，在家照顾两个孩子，偶尔帮忙照看生意，日子肯定是很安逸的。</p><p>后来，堂哥的妻子被牌友拉去打麻将，起初只是图个热闹，几次赢钱后上瘾，渐渐沉迷其中。牌友们不断恭维、诱导，赌注越下越大。最后，她不但把家底输光了，连厂房都给输了拿去抵债，这还不算完，还欠下了巨额赌债。</p><p>堂哥也跟着遭罪，多年奋斗的成果毁于一旦，一切归零，还要跟着还赌债，车子也拿去卖了还债。</p><p>听长辈们说，欠的赌债，利滚利，利息都还不完…</p><h3 id="故事二">故事二</h3><p>有个表妹，也是初中辍学吧，结识了她老公，两人认识的早，所以感情深，后来就结婚生子了。</p><p>表妹靠着在县城里开了个服装店卖衣服，逐渐也挣到了钱，买了车，贷款在县城买了一套房，生活富余。</p><p>只要按照这个轨迹发展，他们不说大富大贵，起码衣食无忧。</p><p>可惜啊，表妹的老公在结婚头几年，还老老实实去上班挣钱，后来兴许是看到表妹开服装店能挣到钱，不太需要他挣钱养家。</p><p>他就逐渐的飘了，开始不务正业，到处鬼混，拈花惹草。</p><p>有人劝表妹跟他离，表妹看在两个孩子的份上，拒绝了。</p><p>后来，表妹的老公更飘了，也是认识了几个牌友，开始去打牌。</p><p>不出意外，出意外了，在赌桌上，他不但把自家才买的房子给输掉，还把他表弟的房子也输掉了。</p><p>结局不用说，肯定不太美好，表妹一家又开始租房住，从头再来…</p><h3 id="故事三">故事三</h3><p>三舅的儿子，比我小不到一岁，其实我跟他没啥交集。只是前几年听我妈跟我说了他的事。</p><p>同样的，不好好上班，到处鬼混，也是去打牌，说是输了十几万。</p><p>后来三舅到处凑钱，给他还完了赌债。</p><p>没过多久，又出去打牌，不出意外，又欠了十几二十万的赌债。</p><p>这次三舅的亲家都不乐意了，说这姑爷要是再去赌博，就让闺女跟他离婚，各过各的。</p><p>后来嘛，好像是女方家也帮忙凑了些钱，给他把赌债还了。</p><p>之后的事，我就不太清楚了。</p><h2 id="分析">分析</h2><p>听完这三个发生在我身边的故事，不知道你有什么看法。</p><p>先不说他们自身的问题，我们来找一找三个故事的共性。</p><p>其一，家里发了财，有点小钱了。（暴富）</p><p>其二，挣钱的人，勤勤恳恳；不挣钱的另一半，无所事事。（飘了）</p><p>其三，被人抓住弱点，做局，对他们的财富洗劫一空。（杀猪盘）</p><p>明白了吧，这些隐藏在城市、乡镇的“猎手”，最喜欢找那些暴发户下手。</p><p>他们通过多人配合做局，还可以谋划多年，博取你的信任，然后榨干你的价值，掳走你的财富。</p><p>那这些“猎手”，到底是哪些人构成的呢，这就需要自己去多想想了。</p><h2 id="总结">总结</h2><p>那么，我们普通人，应该如何避免陷入城市“猎手”的杀猪盘里呢？</p><p>我总结了这么几点：</p><ol><li><p><strong>财不外露。</strong></p><p>管住自己的嘴，家里的掌财者，一定不要给任何人说自己存了多少钱，包括家里嘴巴漏风的人。</p></li><li><p><strong>培训家人。</strong></p><p>多给家里人培训，让他们不要到处炫耀，低调做人，避免让人眼红，给你家人设圈套。</p></li><li><p><strong>去上班。</strong></p><p>家里哪怕衣食无忧，也要去上班，不要无所事事，游手好闲。一旦你游手好闲，就可能落入别人给你精心设下的赌博陷阱。</p></li><li><p><strong>培养爱好。</strong></p><p>钓鱼、打游戏、跑步、健身、跳舞、手工、烹饪，培养一些不跟人打交道的爱好，充实自己。内心富足，才不会被小人抓住漏洞，攫取你的财富。</p></li></ol><p>说到这，我陷入了深深的思考，为啥我就没遇到过赌博陷阱呢。</p><p>思衬良久，悲伤和苦涩逐渐浮上心头，或许，是我穷的太稳定了吧！！！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;社会充满尔虞我诈，每当有人暴富，总会被各种陷阱洗劫一空，打回原形，能逃过此劫的人屈指可数。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>繁忙的六月</title>
    <link href="https://www.guozhenyi.com/post/2025/06/fan-mang-de-liu-yue.html"/>
    <id>https://www.guozhenyi.com/post/2025/06/fan-mang-de-liu-yue.html</id>
    <published>2025-06-26T14:11:11.000Z</published>
    <updated>2025-07-18T09:37:50.234Z</updated>
    
    <content type="html"><![CDATA[<p>六月，阿文迎来了家里的第二个孩子。</p><p>在6月6号接到妻子电话时，阿文在公司请了陪产假，匆匆买了高铁票，踏上了返回武汉的旅程。</p><span id="more"></span><h2 id="为孩子准备">为孩子准备</h2><p>因为是第二个孩子，阿文没有那么慌张，毕竟经验摆在那儿了，按照既定流程走就行。</p><p>经过社会磨练多年，阿文做事，喜欢谋定而后动，也喜欢规划和列清单。</p><p>在五月份的时候，阿文就跟妻子说，把孩子用品列个清单，按清单购买，避免遗漏。</p><p>经过两人讨论和补充，清单已经很全面了，之后阿文就陆陆续续买好了生孩子的必需品。</p><p>首先是待产包，里面物品一应俱全，虽然有些用不上，不过不影响大局。</p><p>其次，奶瓶，买SS奶嘴，最小流速的，贝亲有一款49元，号称人生第一款奶瓶，对，就那个就行。</p><p>奶粉，选1段，老大之前喝A2，现在想想，没啥必要折腾了，直接选飞鹤星飞帆就OK。</p><p>尿不湿，没有多犹豫，直接选好奇铂金装NB型，84片的先搞两包，老大也用这个，等孩子大了可以换金装、银装等更便宜的。</p><p>维生素AD，出生以后，每天一滴，助力孩子发育，老大都用到了四五岁，老二也必须用。</p><p>妙思乐护臀膏、润肤乳、面霜、沐浴露，全买上，都是老大用过来的。</p><p>爽身粉，备上，大宝之前买的，还有个没拆封，可以直接用。</p><p>婴儿衣服，贴身内衣，要柔软，2-3套，医院就提醒宝妈宝爸准备了。</p><p>浴巾，纯棉的，至少2条，我备了3条，加上亲戚朋友送了些，就很够了。</p><p>贴身包被 1-2 个薄款，把握不好换尿不湿的时机，可以多准备几个，哈哈。</p><p>外层包被 1-2 个。</p><p>小帽子、小袜子，按需购买。</p><h2 id="为宝妈准备">为宝妈准备</h2><p>产妇坐月子期间，需要囤一箱卫生巾，直接买医用级的那种卫生巾就行。</p><p>买了艾草叶，每天煮水给宝妈擦身体，比温水更好，抖音学的。</p><p>其他的，待产包里基本都有了。</p><p>（未完待续…）</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;六月，阿文迎来了家里的第二个孩子。&lt;/p&gt;
&lt;p&gt;在6月6号接到妻子电话时，阿文在公司请了陪产假，匆匆买了高铁票，踏上了返回武汉的旅程。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>神奇的重庆北站</title>
    <link href="https://www.guozhenyi.com/post/2025/05/shen-qi-de-chong-qing-bei.html"/>
    <id>https://www.guozhenyi.com/post/2025/05/shen-qi-de-chong-qing-bei.html</id>
    <published>2025-05-16T13:29:42.000Z</published>
    <updated>2025-05-20T09:41:55.415Z</updated>
    
    <content type="html"><![CDATA[<p>小巴是个重庆人，自从十几年前，从重庆的山沟沟外出打拼以后，就很少有时间回重庆了。</p><span id="more"></span><h2 id="起源">起源</h2><p>2024 年秋，由于家庭原因，小巴需要接父母到武汉帮忙一段时间。</p><p>小巴没有多想，在铁路 12306 APP 为父母买好了“重庆北-武汉”的火车票。</p><p><img src="/uploads/2025/05/16/chongqingbei-001.webp" alt="chongqingbei-001"></p><p>鉴于小巴的老家，在重庆的四环外，坐大巴到市区需要两个小时，所以小巴给父母买的上午 11 点左右的火车票。</p><p>等到了乘火车的那一天，小巴跟父母说先坐大巴到龙头寺（长途）汽车站，然后往北边走，走到北站北广场…</p><p>后来，小巴的父母说他们没在龙头寺汽车站诶，在南广场汽车站。</p><p>小巴有点懵，说你们坐错汽车了吧，只有龙头寺汽车站和龙头寺汽车北站。</p><p>龙头寺汽车北站就在重庆北站北广场旁边，坐火车很方便，但是小巴家乡好像没啥大巴车去那个站。</p><p>巴拉巴拉，说了一通，小巴也不知道他父母听懂了没，反正最后是他们自己问路，跌跌撞撞赶到了重庆北站北广场，进了候车室。</p><p>经过这件事以后，小巴心里直犯迷糊，难道记忆错乱了。</p><p>小巴对重庆的印象可能还停留在十年前，对于汽车站、火车站，也是十年前的记忆。</p><p>于是小巴就开始刨根究底的查资料，果然，对于重庆北站犯迷糊的远不止小巴这个重庆人。</p><p>外地去重庆旅游的人也对重庆北站的地名直呼“卧槽”。</p><p>先来个小巴查到的绕口令：</p><blockquote><p>到重庆北站南广场的乘客，请在重庆北站下车；</p><p>到重庆北站北广场的乘客，请在龙头寺站下车；</p><p>到龙头寺汽车站的乘客，请在重庆北站下车；</p><p>到龙头寺汽车北站的乘客，请在龙头寺站下车。</p></blockquote><p>啧啧啧，小巴试着念了一下，确实有点绕。</p><p>这一段绕口令，直接勾起了小巴往昔的记忆。</p><p>大概十五年前，小巴第一次出远门，就是坐汽车到的龙头寺汽车站，然后准备从重庆北站南广场穿到北广场去坐火车。</p><p><img src="/uploads/2025/05/16/chongqingbei-002.webp" alt="chongqingbei-002"></p><p>幸亏在走到南广场时，听到大喇叭不停的喊：“去北广场的乘客，请上摆渡车，南广场和北广场不互通…”</p><p>小巴很庆幸听到了广播，做摆渡车及时赶到了北广场，否则就赶不上火车了。</p><h2 id="真相">真相</h2><p>小巴为了搞清楚来龙去脉，专门查了重庆北站和龙头寺汽车站的过往。</p><p>最后发现，现在只有重庆北站南广场汽车站和重庆北站北广场汽车站了。</p><p>他们的历史名称如下：</p><p><strong>重庆北站南广场汽车站</strong></p><p>原名：龙头寺长途汽车站（位于重庆北站南广场旁边）</p><p>2016 年 1 月改名为：龙头寺汽车南站</p><p>2016 年 4 月改名为：重庆北站南广场汽车站</p><p><strong>重庆北站北广场汽车站</strong></p><p>原名：龙头寺汽车北站（位于重庆北站北广场）</p><p>2016 年 1 月投入使用。</p><p>2016 年 4 月改名为：重庆北站北广场汽车站</p><h2 id="了然">了然</h2><p>原来如此，一切就合情合理，解释得通了。</p><p>汽车站改名了呗，按照南北位置，改得更贴合实际了。</p><p>搜到一张图，更加直观展示改名前后的变化：</p><p><img src="/uploads/2025/05/16/chongqingbei-003.webp" alt="chongqingbei-003"></p><h2 id="总结">总结</h2><p>小巴查完以后，也觉得增长了见识，对家乡的了解也更多了一点。</p><p>或许是，小巴离开家乡太久，以往心心念念的丁家坡洋芋都已经记不清味道。</p><p>重庆的火锅这么独特，为啥不提及呢。</p><p>因为年少时的小巴，哪能随随便便下馆子吃火锅呀。</p><p>成长伴随着舍弃，有舍有得，怎么可能既要又要还要呢。</p><p>小巴也不知道，再过多少年后，家乡会成为小巴记忆中的一个符号，变成那个“熟悉的陌生城市”。</p><h2 id="名词释义">名词释义</h2><p>小巴：一个离开家乡许久的漂泊者。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;小巴是个重庆人，自从十几年前，从重庆的山沟沟外出打拼以后，就很少有时间回重庆了。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>什么 TM 是 99 新</title>
    <link href="https://www.guozhenyi.com/post/2025/05/13/shen-me-shi-99-xin.html"/>
    <id>https://www.guozhenyi.com/post/2025/05/13/shen-me-shi-99-xin.html</id>
    <published>2025-05-13T14:00:26.000Z</published>
    <updated>2025-05-20T07:29:41.020Z</updated>
    
    <content type="html"><![CDATA[<p>如题，小菜很想知道什么是 99 新，什么 TM 是 99 新。</p><span id="more"></span><h2 id="前言">前言</h2><p>小菜的手机 Redmi K40 Gaming 用了三年了，有点卡，并且 256g 的存储已经无法承载《原神》、《崩铁》、《鸣潮》、《王者荣耀》和微信这些巨无霸应用的数据了。</p><p>看着所剩无几的空间，小菜只能把之前拍的照片和视频拷贝到了电脑里，才勉强腾出了二三十个 G 的存储空间。</p><p>既然这样，那就换手机吧。</p><p>小菜依然记得，给家人买过一款小米 Redmi Note12 Turbo，12+512g，不打游戏的情况下，还挺好用的。</p><p>不过据小菜了解，后续 Redmi Note 13 系列没有 Turbo 了，已经全面改成了独立系列：Redmi Turbo 系列。</p><p>并且后续机型为小米 Redmi Turbo 3、Redmi Turbo 4、Redmi Turbo 4 Pro。</p><p>众所周知，小菜对联发科的 CPU 深恶痛绝，被伤害得很深。</p><p>早年间第一款使用的联发科 CPU 的手机，红米 Note2，wifi 断流，至今耿耿于怀。</p><p>而今小菜用的 Redmi K40 Gaming 采用联发科天玑 1200 CPU，屏幕断触、断触、断触…</p><p>小菜已经忍了它三年了！！！</p><p>通过复盘，小菜不禁陷入深深的思考，当初在拿到 Redmi K40 Gaming，知道它断触时，为啥没有找小米售后。</p><p>其实小菜当初有过冲动去找小米售后，但是这破手机，断触不好复现啊…</p><p>可能几天，也可能几个月才会断触一次，完全没规律，小菜也没办法举证它有断触的问题。</p><p>而且它还会死机、黑屏、无响应，遇到过几次，也没法复现。</p><p>好多次在打游戏时，上滑没法回到桌面，游戏里按钮无响应，错过好多次“五杀”的机会（手动滑稽）。</p><h2 id="碎碎念">碎碎念</h2><p>小菜非常喜欢小屏手机，并且青睐直面屏。</p><p>小米 12 是小屏，但它是曲面屏。</p><p>小米 13 是小屏，直面屏。</p><p>小米 14 是小屏，微曲面屏。</p><p>因此，综合下来，小菜最喜欢的是小米 13，可惜发售时间太长，没有新机了吧。</p><p>看过某鱼二手，好像磕碰挺多，惨不忍睹，实在选不到啥成色好的机子。</p><p>退而求其次，就想选择 Redmi Turbo 系列。</p><p>Redmi Turbo 4 是联发科 CPU，直接 PASS，再买联发科 CPU 手机小菜是狗…</p><p>Redmi Turbo 4 Pro 刚发售，是超大屏，厌恶，并且超过预算了，PASS。</p><p>Redmi Turbo 3 16+512g 官网已经没货了，某东好像还有点库存。</p><h2 id="购机">购机</h2><p>于是，小菜在某东 APP 上逛了逛，看了一下 Redmi Turbo 3，16+512g 白色 2099，还有货。</p><p>在往下翻时，看到一个某东拍拍二手自营，Turbo 3 99 新，只要 14xx 元。</p><p><img src="/uploads/2025/05/13/turbo3-001.webp" alt="turbo3-001"></p><p>短暂考虑后，小菜决定下单试试，搏一搏，单车变摩托，省 600 多拿去喝奶茶不香么。</p><p>当然了，不止有 99 新，还有 95 新，9 新等。</p><p>为了不扯皮，也不差那 95 新和 99 新之间那点差价，小菜就果断下单 99 新的了。</p><p><img src="/uploads/2025/05/13/turbo3-002.webp" alt="turbo3-002"></p><p>还有质检报告哦：</p><p><img src="/uploads/2025/05/13/turbo3-003.webp" alt="turbo3-003"></p><p>下完单，怀着愉快的心情，小菜等待了 3 天。</p><p>快递通知小菜去取件，小菜就迫不及待去驿站拿到了热乎的 99 新 Redmi Turbo 3 16+512g 青刃。</p><p><img src="/uploads/2025/05/13/turbo3-004.webp" alt="turbo3-004"></p><p><img src="/uploads/2025/05/13/turbo3-005.webp" alt="turbo3-005"></p><p>鉴于以往的经历，怕被坑，小菜就录了个开箱视频。</p><p>在打开手机盒，拿出手机的那一刻，小菜以为自己眼睛花了，怎么，感觉这个手机屏幕是弯的…</p><p>为了证明不是小菜眼花，就把手机屏幕贴在手机盒子上，对着灯，看了一下，哇塞：一线天耶~</p><p><img src="/uploads/2025/05/13/turbo3-006.webp" alt="turbo3-006"></p><p>经过几次反复观摩后，发现手机确实是弯的。</p><h2 id="退货">退货</h2><p>这次小菜决定不再忍了，果断去某东 APP 申请售后，提交开箱视频证据，申请退货退款。</p><p>某东客服看了视频后，也是果断滑跪，同意了退货退款。</p><h2 id="复盘">复盘</h2><p>既然已经退货退款，那么可以复盘了。</p><p>小菜把质检报告打开仔细看了一下，8 项外观检测里，就包含机身弯曲检测呀。</p><p><img src="/uploads/2025/05/13/turbo3-007.webp" alt="turbo3-007"></p><p>质检员难道是斗鸡眼，看不出来机身弯曲么。</p><p>小菜作为一个普通人，拿到手机的一瞬间都能看出手机是弯的，出质检报告的质检员为啥看不出来。</p><p>这个问题，小菜没有答案，只能陷入深深的思考。</p><h2 id="总结">总结</h2><p>本来对新机满怀期待，经过这么一折腾后，小菜已经浇灭了心中的火焰。</p><p>把此次购机经历写出来，没有 diss 任何商家的意思，只是充满了遗憾。</p><p>建立信任很难，打破信任却只在一瞬间。</p><p>对于这次购机经历，小菜对某东拍拍二手的 99 新已经不再信任。</p><p>小菜也不妄自揣度商家为什么会发与质检不符的商品去毁掉自己口碑。</p><p>最后，小菜只能无奈的仰天问一句：到底什么 TM 是 99 新，啊。</p><h2 id="名词释义">名词释义</h2><p>小菜：一个或一群不想被定义的菜鸟。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;如题，小菜很想知道什么是 99 新，什么 TM 是 99 新。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>盘点那些让人爆笑的中式英语翻译</title>
    <link href="https://www.guozhenyi.com/post/2025/04/24/hilarious-chinglish-translation.html"/>
    <id>https://www.guozhenyi.com/post/2025/04/24/hilarious-chinglish-translation.html</id>
    <published>2025-04-24T13:18:18.000Z</published>
    <updated>2025-05-21T06:31:16.365Z</updated>
    
    <content type="html"><![CDATA[<p>盘点网上那些让人捧腹的神级翻译。</p><span id="more"></span><p>God is a girl ------------ 天道不公</p><p>God is a girl ------------ 苍天有眼</p><p>MLGB first ------------ 丑话说在前头</p><p>No JJ Book ------------ 葵花宝典</p><p>Family⁹=0 ------------ 诛灭九族</p><p>Jerry ------------ 鼠辈</p><p>I’m a gay ------------ 寡人不近女色</p><p>Find east NB man want to be the CEO ------------ 早悉东方不败的不轨之心</p><p>Big JJ man  all like this ------------ 大丈夫当如是</p><p>God damn BMW ------------ 弼马温</p><p>IQ≈10086  HP≈10010 ------------ 智勇双全</p><p>See him jj be JJ ------------ 看着他一步步成长</p><p>Jack, slow fuck ------------ 捷克斯洛伐克</p><p>One, two, three go ------------ 三思而后行</p><p>0.5 yes 0.5 no ------------ 半信半疑</p><p>Panasonic ask the boy ------------ 松下问童子</p><p>You can you up, no can no BB ------------ 你行你上，不行别BB</p><p>VIP dog ------------ 贵宾犬</p><p>you dida dida me I huala huala you ------------ 滴水之恩涌泉相报</p><p>WiFi baby ------------ 天线宝宝</p><p>Beijing gaga ------------ 北京烤鸭</p><p>Half yes half no ------------ 半推半就</p><p>JJ boom fly in the sky ------------ 碉堡了</p><p>Ant on hot pot ------------ 热锅上的蚂蚁</p><p>People mountain people sea ------------ 人山人海</p><p>Husband and wife lung slice ------------ 夫妻肺片</p><p>注：以上内容来自于网络。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;盘点网上那些让人捧腹的神级翻译。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>杨天才传</title>
    <link href="https://www.guozhenyi.com/post/2025/04/13/chinese-teacher-yang-tian-cai.html"/>
    <id>https://www.guozhenyi.com/post/2025/04/13/chinese-teacher-yang-tian-cai.html</id>
    <published>2025-04-13T02:22:19.000Z</published>
    <updated>2025-04-22T01:55:38.560Z</updated>
    
    <content type="html"><![CDATA[<p>他真的可以称之为天才，语文教学被他拿捏得炉火纯青。</p><span id="more"></span><h2 id="缘起">缘起</h2><p>2005 年某月，二年级五班迎来了一位新的语文老师。他高高瘦瘦，穿着西装，打着领带，偏瘦的身材无法撑起西装，给人一种弱不禁风的感觉。但是他的眼神既坚定又犀利，仿佛能洞穿人心。</p><p>走上讲台，他徐徐说道：“同学们好，我是你们新的语文老师，… 你们放心，我能把本班语文带到全年级第一，这点你们不用担心…”</p><p>台下的同学们都惊呆了，开始议论纷纷，心想这位老师挺狂啊，刚来就说大话了。到时候要是本班语文没冲到年级第一，不怕羞愧的无地自容么…</p><p>话说为啥二年级五班会迎来新的语文老师呢，这还得从第一位语文老师说起。</p><p>在一年级时，五班的语文老师是一位非常漂亮的美女老师。上课认真负责，平时穿着打扮也很时尚。不知何故，在二年级时，被调走了…</p><p>于是学校安排了另外一位老师来教五班的语文课。这位老师也是女性，穿着打扮就比较普通了。也许是这位老师身材娇小，气场不够强大，亦或者同学们太调皮，不买这位老师的账。</p><p>在几次上课后，某一次上课时，不知道被哪个调皮的同学，带头起哄，把语文老师轰走了…走了…</p><p>具体经过不甚清楚，只记得通过班主任沟通，得知同学们对这位语文老师的教学不满意，最后校长知道了此事，就答应给我们换一位语文老师。</p><p>于是，前文所述的语文老师就闪亮登场了。</p><p>他的名字叫杨天才，男，高高瘦瘦，职称高级教师。</p><h2 id="传奇">传奇</h2><p>二年级五班的班主任是英语老师，非常认真负责，此处暂且不表，后续有机会专门著述。</p><p>当这位杨天才老师任教二年级五班语文以后，本班的“副”班主任就是语文老师了，没事就喜欢在班里溜达。</p><p>为什么溜达呢，因为他很闲…</p><p>不是贬义词，是真的闲。</p><p>他的教学模式也超出常规，大致如下。</p><p>场景一：</p><blockquote><p>今天要学一篇古文，上课时，老师说：“现在花 20 分钟，同学们把这篇古文熟悉一下”。（小声阅读）</p></blockquote><blockquote><p>20 分钟后，“好，停。我大概讲一下这篇古文里面的难点…”</p></blockquote><blockquote><p>再 10 分钟后，“还有一点时间，同学们再读一读课文…”（小声阅读）</p></blockquote><p>场景二：</p><blockquote><p>“今天语文课，所有同学拿好自己的书，我们去教室外（操场）读书去…”</p></blockquote><blockquote><p>所有同学带着书本，在操场找一个位置，或坐、或立，开始卖力的读书，小声阅读。</p></blockquote><p>场景三：</p><blockquote><p>“嗯，这节课自学，请同学们翻到课本第 xx 页，开始阅读吧…”</p></blockquote><blockquote><p>杨天才老师背负双手，在教室里来回踱步…</p></blockquote><p>作为学生，对他的教学，并无任何不适，反而太轻松了。</p><p>这位语文老师不喜欢布置作业，抓的最紧的就是阅读。</p><p>“读书百遍，其义自现。”这句话的含金量还在上升，并且被他运用得炉火纯青。</p><p>他鼓励同学们买课外杂志阅读，比如当时很火的《读者》《意林》等等。</p><p>学校每学期都会组织多场全年级统一的考试，考场座位混排，防止作弊。</p><p>随着几场考试下来，本班语文成绩一飞冲天，登顶年级第一。</p><p>当时同学们也很迷糊，本班语文成全年级第一了？？？</p><p>他有什么魔力，他做到了，他怎么做到的，他干了什么…</p><p>然后，杨天才老师依旧很淡定。在教室监督学生阅读时，依旧闲庭信步，毫无波澜。</p><p>他创造的奇迹，惊艳了同年级的所有语文老师。</p><p>后续，学校组织了多次其他班级的语文老师来本班听课。只有这个时候，本班杨天才老师才会稍微认真一点，该备课备课。</p><p>并且一改往日风格，开始一本正经的上课，整堂课没有了自由阅读时间。</p><p>我想，其他语文老师一堂课听下来，肯定心里带着不服：也不过如此嘛，无甚特别之处。</p><p>殊不知，天才型选手，从来都不按套路出牌。</p><p>有的教学方式，在学校看来是离经叛道，但是教学质量却出奇的高。</p><p>杨天才老师即使有心告诉各位老师他的教学方法，如果不知其所以然，那也只是邯郸学步罢了。</p><p>从那以后，二年级五班语文成绩一直很稳定，稳定在第一名，无法撼动。</p><p>每当班主任英语老师不在时，总能看到高高瘦瘦的语文老师溜进班里监督同学们学习。</p><p>杨天才老师依然喜欢背负双手，在教室里来回踱步…</p><h2 id="回忆">回忆</h2><p>自从中学毕业后，离开了家乡，也没有回去探望过一位老师。</p><p>十几年后的某一天，在亲戚家吃饭，遇到一位母校的年轻老师，就偶然寻问了几句：“杨天才老师、杨腾波老师还在学校吗？”</p><p>老师回答我说：“他们还在，还在搭档教学呢…”</p><p>对此，我都能想象出一帧一帧的画面，他们可能依然在续写着传奇。</p><p>匆匆二十多年过去了，回家乡的次数屈指可数。</p><p>大多数也是放假之时，老师们不在学校，更加不可能有机会能拜访昔日的各位老师了。</p><p>祝愿他们一切都好。</p><h2 id="后记">后记</h2><p>本篇致我人生中最尊敬的语文老师：杨天才。</p><p>春风化雨育桃李，愿您身体健康，桃李铺满园。</p><p>三尺讲台一颗心，愿您的光芒如星辰般永远闪亮。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;他真的可以称之为天才，语文教学被他拿捏得炉火纯青。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>使用 Algolia DocSearch 实现站内全文检索</title>
    <link href="https://www.guozhenyi.com/post/2025/04/02/algolia-docsearch-full-text-search.html"/>
    <id>https://www.guozhenyi.com/post/2025/04/02/algolia-docsearch-full-text-search.html</id>
    <published>2025-04-02T11:01:10.000Z</published>
    <updated>2025-05-20T07:29:41.019Z</updated>
    
    <content type="html"><![CDATA[<p>本博客站点的搜索框默认是使用 Google 搜索引擎去搜索网站内容，这里有两个问题：一是由于政策原因，国内无法访问 Google 搜索，导致此搜索功能无效；二是 Google 搜索对本站点内容的收录可能不及时、不全面，导致搜不到某些内容。</p><span id="more"></span><p>这里主要介绍 Algolia 出品的一个站内搜索工具 “DocSearch”，在软件开发圈里，很多开源软件的官网都集成了它，比如 <a href="https://vuejs.org">Vue</a>、<a href="https://vite.dev">Vite</a>、<a href="https://react.dev">React</a>、<a href="https://rollupjs.org">Rollup</a>、<a href="https://webpack.js.org">webpack</a> 等等。</p><p>下面讲一下我的博客接入 DocSearch 的过程：</p><h2 id="1、申请">1、申请</h2><p>在 Algolia 的官方网站去申请使用 DocSearch。</p><p>申请地址是：<a href="https://docsearch.algolia.com/apply/">https://docsearch.algolia.com/apply/</a></p><p>填写你的域名和邮箱，再勾选下面三个选项，如下图：</p><p><img src="/uploads/2025/04/02/algolia-001.webp" alt="algolia-001"></p><p>然后点击 “Join the prrogram”，出现下面的界面：</p><p><img src="/uploads/2025/04/02/algolia-002.webp" alt="algolia-002"></p><p>然后 1 分钟左右吧，他们就会往你的邮箱发一封邮件，表示收到了你的申请。</p><p>之后就是继续等待了，我是大概七八个小时以后，收到了第二封邮件，告诉我一切准备就绪，按照邮件里的指示，添加 css 和 js 就可以开始使用了。</p><p><img src="/uploads/2025/04/02/algolia-003.webp" alt="algolia-003"></p><h2 id="2、修改主题模板">2、修改主题模板</h2><p>官方文档地址：<a href="https://docsearch.algolia.com/docs/docsearch-v3">https://docsearch.algolia.com/docs/docsearch-v3</a></p><p>由于 Algolia 给我发的邮件里引用的静态资源是 jsdelivr CDN 的链接，jsdelivr 在国内不是很稳定，所以我改成了 unpkg CDN 的链接。</p><p>我使用的是 maupassant 主题，因此，先在 <code>themes/maupassant/layout/base.pug</code> 文件中头部的位置插入一个 div 标签：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;docsearch&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>我这里是 pug 模板引擎的写法，因此看起来有点不一样，但是最后编译出来就是上面那样的 div 标签（下图）：</p><p><img src="/uploads/2025/04/02/algolia-004.webp" alt="algolia-004"></p><p>再在 <code>themes/maupassant/source/css/style.scss</code> 文件中写入 css 样式：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#docsearch</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">right</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">top</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>实际的添加位置如下图：</p><p><img src="/uploads/2025/04/02/algolia-005.webp" alt="algolia-005"></p><p>然后在页头模板 <code>themes/maupassant/layout/_partial/head.pug</code> 文件中引入 css 样式文件：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://unpkg.com/@docsearch/css@3.9.0/dist/style.css&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure><p>实际代码如下图：</p><p><img src="/uploads/2025/04/02/algolia-006.webp" alt="algolia-006"></p><p>再在页脚模板 <code>themes/maupassant/layout/_partial/after_footer.pug</code> 文件的最后写入 js 脚本：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/@docsearch/js@3.9.0/dist/umd/index.js&quot;</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">    <span class="title function_">docsearch</span>(&#123;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">      <span class="attr">appId</span>: <span class="string">&quot;xxxxxxxxxx&quot;</span>,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">      <span class="attr">apiKey</span>: <span class="string">&quot;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&quot;</span>,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">      <span class="attr">indexName</span>: <span class="string">&quot;username&quot;</span>,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">      <span class="attr">insights</span>: <span class="literal">true</span>,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">      <span class="attr">container</span>: <span class="string">&quot;#docsearch&quot;</span>,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">      <span class="attr">debug</span>: <span class="literal">false</span></span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars">    &#125;);</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"><span class="language-handlebars"></span></span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>实际代码如下：</p><p><img src="/uploads/2025/04/02/algolia-007.webp" alt="algolia-007"></p><p>这段代码可以在 Algolia 发给我们的邮件里找到，唯一需要替换的就是红框中标出来的位置。</p><h2 id="3、验证">3、验证</h2><p>接下来，把网站打包部署到线上，就可以看到效果了。</p><p><img src="/uploads/2025/04/02/algolia-008.webp" alt="algolia-008"></p><h2 id="4、修改预设配置">4、修改预设配置</h2><p>默认情况下，Algolia 已经给我们配置好了一切。</p><p>如果要更详细的设置，或者调整抓取参数，就用申请时填写的邮箱，在 <a href="https://dashboard.algolia.com/users/sign_in">Algolia</a> 官网注册并登录管理后台，就能看到 Algolia 预设置的配置信息。</p><p><strong>记住，配置信息如果看不懂的话，不要去修改，更不要删除任何东西，否则容易出问题。</strong></p><p>我在 Algolia 的管理后台看了一下，配置的是每周检索一次博客内容。</p><p>我看有人说 Algolia 是可以配置为最小每 24 小时检索一次。</p><p>因此翻了一下官方文档，找到了配置检索频率的文档：<a href="https://www.algolia.com/doc/tools/crawler/apis/configuration/schedule/">Crawler: Schedule</a>。</p><p>然后我就把检索频率改为了每天的凌晨 1 点，如下图：</p><p><img src="/uploads/2025/04/02/algolia-009.webp" alt="algolia-009"></p><p>看了一下实际的检索时间，是北京时间的早上 9 点，所以他们应该是按照 UTC 时区来进行检索。</p><h2 id="5、总结">5、总结</h2><p>总的来说，Algolia DocSearch 接入丝滑，通过简单几步就顺利完成了。</p><p>不知道还有没有其他站内搜索方式可以用，我查了好几个，貌似都要自建服务，那就有点得不偿失。</p><p>大道至简，Algolia 做得非常好，难怪那么受众多开源软件的青睐。</p><h2 id="2025-05-11-更新">2025-05-11 更新</h2><p>目前本站使用的 <a href="https://github.com/guozhenyi/hexo-theme-clarity">hexo-theme-clarity</a> 主题，已经集成了 Algolia Docsearch 站内搜索功能。</p><p>只需要完成本页面的第一节所述申请好 Algolia 接入账号，填入主题配置中即可，不需要自己动手去修改主题模板了。</p><p>End–</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;本博客站点的搜索框默认是使用 Google 搜索引擎去搜索网站内容，这里有两个问题：一是由于政策原因，国内无法访问 Google 搜索，导致此搜索功能无效；二是 Google 搜索对本站点内容的收录可能不及时、不全面，导致搜不到某些内容。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>清明节回武汉的火车票真难抢</title>
    <link href="https://www.guozhenyi.com/post/2025/03/28/qingming-wuhan-train-ticket.html"/>
    <id>https://www.guozhenyi.com/post/2025/03/28/qingming-wuhan-train-ticket.html</id>
    <published>2025-03-28T13:15:21.000Z</published>
    <updated>2025-05-20T07:29:41.018Z</updated>
    
    <content type="html"><![CDATA[<p>今天中午在跟同事一起吃饭的时候，谈到清明节买火车票的事，同事顺嘴问了一句‘你买的是靠窗还是靠过道的票啊？’。</p><span id="more"></span><p>转动脑瓜，思虑片刻，既然回答不出来。</p><p>突然想到当时抢票时，忘记选座位了，付款时也没看是靠窗还是靠过道。</p><p>动车组列车，我是肯定不会选择 B 座位的，一般都是选择 D 座或者 F 座。</p><p>于是，我就掏出手机，那么自然的打开了 12306 APP，然后看向座位时，脑瓜子嗡嗡的…</p><p><img src="/uploads/2025/03/28/train-001.webp" alt="train-001"></p><p>无座，无座，无座…</p><p>天啊，天都塌了。为啥是无座，我在买票时根本没勾选“自动抢无座票”的选项。</p><p>两年来，我记得就只买到过一次无座票，那次加了几十块钱去餐车车厢坐回去的。</p><p>那时正值冬天，还被绿皮车车厢缝隙刮进来的风吹感冒了，回家就发高烧。</p><p>24 年春以后，原来的绿皮车 Z1/Z2、Z37/Z38 升级成了 动车组 D1/D2、D37/D38，票价涨了 50 块左右。</p><p>这一次，我可是早早的就定好闹钟，准备抢票。</p><p>在 3 月 20 日，早上 7 点 55 分就守候在 12306 APP 上准备抢清明节回武汉的火车票了。</p><p>要是当时多看一眼，就多看一眼，看到是无座票，我肯定就赶紧候补了啊…</p><p>当时是有很大概率能候补到座位票的啊（卧铺票不敢奢求，抢不过大爷大妈们）。</p><p>也怪自己购票时手欠，看到卧铺还有几张票，就准备去搏一搏卧铺票，结果售罄。</p><p>再回过头来买二等座时，还排队了一两分钟，就是这个排队，在抢到票时，导致我没有去看是否有座就仓促付款了。</p><p>现在一个星期过去了，要是还能候补到票，那简直就是太阳从西边出来…</p><p>怎么办？</p><p>凉拌炒鸡蛋。</p><p>思来想去，没辙，恐怕要在火车上打地铺了…</p><p>为此，吃完饭后，我特意在网上下单了一张防潮垫。</p><p><img src="/uploads/2025/03/28/train-002.webp" alt="train-002"></p><p>希望 4 块 3 毛 4 能解吾之忧愁。</p><p>到时候上了火车就在门口一铺，往地上一躺，爱咋咋地吧。</p><p>要是在地上摆个碗，乘务员会不会把我赶下火车，哈哈哈…</p><p>End–</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;今天中午在跟同事一起吃饭的时候，谈到清明节买火车票的事，同事顺嘴问了一句‘你买的是靠窗还是靠过道的票啊？’。&lt;/p&gt;</summary>
    
    
    
    
  </entry>
  
  <entry>
    <title>Git 日常使用指南</title>
    <link href="https://www.guozhenyi.com/post/2025/03/27/git-daily-usage-guide.html"/>
    <id>https://www.guozhenyi.com/post/2025/03/27/git-daily-usage-guide.html</id>
    <published>2025-03-27T11:31:24.000Z</published>
    <updated>2025-05-20T07:29:41.017Z</updated>
    
    <content type="html"><![CDATA[<p>Git 是一个神奇的工具，不管是不是程序员，建议都学一学，对工作和学习都有帮助。</p><p>Git 也是我工作、学习和生活中的瑞士军刀，通过在各种场景下合理的使用它，使我更加从容面对各种挑战。</p><span id="more"></span><p>Git 的安装和配置，建议看我前一篇文章：<a href="/post/2025/03/22/git-installation-and-configuration-guide.html">Git 安装和配置指南</a></p><p>Git 命令列表可以看官方文档：<a href="https://git-scm.com/docs">https://git-scm.com/docs</a></p><h2 id="1、初识（克隆）">1、初识（克隆）</h2><p>对于程序员来说，干的最多的事就是把别人的仓库代码拉到自己本地电脑上。</p><p>这个操作最简单，我们以 Github 上的仓库举例，假设我对我的博客正在使用的主题 maupassant 有些不满意，想改动一些地方，那么我就可以先把它在 Github 上的仓库代码拉取到我本地。</p><p>打开它的 Github 仓库地址：<a href="https://github.com/tufu9441/maupassant-hexo">https://github.com/tufu9441/maupassant-hexo</a></p><p>找到它的仓库克隆地址：</p><p><img src="/uploads/2025/03/27/git-001.webp" alt="git-001"></p><p>在电脑桌面找到 “Git Bash” 图标，双击打开终端。比如我要把此仓库的代码克隆到本地的 <code>D:\code\</code> 目录下，则我们可以直接在终端中新建此目录，然后克隆代码：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /d       <span class="comment"># 先切换到D盘根目录</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> code  <span class="comment"># 再创建 code 目录</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> code     <span class="comment"># 进入code 目录</span></span><br><span class="line"></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/tufu9441/maupassant-hexo.git <span class="comment"># 克隆仓库</span></span><br></pre></td></tr></table></figure><p>如下图：</p><p><img src="/uploads/2025/03/27/git-002.webp" alt="git-002"></p><p>有点尴尬，网络不好，根本拉不下来。正常情况下，拉取代码成功后，在 <code>D:/code/</code> 目录下，会有个 <code>maupassant-hexo</code> 目录，里面就是 maupassant 主题的源码。</p><h2 id="2、常用命令">2、常用命令</h2><p>先罗列一些常用命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">git init    <span class="comment"># 初始化仓库</span></span><br><span class="line"></span><br><span class="line">git status  <span class="comment"># 查看仓库状态</span></span><br><span class="line"></span><br><span class="line">git fetch  <span class="comment"># 拉取远程仓库的代码</span></span><br><span class="line"></span><br><span class="line">git merge  <span class="comment"># 合并代码</span></span><br><span class="line"></span><br><span class="line">git pull   <span class="comment"># 拉取远程仓库的代码并合并到本地分支</span></span><br><span class="line"></span><br><span class="line">git checkout dev  <span class="comment"># 切换到 dev 分支</span></span><br><span class="line"></span><br><span class="line">git push   <span class="comment"># 把本地分支提交的代码，推送到远程仓库的同名分支（main -&gt; origin/main）</span></span><br><span class="line"></span><br><span class="line">git branch -a  <span class="comment"># 查看所有本地和远程分支</span></span><br></pre></td></tr></table></figure><p>不用死记硬背，通过场景教学，多练习几次，很轻松就能记住并上手。</p><h2 id="3、场景教学">3、场景教学</h2><p>我在 <code>D:/code</code> 目录新建个文件夹 <code>my-note</code>，用来存放 markdown 笔记，应该如何用 git 帮我管理好这些笔记呢？</p><p>常见诉求：</p><ol><li>笔记内容不丟失。</li><li>能多台电脑同步。</li><li>最好能看到笔记的修改历史。</li></ol><h3 id="3-1-新建仓库">3.1 新建仓库</h3><p>创建文件夹，并初始化为 git 仓库。</p><p>打开 Git Bash，输入命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /d/code     <span class="comment"># 进入 D:/code 目录</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> my-note  <span class="comment"># 创建文件夹</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> my-note     <span class="comment"># 进入文件夹</span></span><br><span class="line"></span><br><span class="line">git init       <span class="comment"># 初始化仓库</span></span><br></pre></td></tr></table></figure><p>如下图：</p><p><img src="/uploads/2025/03/27/git-003.webp" alt="git-003"></p><p>如此，my-note 文件夹就已经成为一个 git 仓库了，在该文件夹里有个隐藏的 .git 目录，里面保存了此仓库的所有信息。</p><h3 id="3-2-添加笔记并提交">3.2 添加笔记并提交</h3><p>现在我们可以在 <code>D:/code/my-note</code> 目录下创建一个笔记本文件 <code>how-to-use-git.md</code>，或者创建子文件夹 <code>2025-03</code>，再在子文件夹里创建笔记 <code>note-001.md</code>。</p><p>此时可以运用 Git 命令查看仓库状态：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git status   <span class="comment"># 查看仓库状态</span></span><br></pre></td></tr></table></figure><p>结果如下图：</p><p><img src="/uploads/2025/03/27/git-004.webp" alt="git-004"></p><p>因为这是新仓库，一个提交记录都没有，新建的笔记也没提交到仓库，所以界面上的文字都给提示出来了。</p><p>那么，如何把刚添加的文件全部提交到仓库呢，可以执行如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">git add .     <span class="comment"># 把当前仓库里的所有文件加入暂存区（“点”表示所有）</span></span><br><span class="line"></span><br><span class="line">git commit -m <span class="string">&quot;第一次提交的笔记&quot;</span>  <span class="comment"># 把暂存区的文件提交到仓库，并附上提交信息</span></span><br><span class="line"></span><br><span class="line">git status    <span class="comment"># 查看仓库状态</span></span><br></pre></td></tr></table></figure><p>结果如下图：</p><p><img src="/uploads/2025/03/27/git-005.webp" alt="git-005"></p><p>看其中的英文信息：</p><blockquote><p>On branch main<br>nothing to commit, working tree clean</p></blockquote><p>翻译翻译，就是：</p><blockquote><p>在 main 分支<br>没有什么东西需要提交，工作树是干净的</p></blockquote><p>说明咱们把所有新添加的笔记都用 git 管理起来了，工作区很干净。</p><h3 id="3-3-修改笔记并提交">3.3 修改笔记并提交</h3><p>提交的两条笔记，突然觉得某个地方写错了，于是赶紧打开改了一下，再来看看 git 会有什么变化：</p><p><img src="/uploads/2025/03/27/git-006.webp" alt="git-006"></p><p>这个界面的英文提示也很全面，告诉你：</p><blockquote><p>用 <code>git add</code> 更新你想提交的<br>用 <code>git restore</code> 去撤销你不想更改的内容</p></blockquote><p>里面也追踪到 <code>how-to-use-git.md</code> 和 <code>note-001.md</code> 文件被修改了。</p><p>好，这里的动作就可以拆解了：</p><ol><li>我想把所有修改都提交到仓库，则执行（跟上面添加笔记的步骤一模一样）：</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add .     <span class="comment"># 把当前仓库里的所有文件加入暂存区（“点”表示所有）</span></span><br><span class="line"></span><br><span class="line">git commit -m <span class="string">&quot;提交一些笔记的修改信息&quot;</span>  <span class="comment"># 把暂存区的文件提交到仓库，并附上提交信息</span></span><br></pre></td></tr></table></figure><ol start="2"><li><a href="http://how-to-use-git.md">how-to-use-git.md</a> 文件内容改错了，想恢复原样，则执行：</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git restore how-to-use-git.md    <span class="comment"># 还原文件到仓库里的版本状态</span></span><br></pre></td></tr></table></figure><ol start="3"><li>只想提交 <a href="http://note-001.md">note-001.md</a> 的修改内容到仓库，则执行：</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add 2025-03/note-001.md    <span class="comment"># 把当前仓库里的指定文件加入暂存区</span></span><br><span class="line"></span><br><span class="line">git commit -m <span class="string">&quot;提交笔记修改信息&quot;</span>  <span class="comment"># 把暂存区的文件提交到仓库，并附上提交信息</span></span><br></pre></td></tr></table></figure><hr><p>（内容较长，未完待续…）</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Git 是一个神奇的工具，不管是不是程序员，建议都学一学，对工作和学习都有帮助。&lt;/p&gt;
&lt;p&gt;Git 也是我工作、学习和生活中的瑞士军刀，通过在各种场景下合理的使用它，使我更加从容面对各种挑战。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Git" scheme="https://www.guozhenyi.com/tags/git/"/>
    
  </entry>
  
  <entry>
    <title>Git 安装和配置指南</title>
    <link href="https://www.guozhenyi.com/post/2025/03/22/git-installation-and-configuration-guide.html"/>
    <id>https://www.guozhenyi.com/post/2025/03/22/git-installation-and-configuration-guide.html</id>
    <published>2025-03-22T02:46:57.000Z</published>
    <updated>2025-05-20T07:29:41.016Z</updated>
    
    <content type="html"><![CDATA[<p>Git 是目前最流行的分布式版本控制系统，广泛用于软件开发和协作。Git 也不止可以用于代码的版本控制，任何文本型的文件，都可以用 Git 来控制版本，非常方便。下面介绍下 Git 的安装和配置：</p><span id="more"></span><h2 id="一、Git-安装">一、Git 安装</h2><p>Git 官方下载地址是：<a href="https://git-scm.com/downloads">https://git-scm.com/downloads</a></p><p>（⚠️注意：有一个中文版的官网，应该是国内的爱好者搭建的，域名是 <a href="http://git-scm.cn">git-scm.cn</a>，请注意区别。我这里就是看错了，在中文版网站下载的 Git 安装程序，看了下载地址和官网是一致的，还好还好。）</p><p>（备注：我在中文站下载的是 <code>Git-2.47.0.2-64-bit.exe</code> 版本，实际官网最新现在是 <code>Git-2.49.0-64-bit.exe</code> 版本了。我把 <code>Git-2.49.0-64-bit.exe</code> 下载下来重新安装了一遍。）</p><p>打开链接，点击 “Windows”，去下载 windows 版本：</p><p><img src="/uploads/2025/03/22/git-001.webp" alt="git-001"></p><p>在 windows 下载页面，我们选择 <strong>64-bit Git for Windows Setup</strong>：</p><p><img src="/uploads/2025/03/22/git-002.webp" alt="git-002"></p><p>因为下载地址是 github，所以有可能链接打不开，或者很慢，请多试几次。</p><p>下载完成后，双击安装包，如果出现下图的安全警告，点击“运行”即可：</p><p><img src="/uploads/2025/03/22/git-003.webp" alt="git-003"></p><p>这里还可能出现“账户权限控制”的弹窗，选择“是”，如果没出现的话，就会来到正式的安装界面，点击“Next”，如下图：</p><p><img src="/uploads/2025/03/22/git-004.webp" alt="git-004"></p><p>这里会选择安装目录，默认的安装目录一般是 <code>C:\Program Files\Git</code>，可以不用改，但是我的习惯是把软件都安装到 <code>C:\app\</code> 目录，所以这里我改成了 <code>C:\app\Git</code>，继续点击“Next”，如下图：</p><p><img src="/uploads/2025/03/22/git-005.webp" alt="git-005"></p><p>接着进入选组件页，保持默认就好。不过我勾上了 <code>On the Desktop</code> 选项，此项会在桌面创建图标。并且去掉了“Open Git GUI here” 选项，用不到（Git 可视化工具有其他更好的选择），去掉此项可以让右键菜单少一个选项。如下图：</p><p><img src="/uploads/2025/03/22/git-006.webp" alt="git-006"></p><p>这里是问用户是否创建开始菜单目录，默认会创建，不用改动，直接点“Next”，如下图：</p><p><img src="/uploads/2025/03/22/git-007.webp" alt="git-007"></p><p>此界面是让你选择 Git 使用的编辑器，默认是 vim。可以不用修改，点“Next”就行，如下图：</p><p><img src="/uploads/2025/03/22/git-008.webp" alt="git-008"></p><p>这里是询问 <code>git init</code> 命令初始化新仓库时，默认的分支名用哪一个。以前都是叫 <code>master</code>，后来因为黑人搞政治正确，觉得 <code>master</code> 带有歧视，所以普遍都改用 <code>main</code> 作为默认分支名了，所以我们也选择使用 <code>main</code> 作为默认分支名，如下图：</p><p><img src="/uploads/2025/03/22/git-009.webp" alt="git-009"></p><p>这里选择第二项 “Git from the command line and also from 3d-party software”，让其他命令行工具（比如 <code>cmd</code>）也可以使用 <code>git</code> 命令，如下图：</p><p><img src="/uploads/2025/03/22/git-010.webp" alt="git-010"></p><p>这里保持默认，选择第一项 “Use bundled OpenSSH”，使用内建的 OpenSSH 即可，如下图：</p><p><img src="/uploads/2025/03/22/git-011.webp" alt="git-011"></p><p>这里也保持默认，选择第一项 “Use the OpenSSL library”，如下图：</p><p><img src="/uploads/2025/03/22/git-012.webp" alt="git-012"></p><p>注意，这里要选择第三项 “Checkout as-is, commit as-is”（就是不让 Git 去帮你更改换行符，保持文本原样），如下图：</p><p><img src="/uploads/2025/03/22/git-013.webp" alt="git-013"></p><p>这里也选择第一项 “Use MinTTY(the default terminal of MSYS2)”，如下图：</p><p><img src="/uploads/2025/03/22/git-014.webp" alt="git-014"></p><p>这里也保持默认，选择第一项 “Fast-forward or merge”，如下图：</p><p><img src="/uploads/2025/03/22/git-015.webp" alt="git-015"></p><p>这里选择第二项 “None”，不用 Git 的凭据管理。在 windows 系统，Git 需要输入账号密码时，会默认使用 &quot;windows 凭据管理&quot;来保存密码，实测更好用一些，如下图：</p><p><img src="/uploads/2025/03/22/git-016.webp" alt="git-016"></p><p>这里保持默认，不用改动，点击 “Install” 开始安装，如下图：</p><p><img src="/uploads/2025/03/22/git-017.webp" alt="git-017"></p><p>等待安装完成后，点击 “Finish”， 如下图：</p><p><img src="/uploads/2025/03/22/git-019.webp" alt="git-019"></p><p>至此，Git 就安装完成了。</p><h2 id="二、Git-基本配置">二、Git 基本配置</h2><p>安装 Git 后，需要进行基本的用户信息配置，以便提交代码时能够记录正确的身份信息。</p><p>在桌面上双击 “Git Bash” 图标，打开 Git 控制终端，执行两个配置命令，配置名字和邮箱：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name <span class="string">&quot;你的名字&quot;</span></span><br><span class="line">git config --global user.email <span class="string">&quot;你的邮箱&quot;</span></span><br></pre></td></tr></table></figure><p>如下图：</p><p><img src="/uploads/2025/03/22/git-020.webp" alt="git-020"></p><h2 id="三、生成-SSH-密钥">三、生成 SSH 密钥</h2><p>如果你使用 Git 连接 GitHub、GitLab 或其他远程仓库，建议生成 SSH 密钥进行身份验证。</p><p>同样的，在桌面上双击 “Git Bash” 图标，打开 Git 控制终端，输入以下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -b 4096 -C <span class="string">&quot;你的邮箱&quot;</span></span><br></pre></td></tr></table></figure><p>这里会有几个选项，我们点击三次回车键（Enter）保持默认即可。</p><p>（备注：这里三个选项，第一个是让你选择密钥存放目录；第二个是设置密钥的密码；第三个是重复密钥的密码。设置了密码容易遗忘，所以一般都不设置密码。只要你给每台机器都生成单独的 SSH 密钥，并且不定期的更换 SSH 密钥，不要把私钥泄露出去，一般都不会有什么安全问题。如果实在涉及到高安全性的地方，建议还是设置一下密码。）</p><p>如下图：</p><p><img src="/uploads/2025/03/22/git-021.webp" alt="git-021"></p><p>到这里，SSH 密钥就生成好了。</p><h2 id="四、给-Github-配置-SSH-密钥">四、给 Github 配置 SSH 密钥</h2><p>如果要在 Github 上克隆仓库，或私有仓库，建议给 Github 配置 SSH 密钥。</p><p>如何创建 Github 账号，这里就不讲述了。只讲如何在 Github 账号中配置 SSH 密钥。</p><p>在桌面上双击 “Git Bash” 图标，打开 Git 控制终端，输入以下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> ~/.ssh/id_rsa.pub</span><br></pre></td></tr></table></figure><p>把打印出来的公钥全部选中，然后点击右键，选择 “Copy” 复制，如下图：</p><p><img src="/uploads/2025/03/22/git-022.webp" alt="git-022"></p><p>接着，我们打开 Github 配置密钥的地址：<a href="https://github.com/settings/keys">https://github.com/settings/keys</a></p><p>点击 “New SSH key” 按钮，在 “Title” 里输入一点信息（辅助我们记忆添加这个 SSH 密钥的作用），再把刚复制的公钥粘贴到 “Key” 的文本框中，如下图：</p><p><img src="/uploads/2025/03/22/git-023.webp" alt="git-023"></p><p>点击 “Add SSH key”，在 Github 中就添加好 SSH 公钥了。</p><p>如何验证呢？</p><p>还是在桌面上双击 “Git Bash” 图标，打开 Git 控制终端，输入以下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh -T git@github.com</span><br></pre></td></tr></table></figure><p>如果控制台打印出 “Hi username! You’ve successfully authenticated…” 的字样，就表示 SSH 配置成功了。</p><p>如下图：</p><p><img src="/uploads/2025/03/22/git-024.webp" alt="git-024"></p><h2 id="五、Git-可视化工具-GUI-Client">五、Git 可视化工具(GUI Client)</h2><p>如果单纯用 Git 命令去管理版本，不太直观，我们可以用可视化工具配合使用 Git，可以减少很多手敲的命令。</p><p>Git 官方也列了很多可视化工具，我这里推荐使用 <strong>Git Extensions</strong>，用了很多年了，非常方便。</p><p><img src="/uploads/2025/03/22/git-025.webp" alt="git-025"></p><p>官方下载地址：<a href="https://github.com/gitextensions/gitextensions/releases">https://github.com/gitextensions/gitextensions/releases</a></p><p>打开官方下载链接，由于是 Github，可能比较慢，选择 msi 安装包下载：</p><p><img src="/uploads/2025/03/22/git-026.webp" alt="git-026"></p><p>双击安装包即可开始安装，下一步下一步就安装好了，比较简单。</p><h2 id="六、总结">六、总结</h2><p>至此，我们在 windows 系统上就安装并配置好了 Git，还顺便配置好了 Github SSH，安装了 GUI 客户端。</p><p>后续使用 Git 时，配合 GUI 客户端，简直是如虎添翼，非常丝滑。</p><p>End–</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Git 是目前最流行的分布式版本控制系统，广泛用于软件开发和协作。Git 也不止可以用于代码的版本控制，任何文本型的文件，都可以用 Git 来控制版本，非常方便。下面介绍下 Git 的安装和配置：&lt;/p&gt;</summary>
    
    
    
    
    <category term="Git" scheme="https://www.guozhenyi.com/tags/git/"/>
    
  </entry>
  
  <entry>
    <title>Linux 系统使用 fnm 安装 Nodejs 任意版本</title>
    <link href="https://www.guozhenyi.com/post/2025/03/20/install-nodejs-with-fnm-on-linux.html"/>
    <id>https://www.guozhenyi.com/post/2025/03/20/install-nodejs-with-fnm-on-linux.html</id>
    <published>2025-03-20T11:46:57.000Z</published>
    <updated>2025-05-20T09:41:55.414Z</updated>
    
    <content type="html"><![CDATA[<p>经过多年发展，Nodejs 版本管理工具层出不穷，比如 nvm、nvs、fnm、volta 等等，都是各具特色的工具。</p><p>比如在 Windows 系统上就是使用 <a href="https://github.com/coreybutler/nvm-windows">nvm-windows</a> 来切换 Nodejs 版本，简单方便。</p><span id="more"></span><p>在 Linux 系统上，软件仓库一般会有一个比较老的 Nodejs 版本，可以直接运行命令 <code>apt install nodejs</code> 安装使用。比如在 ubuntu 20.04 系统中，软件仓库默认集成是 Nodejs 10.x 的版本。</p><p>我现在想要在 ubuntu 服务器中部署一个持续集成工具，能帮我自动给前端项目打包，前端项目目前使用的 Nodejs 是 16.x 版本。</p><p>之前写过一篇介绍 ubuntu 安装 Nodejs 的文章：<a href="/post/2020/06/28/ubuntu-18-install-nodejs-12.html">ubuntu 18.04 安装 nodejs 最新版、指定版 12.x 14.x</a>。文章里面的内容好像过时了，而且操作起来不够简单。</p><p>那么我现在要给 ubuntu 20.04 服务器安装 Nodejs 16.x，经过研究后，我觉得使用 <code>fnm</code> 来安装 Nodejs 是比较简便的方式。</p><h2 id="安装-fnm">安装 fnm</h2><p>fnm 是使用 Rust 语言开发的一个 Nodejs 版本管理器。</p><p>fnm 官方下载地址：<a href="https://github.com/Schniz/fnm/releases">https://github.com/Schniz/fnm/releases</a></p><p>我们下载最新的 Linux 平台二进制压缩包：<code>fnm-linux.zip</code>，解压后会得到一个 <code>fnm</code> 程序文件。</p><p>接着在本地打开 <code>Git Bash</code> 终端，把 <code>fnm</code> 上传到 ubuntu 服务器：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scp fnm root@111.111.111.111:/usr/local/bin/</span><br></pre></td></tr></table></figure><p>注意，为了避免权限问题，这里要用 root 账号上传到 <code>/usr/local/bin</code> 目录。</p><p>上传完成后，登录 ubuntu 服务器，切换到 <code>/usr/local/bin</code> 目录，给 fnm 授予执行权限：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 切换目录</span></span><br><span class="line"><span class="built_in">cd</span> /usr/local/bin</span><br><span class="line"></span><br><span class="line"><span class="comment"># 授予执行权限</span></span><br><span class="line"><span class="built_in">chmod</span> +x fnm</span><br></pre></td></tr></table></figure><p>接着切换到 <code>/root</code> 目录，在 <code>.bashrc</code> 文件的最后增加一行：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">eval &quot;$(fnm env --use-on-cd --shell bash)&quot;</span><br></pre></td></tr></table></figure><p>再执行命令重载一下配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">source</span> /root/.bashrc</span><br></pre></td></tr></table></figure><p>输入命令验证一下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fnm --version</span><br></pre></td></tr></table></figure><p>如果打印出版本信息，则 <code>fnm</code> 已经部署好了。</p><h2 id="安装-Nodejs">安装 Nodejs</h2><p>现在我们通过 <code>fnm</code> 安装 Nodejs。</p><p>我这里想安装 Nodejs v16.20.0 版本，则执行如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fnm install 16.20.0</span><br></pre></td></tr></table></figure><p>速度很快，一会就安装好了。</p><p>接着运行如下命令，就可以看到安装好的 Node 了：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fnm list</span><br></pre></td></tr></table></figure><p>默认情况下，node 和 npm 都会一起安装。</p><p>我这里要用 pnpm，所以还需要执行以下命令安装 pnpm：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -g pnpm</span><br></pre></td></tr></table></figure><p>至此，ubuntu 服务器就安装好 Nodejs 比较新的版本了。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;经过多年发展，Nodejs 版本管理工具层出不穷，比如 nvm、nvs、fnm、volta 等等，都是各具特色的工具。&lt;/p&gt;
&lt;p&gt;比如在 Windows 系统上就是使用 &lt;a href=&quot;https://github.com/coreybutler/nvm-windows&quot;&gt;nvm-windows&lt;/a&gt; 来切换 Nodejs 版本，简单方便。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Nodejs" scheme="https://www.guozhenyi.com/tags/nodejs/"/>
    
    <category term="ubuntu" scheme="https://www.guozhenyi.com/tags/ubuntu/"/>
    
    <category term="Linux" scheme="https://www.guozhenyi.com/tags/linux/"/>
    
  </entry>
  
  <entry>
    <title>如何部署 Hexo 博客到 Linux 服务器</title>
    <link href="https://www.guozhenyi.com/post/2025/03/19/how-to-deploy-hexo-to-linux-server.html"/>
    <id>https://www.guozhenyi.com/post/2025/03/19/how-to-deploy-hexo-to-linux-server.html</id>
    <published>2025-03-19T13:18:06.000Z</published>
    <updated>2025-05-20T09:41:55.413Z</updated>
    
    <content type="html"><![CDATA[<p>自从把博客迁移到 Hexo 后，如何方便的把生成的静态博客部署到 Linux 服务器成了摆在眼前的问题。</p><span id="more"></span><p>Hexo 官网介绍了几种部署方式：<a href="https://hexo.io/zh-cn/docs/one-command-deployment">https://hexo.io/zh-cn/docs/one-command-deployment</a></p><h2 id="1、Rsync-方案（放弃）">1、Rsync 方案（放弃）</h2><p>本来想试一下 rsync 部署，发现它不支持 windows 系统。</p><p>后来灵机一动，Git 能在 windows 系统里用，Git for windows 里还自带 bash.exe，而 Git for windows 又是 msys2 的工具包封装而来。那么先看看 msys2 里有没有 rsync，有的话，复制到 Git 里不就可以在 windows 系统下用 rsync 了么。</p><p>打开 MSYS2 Shell，执行以下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pacman -S rsync</span><br></pre></td></tr></table></figure><p><img src="/uploads/2025/03/19/rsync-001.webp" alt="rsync-001"></p><p>果然有，于是查看了 rsync 安装位置和依赖包，复制到 Git 里相应位置，运行时发现版本不兼容，无奈作罢。</p><h2 id="2、Bash-脚本方案">2、Bash 脚本方案</h2><p>看了下文档，还可以选择 SFTP 部署方式，我没尝试了，而是想到了更简单的部署方式。</p><p>目前我的部署方式是在 windows 系统本地运行 <code>hexo clean &amp;&amp; hexo g</code> 生成静态站点，然后 ftp 上传到服务器上。</p><p>而这一过程重复多次以后，就觉得很烦了，想着把它简化一下吧。</p><p>于是写了个 bash 脚本放在 Hexo 博客根目录，命名为 “<a href="http://deploy.sh">deploy.sh</a>”，内容如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">_date=$(<span class="built_in">date</span> +<span class="string">&quot;%Y%m%d-%H%M&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 清理缓存</span></span><br><span class="line">hexo clean</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成网站</span></span><br><span class="line">hexo generate</span><br><span class="line"></span><br><span class="line">_pkg=site-<span class="variable">$&#123;_date&#125;</span>.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="comment"># 打包</span></span><br><span class="line">tar -czf <span class="variable">$&#123;_pkg&#125;</span> public</span><br><span class="line"></span><br><span class="line"><span class="comment"># 远程主机中的网站存放目录</span></span><br><span class="line">_remote_dir=/var/www/website/</span><br><span class="line"></span><br><span class="line"><span class="comment"># 主机登录信息</span></span><br><span class="line">_remote_host=root@xxx.xx.xx.xxx</span><br><span class="line"></span><br><span class="line"><span class="comment"># 上传</span></span><br><span class="line">scp <span class="variable">$&#123;_pkg&#125;</span> <span class="variable">$&#123;_remote_host&#125;</span>:<span class="variable">$&#123;_remote_dir&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 远程部署</span></span><br><span class="line">_tar=<span class="string">&quot;tar -xzf <span class="variable">$&#123;_pkg&#125;</span>&quot;</span></span><br><span class="line"></span><br><span class="line">ssh <span class="variable">$&#123;_remote_host&#125;</span> <span class="string">&quot;cd <span class="variable">$&#123;_remote_dir&#125;</span> &amp;&amp; rm -rf public &amp;&amp; <span class="variable">$&#123;_tar&#125;</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Deploy success.&quot;</span></span><br></pre></td></tr></table></figure><p>注意，此脚本运行的前提条件是为 Linux 服务器配置好免密登录，可以参考我的另一篇文章：</p><p>《<a href="/post/2023/11/30/configure-password-free-login-for-linux.html">Linux 服务器配置免密码登录</a>》</p><p>我在 Nginx 配置的完整目录是 <code>/var/www/website/public</code>。</p><p>脚本中的 <code>_remote_dir</code> 即为我的网站存放目录，因为网站打包已经包含了 public 目录，所以这里就不需要再填写 public 目录了。</p><p>脚本中的 <code>_remote_host</code> 则是配置我的 ubuntu 服务器的地址（username@ip）。</p><p>这样每当我写完新的文章以后，就可以在网站根目录打开 “Git Bash”，执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash deploy.sh</span><br></pre></td></tr></table></figure><p>脚本运行完，就表示我的网站已经部署好啦，怎么样，是不是简单方便。</p><p>End–</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;自从把博客迁移到 Hexo 后，如何方便的把生成的静态博客部署到 Linux 服务器成了摆在眼前的问题。&lt;/p&gt;</summary>
    
    
    
    
    <category term="Linux" scheme="https://www.guozhenyi.com/tags/linux/"/>
    
    <category term="Hexo" scheme="https://www.guozhenyi.com/tags/hexo/"/>
    
  </entry>
  
</feed>
