<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Ethaniel</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <icon>https://hcyhub.com/H.svg</icon>
  <id>https://hcyhub.com/</id>
  <link href="https://hcyhub.com/" rel="alternate"/>
  <link href="https://hcyhub.com/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Ethaniel</rights>
  <subtitle>静水深流</subtitle>
  <title>静水深流</title>
  <updated>2026-10-22T14:44:09.188Z</updated>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>我的网站评论区使用的是 Twikoo 系统，由于它支持自定义 OwO 表情包，我便整理了一套常用表情并放置在 <code>owo.hcyhub.com</code> 域名下。</p><p>之前这个站点只存放了 <code>owo.json</code> 和图片源文件，直接访问只会触发 404 页面，只能访问<a href="https://owo.hcyhub.com/owo.json">OWO.json</a>查看JSON文件。今天正好有空，就顺手给它做了个<strong>索引预览页</strong>。</p><p>可以看到效果还是很不错的，不仅可以直观地按分类浏览收录的表情，还能点击放大预览、一键复制图片&#x2F;颜文字以及下载保存。</p><img src="./../../images/OWO表情包索引预览页/OWO表情预览.png" style="zoom:80%;" /><img src="./../../images/OWO表情包索引预览页/放大查看.png" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/OWO%E8%A1%A8%E6%83%85%E5%8C%85%E7%B4%A2%E5%BC%95%E9%A2%84%E8%A7%88%E9%A1%B5</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/OWO%E8%A1%A8%E6%83%85%E5%8C%85%E7%B4%A2%E5%BC%95%E9%A2%84%E8%A7%88%E9%A1%B5"/>
    <published>2026-10-22T14:30:56.265Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>我的网站评论区使用的是 Twikoo 系统，由于它支持自定义 OwO 表情包，我便整理了一套常用表情并放置在 <code>owo.hcyhub.com</code> 域名下。</p>
<p>之前这个站点只存放了 <code>owo.json</code> 和图片源文件，直接访问只会触发 404 页面，只能访问<a]]>
    </summary>
    <title>OWO表情包索引预览页</title>
    <updated>2026-10-22T14:44:09.188Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>在网页中，音频播放是一个再经典不过的需求。通常我们直接用 <code>&lt;audio src=&quot;https://example.com/example.mp3&quot; controls&gt;&lt;/audio&gt;</code> 就能搞定。但只要你对 UI 有一点点追求，很快就会遇到两个让人抓狂的痛点：</p><ol><li><strong>多端样式分裂</strong>：Chrome 的样式圆润现代，Firefox 的复古方正，Safari 又自成一派。在不同浏览器渲染下样式完全不一样，可能用 Chrome 打开的人觉得很好看就留下了，Firefox 打开的人一看一个现代页面中居然穿插了个梦回千禧年的播放器直接劝退。</li><li><strong>完全无法定制</strong>：因为浏览器默认的播放控件被藏在<strong>影子 DOM (Shadow DOM)</strong> 内部，外界的 CSS 和 JS 根本摸不到它。如果你想在播放器里加个新的菜单选项、做点别的修改，根本不可能。</li></ol><p>而在我音乐空间的<a href="/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E9%9F%B3%E4%B9%90%E7%A9%BA%E9%97%B4#2026-4-22%E6%9B%B4%E6%96%B0">2026.4.22更新</a>中，我解决了这两个问题，既然我改不了 Shadow DOM，那就隐藏它，用 DOM 复刻一个 Chrome 默认的音频播放器。</p><p>效果对比：</p><p><img src="/./../../images/%E7%BA%AFDOM%E5%A4%8D%E5%88%BBChrome%E9%BB%98%E8%AE%A4%E9%9F%B3%E9%A2%91%E6%92%AD%E6%94%BE%E5%99%A8/%E5%AF%B9%E6%AF%94%E5%9B%BE.png" alt="对比图"><br><em>注：上方为 DOM 复刻版，下方为 Chrome 原生播放器。</em></p><p>猛地一瞅，视觉和动态交互体验几乎和Chrome 原生播放器没区别。除了右侧展开的倍速菜单长得不同，其他几乎一致。</p><p>这个DOM复刻完美复刻了这两个交互细节：</p><ol><li><p>自动向左滑出展开的音量条，Chrome 的音量条平时是隐藏的，鼠标悬停到喇叭图标上时，音量滑动条会平滑地<strong>向左</strong>滑出。</p></li><li><p>倍速菜单的自动滚动定位，当用户点击“播放速度”打开子菜单时，如果当前已经设置了 2.0x 播放，菜单会自动把当前选中的选项滚动到正中间。</p></li></ol><h2 id="完整实现代码"><a href="#完整实现代码" class="headerlink" title="完整实现代码"></a><strong>完整实现代码</strong></h2><blockquote><p>不依赖任何第三方库（如 jQuery、Tailwind 等），用纯原生 HTML5、CSS3 和 Vanilla JS 编写。你可以直接复制这些代码，在本地新建一个 <code>.html</code> 文件即可运行体验。</p><p>HTML里有个小细节，我给进度显示的cap-time加上了translate&#x3D;”no”属性，这个属性的意思是让翻译插件滚开，避免说翻译插件把 <code>00:00 / 00:00</code>这个进度给翻译了。有的机翻会翻译乱掉，比如翻译成<code>00:00</code>、<code>00时00分</code></p></blockquote><h3 id="HTML"><a href="#HTML" class="headerlink" title="HTML"></a>HTML</h3><pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token comment">&lt;!-- 使用audio播放音乐，但隐藏浏览器自己渲染的默认播放器控件 --></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>audio</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>PlayAudio<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://example.com/example.mp3<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>audio</span><span class="token punctuation">></span></span><span class="token comment">&lt;!-- 复刻DOM --></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>chrome-audio-player<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>chromeAudioPlayer<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>    <span class="token comment">&lt;!-- 播放/暂停按钮 --></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capPlayPauseBtn<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-btn<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>播放<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capPlayIcon<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik04IDV2MTRsMTEtN3oiLz4KICAgIDxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4KPC9zdmc+<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>play<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capPauseIcon<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik02IDE5aDRWNUg2djE0em04LTE0djE0aDRWNWgtNHoiLz4KICAgIDxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4KPC9zdmc+<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pause<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>        <span class="token comment">&lt;!-- 时间 --></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-time<span class="token punctuation">"</span></span> <span class="token attr-name">translate</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>no<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capCurrentTime<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>0:00<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span> / <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capDuration<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>0:00<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token comment">&lt;!-- 进度条 --></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-progress-container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capSeekSlider<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-custom-slider<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-track<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capSeekFill<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-fill<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capSeekThumb<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-thumb<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token comment">&lt;!-- 音量 --></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-volume-group<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capMuteBtn<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-btn<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>静音<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capVolumeIcon<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0zIDl2Nmg0bDUgNVY0TDcgOUgzem0xMy41IDNjMC0xLjc3LTEuMDItMy4yOS0yLjUtNC4wM3Y4LjA1YzEuNDgtLjczIDIuNS0yLjI1IDIuNS00LjAyek0xNCAzLjIzdjIuMDZjMi44OS44NiA1IDMuNTQgNSA2Ljcxcy0yLjExIDUuODUtNSA2LjcxdjIuMDZjNC4wMS0uOTEgNy00LjQ5IDctOC43N3MtMi45OS03Ljg2LTctOC43N3oiLz4KICAgIDxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4KPC9zdmc+<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>volume<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capMuteIcon<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xNi41IDEyYzAtMS43Ny0xLjAyLTMuMjktMi41LTQuMDN2Mi4yMWwyLjQ1IDIuNDVjLjAzLS4yLjA1LS40MS4wNS0uNjN6bTIuNSAwYzAgLjk0LS4yIDEuODItLjU0IDIuNjRsMS41MSAxLjUxQzIwLjYzIDE0LjkxIDIxIDEzLjUgMjEgMTJjMC00LjI4LTIuOTktNy44Ni03LTguNzd2Mi4wNmMyLjg5Ljg2IDUgMy41NCA1IDYuNzF6TTQuMjcgM0wzIDQuMjcgNy43MyA5SDN2Nmg0bDUgNXYtNi43M2w0LjI1IDQuMjVjLS42Ny41Mi0xLjQyLjkzLTIuMjUgMS4xOHYyLjA2YzEuMzgtLjMxIDIuNjMtLjk1IDMuNjktMS44MUwxOS43MyAyMSAyMSAxOS43M2wtOS05TDQuMjcgM3pNMTIgNEw5LjkxIDYuMDkgMTIgOC4xOFY0eiIvPgogICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgo8L3N2Zz4=<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>mute<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-volume-panel<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capVolumeSlider<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-custom-slider cap-vol-slider<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-track<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capVolumeFill<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-fill<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">width</span><span class="token punctuation">:</span>100%</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capVolumeThumb<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-thumb<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">left</span><span class="token punctuation">:</span>100%</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token comment">&lt;!-- 更多选项按钮 --></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-wrapper<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capMoreBtn<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-btn<span class="token punctuation">"</span></span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>更多选项<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMjQgMjQiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI0IDI0OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgZmlsbD0iV2luZG93VGV4dCI+CjxnPgoJPGNpcmNsZSBjeD0iMTIiIGN5PSI2IiByPSIyIi8+Cgk8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+Cgk8Y2lyY2xlIGN4PSIxMiIgY3k9IjE4IiByPSIyIi8+CjwvZz4KPC9zdmc+<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>more<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>                <span class="token comment">&lt;!-- 菜单 --></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capMainMenu<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-popover hidden<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token comment">&lt;!-- 下载 --></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-item<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capDownloadBtn<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xOSA5aC00VjNIOXY2SDVsNyA3IDctN3pNNSAxOHYyaDE0di0ySDV6Ii8+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+Cjwvc3ZnPg==<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-icon<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>download<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>下载<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>            <span class="token comment">&lt;!-- 倍速菜单选项 --></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-item<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capOpenSpeedBtn<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHdpZHRoPSIyNCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+CiAgPHBhdGggZD0iTTEzLjA1IDkuNzlMMTAgNy41djlsMy4wNS0yLjI5TDE2IDEybC0yLjk1LTIuMjF6bTAgMEwxMCA3LjV2OWwzLjA1LTIuMjlMMTYgMTJsLTIuOTUtMi4yMXptMCAwTDEwIDcuNXY5bDMuMDUtMi4yOUwxNiAxMmwtMi45NS0yLjIxek0xMSA0LjA3VjIuMDVjLTIuMDEuMi0zLjg0IDEtNS4zMiAyLjIxTDcuMSA1LjY5QTcuOTQxIDcuOTQxIDAgMDExMSA0LjA3ek01LjY5IDcuMUw0LjI2IDUuNjhBOS45NDkgOS45NDkgMCAwMDIuMDUgMTFoMi4wMmMuMTgtMS40Ni43Ni0yLjc5IDEuNjItMy45ek00LjA3IDEzSDIuMDVjLjIgMi4wMSAxIDMuODQgMi4yMSA1LjMybDEuNDMtMS40M0E3Ljg2OCA3Ljg2OCAwIDAxNC4wNyAxM3ptMS42MSA2Ljc0QTkuOTgxIDkuOTgxIDAgMDAxMSAyMS45NXYtMi4wMmE3Ljk0MSA3Ljk0MSAwIDAxLTMuOS0xLjYybC0xLjQyIDEuNDN6TTIyIDEyYzAgNS4xNi0zLjkyIDkuNDItOC45NSA5Ljk1di0yLjAyQzE2Ljk3IDE5LjQxIDIwIDE2LjA1IDIwIDEycy0zLjAzLTcuNDEtNi45NS03LjkzVjIuMDVDMTguMDggMi41OCAyMiA2Ljg0IDIyIDEyeiIvPgo8L3N2Zz4=<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-icon<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>speed<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>播放速度<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzIwMjEyNCI+PHBhdGggZD0iTTguNTkgMTYuNTlMMTMuMTcgMTIgOC41OSA3LjQxIDEwIDZsNiA2LTYgNnoiLz48L3N2Zz4=<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-arrow-icon<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>arrow<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token comment">&lt;!-- 倍速选项子菜单 --></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capSpeedMenu<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-popover hidden cap-speed-popover<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>            <span class="token comment">&lt;!-- 返回主菜单 --></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-item cap-menu-header<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capBackToMainBtn<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>data:image/svg+xml;base64,PHN2ZyBmaWxsPSJXaW5kb3dUZXh0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz4KICAgIDxwYXRoIGQ9Ik0yMCAxMUg3LjgzbDUuNTktNS41OUwxMiA0bC04IDggOCA4IDEuNDEtMS40MUw3LjgzIDEzSDIwdi0yeiIvPgo8L3N2Zz4=<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-menu-icon<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>back<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span>播放速度<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-divider<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>            <span class="token comment">&lt;!-- 倍速选项 --></span>            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cap-speed-list<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>capSpeedOptions<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h3><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> audioPlayer <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'PlayAudio'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capPlayPauseBtn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capPlayPauseBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capPlayIcon <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capPlayIcon'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capPauseIcon <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capPauseIcon'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capCurrentTime <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capCurrentTime'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capDuration <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capDuration'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capMuteBtn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capMuteBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capVolumeIcon <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capVolumeIcon'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capMuteIcon <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capMuteIcon'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capMoreBtn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capMoreBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capMainMenu <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capMainMenu'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capSpeedMenu <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capSpeedMenu'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capDownloadBtn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capDownloadBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capOpenSpeedBtn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capOpenSpeedBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capBackToMainBtn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capBackToMainBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> capSpeedOptionsContainer <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'capSpeedOptions'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">let</span> previousVolume <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">capFormatTime</span><span class="token punctuation">(</span><span class="token parameter">seconds</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isNaN</span><span class="token punctuation">(</span>seconds<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token function">isFinite</span><span class="token punctuation">(</span>seconds<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token string">"0:00"</span><span class="token punctuation">;</span>    <span class="token keyword">const</span> m <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>seconds <span class="token operator">/</span> <span class="token number">60</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">const</span> s <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>seconds <span class="token operator">%</span> <span class="token number">60</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>m<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>s <span class="token operator">&lt;</span> <span class="token number">10</span> <span class="token operator">?</span> <span class="token string">'0'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>s<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token keyword">function</span> <span class="token function">setupCustomSlider</span><span class="token punctuation">(</span><span class="token parameter">containerId<span class="token punctuation">,</span> fillId<span class="token punctuation">,</span> thumbId<span class="token punctuation">,</span> onChange</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token keyword">const</span> container <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>containerId<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">const</span> fill <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>fillId<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">const</span> thumb <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>thumbId<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">let</span> isDragging <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>    <span class="token keyword">function</span> <span class="token function">update</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token keyword">const</span> rect <span class="token operator">=</span> container<span class="token punctuation">.</span><span class="token function">getBoundingClientRect</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token keyword">let</span> clientX <span class="token operator">=</span> e<span class="token punctuation">.</span>clientX<span class="token punctuation">;</span>        <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>touches <span class="token operator">&amp;&amp;</span> e<span class="token punctuation">.</span>touches<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            clientX <span class="token operator">=</span> e<span class="token punctuation">.</span>touches<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>clientX<span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>        <span class="token keyword">if</span> <span class="token punctuation">(</span>clientX <span class="token operator">===</span> <span class="token keyword">undefined</span><span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>        <span class="token keyword">let</span> percentage <span class="token operator">=</span> <span class="token punctuation">(</span>clientX <span class="token operator">-</span> rect<span class="token punctuation">.</span>left<span class="token punctuation">)</span> <span class="token operator">/</span> rect<span class="token punctuation">.</span>width<span class="token punctuation">;</span>        percentage <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> percentage<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        fill<span class="token punctuation">.</span>style<span class="token punctuation">.</span>width <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>percentage <span class="token operator">*</span> <span class="token number">100</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">%</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>        thumb<span class="token punctuation">.</span>style<span class="token punctuation">.</span>left <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>percentage <span class="token operator">*</span> <span class="token number">100</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">%</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>        <span class="token keyword">if</span> <span class="token punctuation">(</span>onChange<span class="token punctuation">)</span> <span class="token function">onChange</span><span class="token punctuation">(</span>percentage<span class="token punctuation">,</span> isDragging<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>    <span class="token keyword">function</span> <span class="token function">onDown</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        isDragging <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>        container<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'dragging'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">update</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mousemove'</span><span class="token punctuation">,</span> onMove<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseup'</span><span class="token punctuation">,</span> onUp<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'touchmove'</span><span class="token punctuation">,</span> onMove<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">passive</span><span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'touchend'</span><span class="token punctuation">,</span> onUp<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>    <span class="token keyword">function</span> <span class="token function">onMove</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>isDragging<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>        e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">update</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>    <span class="token keyword">function</span> <span class="token function">onUp</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        isDragging <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>        container<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">'dragging'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">update</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'mousemove'</span><span class="token punctuation">,</span> onMove<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseup'</span><span class="token punctuation">,</span> onUp<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'touchmove'</span><span class="token punctuation">,</span> onMove<span class="token punctuation">)</span><span class="token punctuation">;</span>        document<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'touchend'</span><span class="token punctuation">,</span> onUp<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>    container<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mousedown'</span><span class="token punctuation">,</span> onDown<span class="token punctuation">)</span><span class="token punctuation">;</span>    container<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'touchstart'</span><span class="token punctuation">,</span> onDown<span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">passive</span><span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token function">setPercentage</span><span class="token punctuation">(</span><span class="token parameter">pct</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>isDragging<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            <span class="token keyword">const</span> safePct <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> pct<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            fill<span class="token punctuation">.</span>style<span class="token punctuation">.</span>width <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>safePct <span class="token operator">*</span> <span class="token number">100</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">%</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>            thumb<span class="token punctuation">.</span>style<span class="token punctuation">.</span>left <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>safePct <span class="token operator">*</span> <span class="token number">100</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">%</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token keyword">const</span> updateSeekUI <span class="token operator">=</span> <span class="token function">setupCustomSlider</span><span class="token punctuation">(</span><span class="token string">'capSeekSlider'</span><span class="token punctuation">,</span> <span class="token string">'capSeekFill'</span><span class="token punctuation">,</span> <span class="token string">'capSeekThumb'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">pct<span class="token punctuation">,</span> dragging</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>dragging<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        capCurrentTime<span class="token punctuation">.</span>textContent <span class="token operator">=</span> <span class="token function">capFormatTime</span><span class="token punctuation">(</span>pct <span class="token operator">*</span> <span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>duration <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>        audioPlayer<span class="token punctuation">.</span>currentTime <span class="token operator">=</span> pct <span class="token operator">*</span> <span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>duration <span class="token operator">||</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> updateVolumeUI <span class="token operator">=</span> <span class="token function">setupCustomSlider</span><span class="token punctuation">(</span><span class="token string">'capVolumeSlider'</span><span class="token punctuation">,</span> <span class="token string">'capVolumeFill'</span><span class="token punctuation">,</span> <span class="token string">'capVolumeThumb'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">pct</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    audioPlayer<span class="token punctuation">.</span>muted <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>    audioPlayer<span class="token punctuation">.</span>volume <span class="token operator">=</span> pct<span class="token punctuation">;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>pct <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> previousVolume <span class="token operator">=</span> pct<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>audioPlayer<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'loadedmetadata'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    capDuration<span class="token punctuation">.</span>textContent <span class="token operator">=</span> <span class="token function">capFormatTime</span><span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>duration<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">updateSeekUI</span><span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>currentTime <span class="token operator">/</span> audioPlayer<span class="token punctuation">.</span>duration<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token function">updateVolumeUI</span><span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>volume<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>audioPlayer<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'timeupdate'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>duration<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        capCurrentTime<span class="token punctuation">.</span>textContent <span class="token operator">=</span> <span class="token function">capFormatTime</span><span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>currentTime<span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token function">updateSeekUI</span><span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>currentTime <span class="token operator">/</span> audioPlayer<span class="token punctuation">.</span>duration<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>audioPlayer<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'play'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    capPlayIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'none'</span><span class="token punctuation">;</span>    capPauseIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'block'</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>audioPlayer<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'pause'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    capPlayIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'block'</span><span class="token punctuation">;</span>    capPauseIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'none'</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>audioPlayer<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'volumechange'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>volume <span class="token operator">===</span> <span class="token number">0</span> <span class="token operator">||</span> audioPlayer<span class="token punctuation">.</span>muted<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        capVolumeIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'none'</span><span class="token punctuation">;</span>        capMuteIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'block'</span><span class="token punctuation">;</span>        <span class="token function">updateVolumeUI</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>        capVolumeIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'block'</span><span class="token punctuation">;</span>        capMuteIcon<span class="token punctuation">.</span>style<span class="token punctuation">.</span>display <span class="token operator">=</span> <span class="token string">'none'</span><span class="token punctuation">;</span>        <span class="token function">updateVolumeUI</span><span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>volume<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>capPlayPauseBtn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    audioPlayer<span class="token punctuation">.</span>paused <span class="token operator">?</span> audioPlayer<span class="token punctuation">.</span><span class="token function">play</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> audioPlayer<span class="token punctuation">.</span><span class="token function">pause</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>capMuteBtn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>audioPlayer<span class="token punctuation">.</span>volume <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>audioPlayer<span class="token punctuation">.</span>muted<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        previousVolume <span class="token operator">=</span> audioPlayer<span class="token punctuation">.</span>volume<span class="token punctuation">;</span>        audioPlayer<span class="token punctuation">.</span>volume <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>        audioPlayer<span class="token punctuation">.</span>muted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>        audioPlayer<span class="token punctuation">.</span>muted <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>        audioPlayer<span class="token punctuation">.</span>volume <span class="token operator">=</span> previousVolume <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">?</span> previousVolume <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>capMoreBtn<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>capMainMenu<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>capSpeedMenu<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        capSpeedMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>capMoreBtn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> capSpeedMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>        capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        capSpeedMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>capOpenSpeedBtn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    capSpeedMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">const</span> activeOption <span class="token operator">=</span> capSpeedMenu<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.cap-speed-option.active'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>activeOption<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        <span class="token keyword">const</span> menuHalfHeight <span class="token operator">=</span> capSpeedMenu<span class="token punctuation">.</span>clientHeight <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span>        <span class="token keyword">const</span> optionHalfHeight <span class="token operator">=</span> activeOption<span class="token punctuation">.</span>clientHeight <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span>        capSpeedMenu<span class="token punctuation">.</span>scrollTop <span class="token operator">=</span> activeOption<span class="token punctuation">.</span>offsetTop <span class="token operator">-</span> menuHalfHeight <span class="token operator">+</span> optionHalfHeight<span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>capBackToMainBtn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    capSpeedMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>capDownloadBtn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    capMainMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>audioPlayer<span class="token punctuation">.</span>src<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>        console<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"当前音频源为空"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token keyword">return</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>        <span class="token keyword">const</span> a <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    a<span class="token punctuation">.</span>href <span class="token operator">=</span> audioPlayer<span class="token punctuation">.</span>src<span class="token punctuation">;</span>    <span class="token keyword">const</span> filename <span class="token operator">=</span> audioPlayer<span class="token punctuation">.</span>src<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token string">'audio.mp3'</span><span class="token punctuation">;</span>    a<span class="token punctuation">.</span>download <span class="token operator">=</span> filename<span class="token punctuation">;</span>    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>    a<span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> speedRates <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0.25</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">0.75</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1.25</span><span class="token punctuation">,</span> <span class="token number">1.5</span><span class="token punctuation">,</span> <span class="token number">1.75</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">renderSpeedOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    capSpeedOptionsContainer<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>    speedRates<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">rate</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>        <span class="token keyword">const</span> div <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'div'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        div<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">cap-speed-option </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>rate <span class="token operator">===</span> audioPlayer<span class="token punctuation">.</span>playbackRate <span class="token operator">?</span> <span class="token string">'active'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>        div<span class="token punctuation">.</span>textContent <span class="token operator">=</span> rate <span class="token operator">===</span> <span class="token number">1</span> <span class="token operator">?</span> <span class="token string">'正常'</span> <span class="token operator">:</span> rate<span class="token punctuation">;</span>                div<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>            e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            audioPlayer<span class="token punctuation">.</span>playbackRate <span class="token operator">=</span> rate<span class="token punctuation">;</span>            <span class="token function">renderSpeedOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            capSpeedMenu<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'hidden'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        capSpeedOptionsContainer<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>div<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token function">renderSpeedOptions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h3><pre class="line-numbers language-css" data-language="css"><code class="language-css"><span class="token selector">*,*::before,*::after</span> <span class="token punctuation">&#123;</span>    <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">#chromeAudioPlayer.chrome-audio-player</span> <span class="token punctuation">&#123;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">background-color</span><span class="token punctuation">:</span> #f1f3f4<span class="token punctuation">;</span>    <span class="token property">border-radius</span><span class="token punctuation">:</span> 30px<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 54px<span class="token punctuation">;</span>    <span class="token property">padding</span><span class="token punctuation">:</span> 0 6px<span class="token punctuation">;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>    <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span>    <span class="token property">font-family</span><span class="token punctuation">:</span> Roboto<span class="token punctuation">,</span> Arial<span class="token punctuation">,</span> sans-serif<span class="token punctuation">;</span>    <span class="token property">color</span><span class="token punctuation">:</span> #202124<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">#chromeAudioPlayer.chrome-audio-player button.cap-btn,.chrome-audio-player .cap-btn</span> <span class="token punctuation">&#123;</span>    <span class="token property">background</span><span class="token punctuation">:</span> transparent<span class="token punctuation">;</span>    <span class="token property">border</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>    <span class="token property">box-shadow</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>    <span class="token property">border-radius</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 40px<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 40px<span class="token punctuation">;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">justify-content</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span>    <span class="token property">outline</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>    <span class="token property">flex-shrink</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>    <span class="token property">padding</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>    <span class="token property">transition</span><span class="token punctuation">:</span> background-color 0.2s<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">#chromeAudioPlayer.chrome-audio-player button.cap-btn:hover</span> <span class="token punctuation">&#123;</span>     <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.06<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">#chromeAudioPlayer.chrome-audio-player button.cap-btn:active</span> <span class="token punctuation">&#123;</span>     <span class="token property">background-color</span><span class="token punctuation">:</span> <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-btn img</span> <span class="token punctuation">&#123;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span>    <span class="token property">opacity</span><span class="token punctuation">:</span> 0.8<span class="token punctuation">;</span>    <span class="token property">pointer-events</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-time</span> <span class="token punctuation">&#123;</span>    <span class="token property">font-size</span><span class="token punctuation">:</span> 14px<span class="token punctuation">;</span>    <span class="token property">margin</span><span class="token punctuation">:</span> 0 10px 0 0<span class="token punctuation">;</span>    <span class="token property">user-select</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>    <span class="token property">flex-shrink</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>    <span class="token property">min-width</span><span class="token punctuation">:</span> 65px<span class="token punctuation">;</span>    <span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">letter-spacing</span><span class="token punctuation">:</span> 0.2px<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-progress-container</span> <span class="token punctuation">&#123;</span>    <span class="token property">flex</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span>    <span class="token property">margin</span><span class="token punctuation">:</span> 0 10px<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-custom-slider</span> <span class="token punctuation">&#123;</span>    <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>    <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">touch-action</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-track</span> <span class="token punctuation">&#123;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>    <span class="token property">background</span><span class="token punctuation">:</span> #dfdfdf<span class="token punctuation">;</span>    <span class="token property">border-radius</span><span class="token punctuation">:</span> 2px<span class="token punctuation">;</span>    <span class="token property">pointer-events</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-fill</span> <span class="token punctuation">&#123;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 0%<span class="token punctuation">;</span>    <span class="token property">background</span><span class="token punctuation">:</span> #202124<span class="token punctuation">;</span>    <span class="token property">border-radius</span><span class="token punctuation">:</span> 2px<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-thumb</span> <span class="token punctuation">&#123;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 10px<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 10px<span class="token punctuation">;</span>    <span class="token property">background</span><span class="token punctuation">:</span> transparent<span class="token punctuation">;</span>    <span class="token property">border-radius</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>    <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>    <span class="token property">top</span><span class="token punctuation">:</span> 50%<span class="token punctuation">;</span>    <span class="token property">left</span><span class="token punctuation">:</span> 0%<span class="token punctuation">;</span>    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translate</span><span class="token punctuation">(</span>-50%<span class="token punctuation">,</span> -50%<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token property">transition</span><span class="token punctuation">:</span> background 0.2s<span class="token punctuation">,</span> transform 0.1s<span class="token punctuation">;</span>    <span class="token property">pointer-events</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-custom-slider:hover .cap-thumb,.chrome-audio-player .cap-custom-slider.dragging .cap-thumb</span> <span class="token punctuation">&#123;</span>    <span class="token property">background</span><span class="token punctuation">:</span> #202124<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-custom-slider.dragging .cap-thumb</span> <span class="token punctuation">&#123;</span>    <span class="token property">transform</span><span class="token punctuation">:</span> <span class="token function">translate</span><span class="token punctuation">(</span>-50%<span class="token punctuation">,</span> -50%<span class="token punctuation">)</span> <span class="token function">scale</span><span class="token punctuation">(</span>1.3<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-volume-group</span> <span class="token punctuation">&#123;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">flex-direction</span><span class="token punctuation">:</span> row-reverse<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-volume-panel</span> <span class="token punctuation">&#123;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>    <span class="token property">opacity</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>    <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">transition</span><span class="token punctuation">:</span> width 0.3s <span class="token function">cubic-bezier</span><span class="token punctuation">(</span>0.4<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.2<span class="token punctuation">,</span> 1<span class="token punctuation">)</span><span class="token punctuation">,</span> opacity 0.3s ease<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-vol-slider</span> <span class="token punctuation">&#123;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 60px<span class="token punctuation">;</span>    <span class="token property">margin-right</span><span class="token punctuation">:</span> 5px<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-volume-group:hover .cap-volume-panel</span> <span class="token punctuation">&#123;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 60px<span class="token punctuation">;</span>    <span class="token property">opacity</span><span class="token punctuation">:</span> 1<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-menu-wrapper</span> <span class="token punctuation">&#123;</span>     <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-popover</span> <span class="token punctuation">&#123;</span>    <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>    <span class="token property">bottom</span><span class="token punctuation">:</span> 50px<span class="token punctuation">;</span>    <span class="token property">right</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>    <span class="token property">background</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span>    <span class="token property">border-radius</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>    <span class="token property">box-shadow</span><span class="token punctuation">:</span> 0 2px 8px <span class="token function">rgba</span><span class="token punctuation">(</span>0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0<span class="token punctuation">,</span> 0.15<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token property">min-width</span><span class="token punctuation">:</span> 160px<span class="token punctuation">;</span>    <span class="token property">padding</span><span class="token punctuation">:</span> 8px 0<span class="token punctuation">;</span>    <span class="token property">z-index</span><span class="token punctuation">:</span> 100<span class="token punctuation">;</span>    <span class="token property">font-size</span><span class="token punctuation">:</span> 13px<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-speed-popover</span> <span class="token punctuation">&#123;</span>     <span class="token property">min-width</span><span class="token punctuation">:</span> 160px<span class="token punctuation">;</span>     <span class="token property">max-height</span><span class="token punctuation">:</span> 250px<span class="token punctuation">;</span>     <span class="token property">overflow-y</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-popover.hidden</span> <span class="token punctuation">&#123;</span>     <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-menu-item</span> <span class="token punctuation">&#123;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">padding</span><span class="token punctuation">:</span> 10px 16px<span class="token punctuation">;</span>    <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span>    <span class="token property">color</span><span class="token punctuation">:</span> #202124<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-menu-item:hover</span> <span class="token punctuation">&#123;</span>     <span class="token property">background</span><span class="token punctuation">:</span> #f1f3f4<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-menu-icon</span> <span class="token punctuation">&#123;</span>     <span class="token property">width</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>     <span class="token property">height</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>     <span class="token property">margin-right</span><span class="token punctuation">:</span> 12px<span class="token punctuation">;</span>     <span class="token property">opacity</span><span class="token punctuation">:</span> 0.7<span class="token punctuation">;</span>     <span class="token property">pointer-events</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-arrow-icon</span> <span class="token punctuation">&#123;</span>     <span class="token property">width</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>     <span class="token property">height</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>     <span class="token property">margin-left</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span>     <span class="token property">opacity</span><span class="token punctuation">:</span> 0.5<span class="token punctuation">;</span>     <span class="token property">pointer-events</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-divider</span> <span class="token punctuation">&#123;</span>     <span class="token property">height</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span>     <span class="token property">background</span><span class="token punctuation">:</span> #e0e0e0<span class="token punctuation">;</span>     <span class="token property">margin</span><span class="token punctuation">:</span> 8px 0<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-speed-option</span> <span class="token punctuation">&#123;</span>    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>    <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>    <span class="token property">padding</span><span class="token punctuation">:</span> 10px 40px 10px 16px<span class="token punctuation">;</span>    <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span>    <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-speed-option:hover</span> <span class="token punctuation">&#123;</span>     <span class="token property">background</span><span class="token punctuation">:</span> #f1f3f4<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token selector">.chrome-audio-player .cap-speed-option.active::before</span> <span class="token punctuation">&#123;</span>    <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">;</span>    <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span>    <span class="token property">right</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>    <span class="token property">width</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>    <span class="token property">height</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span>    <span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span><span class="token string url">"data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23202124'%3e%3cpath d='M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z'/%3e%3c/svg%3e"</span><span class="token punctuation">)</span></span><span class="token punctuation">;</span>    <span class="token property">background-size</span><span class="token punctuation">:</span> contain<span class="token punctuation">;</span>    <span class="token property">background-repeat</span><span class="token punctuation">:</span> no-repeat<span class="token punctuation">;</span>    <span class="token property">background-position</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/%E7%BA%AFDOM%E5%A4%8D%E5%88%BBChrome%E9%BB%98%E8%AE%A4%E9%9F%B3%E9%A2%91%E6%92%AD%E6%94%BE%E5%99%A8</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/%E7%BA%AFDOM%E5%A4%8D%E5%88%BBChrome%E9%BB%98%E8%AE%A4%E9%9F%B3%E9%A2%91%E6%92%AD%E6%94%BE%E5%99%A8"/>
    <published>2026-06-13T09:20:37.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>在网页中，音频播放是一个再经典不过的需求。通常我们直接用 <code>&lt;audio src=&quot;https://example.com/example.mp3&quot; controls&gt;&lt;/audio&gt;</code> 就能搞定。但只要你对 UI 有一点点追求，很快就会遇到两个让人抓狂的痛点：</p>
<ol>
<li><strong>多端样式分裂</strong>：Chrome]]>
    </summary>
    <title>纯DOM复刻Chrome默认音频播放器</title>
    <updated>2026-06-13T09:25:25.526Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Rust" scheme="https://hcyhub.com/tags/Rust/"/>
    <category term="Lepton" scheme="https://hcyhub.com/tags/Lepton/"/>
    <category term="WebAssembly" scheme="https://hcyhub.com/tags/WebAssembly/"/>
    <category term="前端" scheme="https://hcyhub.com/tags/%E5%89%8D%E7%AB%AF/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>在上篇博文中，我分享了针对桌面端开发的<a href="/%E7%BC%96%E7%A8%8B/Lepton%20JPG%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%E4%B8%89%E4%BB%B6%E5%A5%97">Lepton 三件套</a>（TinyLep、LepViewer、LepThumb）。那套工具帮我高效存档了250GB照片，且有着极佳的使用体验。</p><p>但随着我这几天的使用，新的需求出现了：如果我想要在在线相册里查看我的照片，浏览器是不认识Lep格式文件的啊，如何在浏览器里在线查看Lep文件呢？为了填补这个空白，我开发了 Lepton 家族的第四个成员：**<a href="https://github.com/2010HCY/LeptonWASM">Lepton WASM</a>**。</p><h3 id="为什么需要-Lepton-WASM？"><a href="#为什么需要-Lepton-WASM？" class="headerlink" title="为什么需要 Lepton WASM？"></a>为什么需要 Lepton WASM？</h3><p>在 Web 环境下处理 <code>.lep</code> 文件面临两个核心挑战：</p><ol><li><strong>兼容性</strong>：由于<code>.lep</code>并不是通用格式，浏览器无法查看Lep文件</li><li><strong>性能</strong>：Lepton 这种针对 DCT 系数重组的算法，计算量远大于普通压缩。如果用纯 JavaScript 编写解码器，速度会慢到令人绝望。</li></ol><p>得益于 Rust 优秀的生态，我基于微软开源的 <code>lepton_jpeg_rust</code> 核心，利用 <strong>WebAssembly (WASM)</strong> 技术将其编译成了可在浏览器运行的二进制模块，该WASM文件完整版仅337KB，若只包括仅查看代码，WASM体积甚至可以精简到仅249KB，极其轻量<del>还没我一张照片大</del></p><h4 id="硬件加速：AVX-To-WASM-SIMD"><a href="#硬件加速：AVX-To-WASM-SIMD" class="headerlink" title="硬件加速：AVX To WASM SIMD"></a>硬件加速：AVX To WASM SIMD</h4><p>在桌面环境下，Lepton可以使用AVX2指令集提升速度，但在 WASM 环境下，我们无法直接操作 x86 的 256 位寄存器。</p><p>好在 WASM 标准已经引入了 <strong>SIMD (单指令多数据流)</strong> 支持。通过开启 <code>simd128</code> 特性，Lepton WASM 可以在浏览器中调用 CPU 的 128 位向量指令。实测开启 SIMD 后，**解码速度提升了约 25%**。这意味着在现代浏览器中，解码一张高清照片仅需不到一秒。</p><p>具体性能提升可以查看下表：</p><blockquote><p>时间取三次的平均值，图片大小为1.45MB</p></blockquote><table><thead><tr><th></th><th>压缩（SIMD 加速）</th><th>解压（SIMD 加速）</th><th>压缩（兼容版）</th><th>解压（兼容版）</th></tr></thead><tbody><tr><td>平均时间</td><td><strong>431 ms</strong></td><td><strong>421 ms</strong></td><td><strong>597 ms</strong></td><td><strong>577 ms</strong></td></tr><tr><td>第一次耗时</td><td>438 ms</td><td>410 ms</td><td>596 ms</td><td>589 ms</td></tr><tr><td>第二次耗时</td><td>423 ms</td><td>437 ms</td><td>599 ms</td><td>555 ms</td></tr><tr><td>第三次耗时</td><td>432 ms</td><td>416 ms</td><td>596 ms</td><td>588 ms</td></tr></tbody></table><blockquote><p>PS：尽管 WASM 让浏览器具备了近乎原生的计算能力，但 Web 环境由于其<strong>沙盒机制</strong>与<strong>单线程调度</strong>的特性，性能表现会很大程度上受到环境干扰。</p><ol><li><strong>资源竞争</strong>：解压过程属于计算密集型任务，如果此时浏览器正在进行复杂的 DOM 渲染或 CSS 动画，可能会产生调度冲突，导致耗时异常波动（极端情况下可能出现长达数秒的延迟）。</li><li><strong>异步建议</strong>：为了避免阻塞 UI 交互，我强烈建议在 <strong>Web Worker</strong> 中运行编解码逻辑。这样即使是在进行高负载计算，页面依然可以保持丝滑滚动。</li><li><strong>场景选型</strong>：Web 版的核心意义在于零依赖、即时预览、小规模快速处理，给跨平台查看兼容性做个兜底。如果你有数以万计的照片需要进行大规模批处理，桌面端的 <strong>TinyLep</strong> 具备无可比拟的性能优势。</li></ol></blockquote><h4 id="极简的使用方法"><a href="#极简的使用方法" class="headerlink" title="极简的使用方法"></a>极简的使用方法</h4><p>为了兼顾不同的使用场景，我准备了两个版本的包：</p><ul><li>**Viewer (查看版)**：精简掉所有编码代码，体积极小。适合只需要在网页展示图片，不需要在线压缩的场景。</li><li>**Full (全能版)**：包含完整的编解码能力。你可以直接用它做一个在线压缩工具，所有计算都在用户本地浏览器完成。</li></ul><p>为了让展示 <code>.lep</code> 文件像展示原生图片一样简单，我利用 Web Components 封装了一个自定义标签 <code>&lt;lep-img&gt;</code>，无需进行复杂的配置，只需要引入JS，然后再使用自定义标签<code>&lt;lep-img&gt;</code>即可插入图片</p><pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>lep-img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>images/my_photo.lep<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>lep-img</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>目前大部分主流的浏览器都支持SIMD，本项目可以启用SIMD加速处理，这是目前的支持情况：</p><ul><li>Chrome ≥ 91 (2021年5月)</li><li>Firefox ≥ 89 (2021年6月)</li><li>Safari ≥ 16.4 (2023年3月)</li><li>Node.js ≥ 16.4 (2021年6月)</li></ul><p>为了照顾一些老版本浏览器，本项目分为SIMD加速版和兼容版，可以通过在JS里使用<a href="https://github.com/GoogleChromeLabs/wasm-feature-detect">wasm-feature-detect</a>这个项目检测浏览器是否支持SIMD，然后自动加载最优版本。</p><p>示例：</p><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> simd <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">"https://unpkg.com/wasm-feature-detect?module"</span><span class="token punctuation">;</span><span class="token function">simd</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">isSupported</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">if</span> <span class="token punctuation">(</span>isSupported<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// 加载SIMD加速版</span>    <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>    <span class="token comment">// 加载兼容版</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>你可以在控制台中输入以下JS代码查询浏览器是否支持SIMD：</p><pre class="line-numbers language-none"><code class="language-none">import(&quot;https:&#x2F;&#x2F;unpkg.com&#x2F;wasm-feature-detect?module&quot;).then(module &#x3D;&gt; &#123;    module.simd().then(isSupported &#x3D;&gt; &#123;        console.log(&#96;SIMD: $&#123;isSupported&#125;&#96;);    &#125;);&#125;);<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>或者你也可以访问<a href="https://page.hcyhub.com/%E5%B0%8F%E5%B7%A5%E5%85%B7/SIMD%E6%94%AF%E6%8C%81%E6%80%A7%E6%A3%80%E6%B5%8B/">WebAssembly SIMD 检测</a>查询自己的浏览器是否支持SIMD</p><p>你可以访问此Demo查看Lep在线查看效果：<a href="https://page.hcyhub.com/%E5%B0%8F%E5%B7%A5%E5%85%B7/Lepton%20Web/DemoLepViewer/">Lep在线查看示例</a></p><img src="./../../images/LeptonWASM/Lep在线查看示例.png" alt="Lep在线查看示例" style="zoom:67%;" /><img src="./../../images/LeptonWASM/Lepton 在线无损压缩、解压JPEG.png" alt="Lepton 在线无损压缩、解压JPEG" style="zoom:67%;" /><blockquote><p>这里不对JS代码方面做过多介绍，感兴趣可以查看Demo实现</p></blockquote><h3 id="Lepton-工具全家桶"><a href="#Lepton-工具全家桶" class="headerlink" title="Lepton 工具全家桶"></a>Lepton 工具全家桶</h3><p>至此，Lepton的有关工具又新增了一个成员，现在不仅可以本地批量压缩、快速查看，还可以在浏览器中浏览了。</p><ol><li>**<a href="https://github.com/2010HCY/TinyLep">TinyLep</a>**：负责大规模批量压缩，把硬盘里的 JPG 瘦身。</li><li>**<a href="https://github.com/2010HCY/LepViewer">LepViewer</a>**：负责本地电脑的即时预览。</li><li>**<a href="https://github.com/2010HCY/LepViewer/tree/main/LepThumb">LepThumb</a>**：负责 Windows 资源管理器的缩略图显示。</li><li>**<a href="https://github.com/2010HCY/LeptonWASM">LeptonWASM</a>**：负责在网页端、H5、在线相册中原生支持预览和处理。</li></ol><p>如果你也有在线查看Lep图片的需求，或者是单纯只想在线压个JPG试试水，欢迎尝试本项目。</p><ul><li><strong>项目地址</strong>：<a href="https://github.com/2010HCY/LeptonWASM">GitHub - LeptonWASM</a></li><li><strong>在线演示</strong>：<ul><li><a href="https://page.hcyhub.com/...">SIMD 支持性检测</a></li><li><a href="https://page.hcyhub.com/...">Lep 在线查看 Demo</a></li><li><a href="https://page.hcyhub.com/...">在线无损压缩器</a></li></ul></li></ul><p>阅读上一篇博文：<a href="/%E7%BC%96%E7%A8%8B/Lepton%20JPG%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%E4%B8%89%E4%BB%B6%E5%A5%97">Lepton 三件套</a></p><h4 id="赞赏"><a href="#赞赏" class="headerlink" title="赞赏"></a>赞赏</h4><p>如果这些工具帮到了你，或者为你节省了昂贵的对象存储（OSS&#x2F;S3）费用，欢迎打赏支持：</p><img src="./../../images/Lepton JPG无损压缩解压三件套/PayQrcode.jpg" alt="PayQrcode" style="zoom:50%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/Lepton%20WASM%EF%BC%9A%E5%9C%A8%E6%B5%8F%E8%A7%88%E5%99%A8%E9%87%8C%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%EF%BC%8C%E5%AE%9E%E7%8E%B0.lep%E5%9C%A8%E7%BA%BF%E6%9F%A5%E7%9C%8B</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/Lepton%20WASM%EF%BC%9A%E5%9C%A8%E6%B5%8F%E8%A7%88%E5%99%A8%E9%87%8C%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%EF%BC%8C%E5%AE%9E%E7%8E%B0.lep%E5%9C%A8%E7%BA%BF%E6%9F%A5%E7%9C%8B"/>
    <published>2026-05-14T14:34:29.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>在上篇博文中，我分享了针对桌面端开发的<a href="/%E7%BC%96%E7%A8%8B/Lepton%20JPG%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%E4%B8%89%E4%BB%B6%E5%A5%97">Lepton]]>
    </summary>
    <title>Lepton WASM：在浏览器里无损压缩解压，实现.lep在线查看</title>
    <updated>2026-05-14T15:59:22.260Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Rust" scheme="https://hcyhub.com/tags/Rust/"/>
    <category term="Tauri" scheme="https://hcyhub.com/tags/Tauri/"/>
    <category term="Lepton" scheme="https://hcyhub.com/tags/Lepton/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>最近在整理硬盘，手里有一个约 250GB 的照片库需要归档存放。因为都是原图，占用的空间实在不小，并且因为我要上传到云端，体积越大价格越贵，所以肯定是本地能压缩一点是一点，于是我开始寻找合适的压缩方案。</p><p>作为一个存档性质的照片集，我的核心要求是<strong>必须是无损压缩</strong>。所以，任何会改变哪怕一个像素、损失些许细节的有损压缩方案（比如转码成 WebP 或低画质 JPG）都被排除了。如果使用 7z 或 Zip 等通用压缩算法，不仅压缩率极低，而且过程非常缓慢。</p><p>经过一番搜索，我找到了 Dropbox 曾推出的 C++ 开源工具：**<a href="https://github.com/dropbox/lepton">（Dropbox&#x2F;Lepton）</a>**。</p><p>Lepton 是一个专门针对 JPEG 图像设计的无损压缩工具。因为它能“读懂”JPG，所以在能够完全无损（能够还原每个字节，MD5、SHA一致）的前提下，平均能将文件体积再压缩 20% 左右，速度和压缩率都非常理想。</p><h3 id="Lepton-三件套"><a href="#Lepton-三件套" class="headerlink" title="Lepton 三件套"></a>Lepton 三件套</h3><p>方案确定了，但在实际使用中遇到了阻碍。</p><p>首先，Dropbox 的官方仓库已被存档。顺藤摸瓜，我找到了微软重构并开源的<a href="https://github.com/microsoft/lepton_jpeg_rust">lepton_jpeg_rust</a>版本。Rust 版本更具安全性，正好可以结合 Tauri 进行桌面端开发。</p><p>其次，Lepton 本体是 CLI 命令行工具。虽然我大可以写一个脚本遍历压缩，但总觉得不大优雅，不能直观的看到任务进行到了哪，压缩成效。此外，压缩成 <code>.lep</code> 格式后，由于<code>.lep</code> 非通用格式，Windows 系统无法直接预览和查看，需要手动解压回JPG后才可被图片查看器打开，后续我要找图、查看图片会非常麻烦。</p><p>既然现成的工具不够顺手，我搜了搜也没有人造好了这个轮子，于是我决定自己整一套Lepton工具。</p><h4 id="1-查看器：LepViewer-查看器"><a href="#1-查看器：LepViewer-查看器" class="headerlink" title="1. 查看器：LepViewer 查看器"></a>1. 查看器：LepViewer 查看器</h4><p>为了快速方便的先查看一下我用CLI压缩好的<code>.lep</code>文件，于是我先做了Lep查看器**<a href="https://github.com/2010HCY/LepViewer/">LepViewer</a>**来试试水，实现双击Lep文件即可打开查看。</p><p>测试结果符合预期，将 <code>.lep</code> 文件关联后，双击即可像打开普通图片一样进行浏览、缩放，无需手动解压。</p><img src="./../../images/Lepton JPG无损压缩解压三件套/软件页面1.png" alt="软件页面1" style="zoom:67%;" /><img src="./../../images/Lepton JPG无损压缩解压三件套/效果1-1.1.0.png" alt="效果1-1.1.0" style="zoom:67%;" /><img src="./../../images/Lepton JPG无损压缩解压三件套/效果2-1.1.0.png" alt="效果2-1.1.0" style="zoom:67%;" /><h4 id="2-批量处理器：TinyLep-压缩工具"><a href="#2-批量处理器：TinyLep-压缩工具" class="headerlink" title="2. 批量处理器：TinyLep 压缩工具"></a>2. 批量处理器：TinyLep 压缩工具</h4><p>验证了查看功能后，我在 5 月 8 日顺势完成了批量压缩工具 **<a href="https://github.com/2010HCY/TinyLep/">TinyLep</a>**。</p><p>有了 GUI 界面，操作就直观多了。支持直接拖拽文件或文件夹，批量进行 JPG 与 LEP 的双向转换。界面上可以清晰地看到整体处理进度、每一张图片的压缩前后大小对比以及具体的压缩率。实测 1.36 GB 的照片集合，在开启 AVX 指令集构建的版本下，仅需58.49秒即可压缩完毕。</p><img src="./../../images/Lepton JPG无损压缩解压三件套/页面.png" alt="页面" style="zoom:67%;" /><img src="./../../images/Lepton JPG无损压缩解压三件套/压缩效果.png" alt="压缩效果" style="zoom:67%;" /><p>以下是关于启用AVX和不启用AVX指令集的性能对比</p><p>使用 480 张总计 1.36 GB 的 JPG 照片进行测试，兼容版 (x64) 与 AVX 指令集版的耗时对比如下：</p><table><thead><tr><th>操作</th><th>x64</th><th>AVX</th></tr></thead><tbody><tr><td>解压</td><td>41.38</td><td>39.28</td></tr><tr><td>压缩</td><td>1:01.64</td><td>58.49</td></tr></tbody></table><blockquote><p>注：计时为手动操作有误差，时间消耗主要在硬盘 I&#x2F;O 读取上。</p></blockquote><p>效果相当不错，我压缩我80GB照片集花了1小时整。</p><h4 id="3-Windows缩略图插件：LepThumb-缩略图插件"><a href="#3-Windows缩略图插件：LepThumb-缩略图插件" class="headerlink" title="3. Windows缩略图插件：LepThumb 缩略图插件"></a>3. Windows缩略图插件：LepThumb 缩略图插件</h4><p>原本以为到这里就大功告成了，但实际浏览那 250GB 压缩后的照片库时，我发现了一个致命问题：资源管理器里全是 LepViewer 的软件 Logo，没有缩略图供我查看。</p><p>虽然是存档级别的不常看，但偶尔需要检索找图时，没有缩略图快速筛选简直无从下手，我难不成还得一个个点击查找吗？于是这两天（5 月 8 日 - 9 日），我又制作了 Windows 系统的缩略图插件：**<a href="https://github.com/2010HCY/LepViewer/tree/main/LepThumb">LepThumb</a>**。</p><p>这也是制作过程中最恶心的一个，插件编译成 DLL 并注册到系统后，不仅缩略图死活不显示，甚至我加的日志也没有任何写入迹象，我在开发环境手动试着调用DLL，发现DLL正确的给我返回了缩略图没有任何报错——系统似乎根本没有加载这个 DLL。</p><p>经过漫长的排查丧心病狂的加调试信息均无效果，我一度怀疑是否是我注册方式不对，今天用左手开机让电脑不爽了？反复重启后均无效果，我服了，我手动写了一个脚本去模拟 Windows 资源管理器调用COM组件，在这次的调试信息中发现——是<strong>动态链接依赖</strong>的问题。在我的开发环境中存在了相关依赖，所以调用一切正常；但在资源管理器独立的运行环境中缺失了该依赖，导致 DLL 加载时直接退出，连写日志的代码都执行不到。</p><p>找到症结后，解决起来就很简单了。在 <code>Cargo.toml</code> 和<code>.cargo\config.toml</code>中配置静态链接，将依赖直接打包进 DLL 中：</p><pre class="line-numbers language-toml" data-language="toml"><code class="language-toml"><span class="token punctuation">[</span><span class="token table class-name">lib</span><span class="token punctuation">]</span><span class="token key property">crate-type</span> <span class="token punctuation">=</span> <span class="token punctuation">[</span><span class="token string">"cdylib"</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><pre class="line-numbers language-toml" data-language="toml"><code class="language-toml"><span class="token punctuation">[</span><span class="token table class-name">build</span><span class="token punctuation">]</span><span class="token key property">target</span> <span class="token punctuation">=</span> <span class="token string">"x86_64-pc-windows-msvc"</span><span class="token punctuation">[</span><span class="token table class-name">target.x86_64-pc-windows-msvc</span><span class="token punctuation">]</span><span class="token key property">rustflags</span> <span class="token punctuation">=</span> <span class="token punctuation">[</span><span class="token string">"-C"</span><span class="token punctuation">,</span> <span class="token string">"target-feature=+crt-static"</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>重新编译并注册 DLL 后，缩略图终于成功在文件管理器中显示了出来。单张（15MB 左右的 JPG）生成时间大约在 0.25 秒，配合 Windows 自身的缩略图缓存，只有首次打开文件夹时会稍有延迟，后续浏览非常流畅。</p><img src="./../../images/Lepton JPG无损压缩解压三件套/缩略图预览效果.png" alt="缩略图预览效果" style="zoom:67%;" /><h2 id="附录-Q-A"><a href="#附录-Q-A" class="headerlink" title="附录&#x2F;Q&amp;A"></a>附录&#x2F;Q&amp;A</h2><p><strong>Q1：既然要压缩，为什么不用 7z &#x2F; ZIP &#x2F; RAR？</strong><br><strong>A：</strong> 通用压缩算法对基于哈夫曼编码的 JPG 几乎无效（压缩率仅为 1%~2%）。本项目使用的是专门针对 JPG 内部 DCT 系数重组的算法，能实打实缩小 20%+ 的体积，可以这么理解，LZMA2是通用压缩算法，什么都能压，但是他们“看不懂”JPG，不知道如何表达使得体积更小。</p><p><strong>Q2：为什么不用 Caesium &#x2F; WebP 转码压缩？</strong><br><strong>A：</strong> 本项目是JPG的无损压缩，虽然说有损压缩能节省相当之多的空间，但是代价的不可逆损失了质量，本项目适合将原图压缩后存档长期保存。（而且如果不在意质量，你也完全可以有损压缩完后再使用本项目压缩啊，可以直接白嫖约20%的空间不损失任何质量）</p><p><strong>Q3：JXL 也支持 JPG 无损重组，为什么不用 JXL，反而搞个“非主流”的 Lepton？</strong><br><strong>A：</strong> 两个原因：<strong>第一，性能与体积 Lepton 远比JXL好；第二，JXL 的桌面生态太烂</strong></p><p>目前 Windows 资源管理器<strong>默认（原生）并不支持</strong> JXL 缩略图，普通用户需要自行去应用商店手动下载安装可选扩展（且该官方扩展<strong>仅限 Win11 24H2 及以上版本</strong>，Win10 甚至无法安装），或者折腾第三方 WIC 插件。我的工具是直接打包 GUI + 看图器，抹平了这些所有的使用门槛。</p><p>具体可以看一下对比：</p><table><thead><tr><th>压缩算法 &#x2F; 工具</th><th>实际耗时</th><th>压缩后体积</th><th>附加说明</th></tr></thead><tbody><tr><td><strong>本项目的 Lepton</strong></td><td><strong>0.51 秒</strong></td><td><strong>13,383 KB</strong></td><td>耗时<strong>包含了压缩 + 二次解压校验是否是真无损</strong>的总时间</td></tr><tr><td><strong>JXL 默认无损 (-e 7)</strong></td><td>0.63 秒</td><td>13,981 KB</td><td>纯压缩耗时</td></tr><tr><td><strong>JXL 极限无损 (-e 9)</strong></td><td>16.07 秒</td><td>13,966 KB</td><td>耗时是默认的 25 倍多压了个15KB</td></tr></tbody></table><pre class="line-numbers language-none"><code class="language-none">$ time .&#x2F;cjxl.exe DSC00016.jpg output_max.jxl -e 9JPEG XL encoder v0.11.2 332feb1 [AVX2,SSE2]Note: Implicit-default for JPEG is lossless-transcoding. To silence this message, set --lossless_jpeg&#x3D;(1|0).Encoding [JPEG, lossless transcode, effort: 9]Compressed to 13966.1 kB including containerreal    0m16.075suser    0m0.000ssys     0m0.000s<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><pre class="line-numbers language-none"><code class="language-none">$ time .&#x2F;cjxl.exe DSC00016.jpg output.jxlJPEG XL encoder v0.11.2 332feb1 [AVX2,SSE2]Note: Implicit-default for JPEG is lossless-transcoding. To silence this message, set --lossless_jpeg&#x3D;(1|0).Encoding [JPEG, lossless transcode, effort: 7]Compressed to 13981.0 kB including containerreal    0m0.638suser    0m0.000ssys     0m0.015s<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><pre class="line-numbers language-none"><code class="language-none">$ .&#x2F;lepton_jpeg_util.exe DSC00016.jpg 1.lep2026-05-09T09:24:38.446Z INFO  [lepton_jpeg::structs::lepton_file_writer] compressing to Lepton format2026-05-09T09:24:38.583Z INFO  [lepton_jpeg::structs::lepton_file_writer] Number of threads: 82026-05-09T09:24:38.766Z INFO  [lepton_jpeg::structs::lepton_file_writer] worker threads 984ms of CPU time in 150ms of wall time2026-05-09T09:24:38.766Z INFO  [lepton_jpeg::structs::lepton_file_writer] decompressing to verify contents2026-05-09T09:24:38.955Z INFO  [lepton_jpeg_util] compressed input 17414140, output 13703659 bytes (compression &#x3D; 27.1%)2026-05-09T09:24:38.956Z INFO  [lepton_jpeg_util] Main thread CPU: 187ms, Worker thread CPU: 2343 ms, walltime: 512 ms<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>在同等硬件下无损压缩一张 17.4MB 的原图，Lepton 的耗时仅为 0.51秒（且包含了二次解压的完整性校验）。而 JXL 就算是开启了极限压缩参数，体积依然比 Lepton 略大，且耗时显著更长。并且我提供了整套方案，使用体验甚至可以媲美未压缩JPG。</p><img src="./../../images/Lepton JPG无损压缩解压三件套/JXL、Lep对比.png" alt="JXL、Lep对比" style="zoom:80%;" /><p><strong>Q4：为什么要在已经有损的JPG基础上追求无损压缩？为什么不轻微降低质量来节省80%的空间？</strong><br><strong>A：</strong> 因为这个项目的初衷是<strong>“历史数据归档”</strong>。<br>很多人的硬盘里存有十几年来积累的海量 JPG 照片（且无法获取 RAW 原片）。在归档场景下，核心诉求是<strong>“保留文件当前状态的每一比特，绝不接受二次画质破坏”</strong>。有损压缩确实能省下 80% 的空间，但代价是永久且不可逆地改变了原图数据。</p><p>举个通俗的例子：假设你发现了一幅受损的古画，它对你很有意义。虽然它从被发现起就是有损的，但我选择把它妥善装裱在画框里无损保存，这完全是可以理解的。当然，任何人都有权利选择如何处置自己的东西，哪怕是把它揉成一团塞抽屉里。<br>再比如，我有一段 30年前绝版的老旧 MP3 音频，我当然可以直接把它再压缩一遍省空间，但面对珍贵的历史记忆，这种永久性的二次破坏是令人难以下手的。本工具服务的就是这群希望“既能节省空间，又能保证解压后校验值分毫不差”的群体。</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>至此，这套针对 JPG 的无损压缩“三件套”算是彻底完成了：</p><ol><li>**<a href="https://github.com/2010HCY/TinyLep/">TinyLep</a>**：批量无损压缩工具（可视化进度与压缩率）。</li><li>**<a href="https://github.com/2010HCY/LepViewer/">LepViewer</a>**：即时图片查看器（双击直接查看 <code>.lep</code> 文件）。</li><li>**<a href="https://github.com/2010HCY/LepViewer/tree/main/LepThumb">LepThumb</a>**：Windows 资源管理器缩略图插件。</li></ol><p>最近一两年，大家应该都深有体会：固态硬盘和机械硬盘的价格都在疯涨。在这个存储成本翻倍的节骨眼上，如果你也有大量的 JPG 原图（比如摄影原片、家庭相册）需要长期归档，且<strong>不能接受降画质的有损压缩</strong>，那强烈建议你试试这套工具。它能实打实地帮你省出约 20% 的空间（在一些信息熵低的图片里，压缩率甚至能达到夸张的 49.8%）。几十数百 GB 的空间，就这么白嫖出来了。</p><p>该项目本质上就是使用时间换空间，用压缩、解压的时间换更小的空间，这才是对现代PC的过剩性能的一个好的利用方式（也就压缩、解压的那几毫秒，大部分时间是在读取上）。在现在电脑面前这点开销压根算不上什么，不过如果需要经常导入第三方软件比如PS可能会比较麻烦，建议是压缩需要长期存档的部分。</p><p><strong>⚠️ 当然，也要说说局限性：</strong><br>由于 <code>.lep</code> 不是通用格式，如果你需要经常把照片导入 PS、PR 等第三方软件进行后期处理，每次解压会比较繁琐。因此，它最完美的适用场景是<strong>“冷数据&#x2F;温数据长期存档”</strong>。</p><p>如果有需要，可以去仓库里的<a href="https://github.com/2010HCY/LepViewer/releases">LepViewerReleases</a> | <a href="https://github.com/2010HCY/TinyLep/releases">TinyLep Releases</a>里获取编译好的EXE。MacOS、Linux需要自己编译了，没Mac机器，懒得去Linux下再编译一份。</p><p>目前项目已经开源，感谢微软团队开源的对 Lepton 工具的 Rust 移植与重构 <a href="https://github.com/microsoft/lepton_jpeg_rust">lepton_jpeg_rust</a>。</p><h4 id="赞赏"><a href="#赞赏" class="headerlink" title="赞赏"></a>赞赏</h4><p>如果这些工具对你有帮助，欢迎打赏支持：</p><img src="./../../images/Lepton JPG无损压缩解压三件套/PayQrcode.jpg" alt="PayQrcode" style="zoom:50%;" /><h2 id="更新日志"><a href="#更新日志" class="headerlink" title="更新日志"></a>更新日志</h2><h3 id="LepViewer-查看器"><a href="#LepViewer-查看器" class="headerlink" title="LepViewer 查看器"></a>LepViewer 查看器</h3><h4 id="1-1-0"><a href="#1-1-0" class="headerlink" title="1.1.0"></a>1.1.0</h4><ul><li>交互优化，滚轮缩放以鼠标为中心缩放，快速缩放以展示区域为中心点缩放。</li><li>优化图片打开效果，打开自动自适应窗口显示。</li><li>快速缩放组件使用DOM重写以保证一致性美观性。</li><li>信息丰富，底部状态栏会显示Lep文件大小。</li><li>优化另存为与复制逻辑，避免每次另存为、复制图片需要反复解压。</li></ul><img src="./../../images/Lepton JPG无损压缩解压三件套/效果1-1.1.0.png" alt="效果1-1.1.0" style="zoom:67%;" /><img src="./../../images/Lepton JPG无损压缩解压三件套/效果2-1.1.0.png" alt="效果2-1.1.0" style="zoom:67%;" /><img src="./../../images/Lepton JPG无损压缩解压三件套/快速缩放组件.png" alt="快速缩放组件" style="zoom:67%;" /><h4 id="1-0-0"><a href="#1-0-0" class="headerlink" title="1.0.0"></a>1.0.0</h4><p>有最基础的放大缩小查看功能</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/Lepton%20JPG%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%E4%B8%89%E4%BB%B6%E5%A5%97</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/Lepton%20JPG%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9%E8%A7%A3%E5%8E%8B%E4%B8%89%E4%BB%B6%E5%A5%97"/>
    <published>2026-05-09T04:38:03.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>最近在整理硬盘，手里有一个约 250GB 的照片库需要归档存放。因为都是原图，占用的空间实在不小，并且因为我要上传到云端，体积越大价格越贵，所以肯定是本地能压缩一点是一点，于是我开始寻找合适的压缩方案。</p>
<p>作为一个存档性质的照片集，我的核心要求是<strong>必须是无损压缩</strong>。所以，任何会改变哪怕一个像素、损失些许细节的有损压缩方案（比如转码成 WebP 或低画质 JPG）都被排除了。如果使用 7z 或 Zip]]>
    </summary>
    <title>Lepton JPG无损压缩解压三件套</title>
    <updated>2026-05-12T09:11:34.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="Meme-Classifier"><a href="#Meme-Classifier" class="headerlink" title="Meme Classifier"></a><strong>Meme Classifier</strong></h2><p>你是否在相册里屯了上千张Meme图，结果却在关键时刻脑子里已经想好了那张图，手指却在相册里划了三分钟还没找到？</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/photo_1535.png" alt="我之前收藏的屌图呢？"></p><p>Meme Classifier 为解决此痛点而生！它使用多模态 AI 模型（如 GPT-4o, Gemini）对你的Meme图进行批量OCR 识别文字、场景描述和标记标签。从此，找图只需输入关键词，快速从上千张图片中筛选出需要的那张Meme。</p><p>本项目的宗旨是一次分类，永久生效，相比于主流搜图使用的的语义向量模型，我选择了使用视觉模型识图，原因有三：</p><ol><li>精准搜索： OCR 能实现对图上文字的精确匹配，这是语义搜索难以企及的。</li><li>信息互补： AI 生成的场景描述弥补了无文字图片的搜索盲区。</li><li>后续成本低： 避开了语义模型在每次搜索时对 API 的依赖。处理是一次性投入的，一次处理永久受用</li></ol><h2 id="效果预览"><a href="#效果预览" class="headerlink" title="效果预览"></a>效果预览</h2><p>初次使用仅需点击“同步图片”，然后点击“一键处理”。系统就会开始向 AI 发送请求并接收返回的元信息存入本地 SQLite 数据库，过程支持设置并发（推荐设置为10~100，我使用Vertex Ai是能跑200并发，再高就会429了）</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/%E9%A6%96%E9%A1%B5.png" alt="首页"></p><p>处理好后，就可以在搜索页愉快地搜图了。可以搜索OCR文本、AI生成的画面描述、标签，或者是搜索某个特定路径下特定名字的Meme图。</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/%E6%90%9C%E7%B4%A2%E9%A1%B5.png" alt="搜索页"></p><p>可以在图库页面下查看所有已分类、未分类的Meme：</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/%E5%9B%BE%E5%BA%93.png" alt="图库"></p><p>点击卡片还可以显示AI分类的详细图片信息：</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/%E5%9B%BE%E7%89%87%E4%BF%A1%E6%81%AF.png" alt="图片信息"></p><p>若是对AI返回的内容不满意，还可以手动修改其内容：</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/%E6%89%8B%E5%8A%A8%E7%BC%96%E8%BE%91.png" alt="手动编辑"></p><p>分类器还有标签页，标签页主要是为了快速找到某一大类图片，比如我希望立刻找到所有有关猫猫的Meme、Minecraft（我的世界）Meme图，点一下即可跳转显示所有带有该标签的图片。不过目前AI还是很喜欢返回万金油标签，以后会做一个标签字典功能，避免AI创造多个语义相同的标签，可参考已有标签列表。</p><p><img src="/./../../images/Meme%E5%88%86%E7%B1%BB%E5%99%A8/%E6%A0%87%E7%AD%BE%E9%A1%B5.png" alt="标签页"></p><blockquote><p>PS：<br>分类GIF功能是使用FFmpeg将GIF转换成MP4后发送给AI的，需要自行下载FFmpeg并将其放入系统变量中。<br>若你使用OpenAI官方接口是不支持直接发送整个视频的，官方接口需要使用FFmpeg将GIF拆成一帧一帧的，所以如果使用官方接口需要自行魔改<br>若不是使用OpenAI官方接口，而是兼容OpenAI格式的Gemini或其他支持Hack写法的中转站是可以使用<code>data:video/mp4;</code>这样发送出去的</p></blockquote><h2 id="快速开始"><a href="#快速开始" class="headerlink" title="快速开始"></a>快速开始</h2><p>想要部署一个自己的Meme分类器也很简单，需要确保电脑上安装了Node.js以及FFmpeg（若有要分类GIF）</p><h3 id="1-安装依赖"><a href="#1-安装依赖" class="headerlink" title="1. 安装依赖"></a>1. 安装依赖</h3><p>克隆此仓库，然后执行：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token builtin class-name">cd</span> /path/to/Meme<span class="token function">npm</span> <span class="token function">install</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><h3 id="2-配置、启动"><a href="#2-配置、启动" class="headerlink" title="2. 配置、启动"></a>2. 配置、启动</h3><p>将 .env.example 重命名为 .env，并填入你的配置：</p><pre class="line-numbers language-none"><code class="language-none"># AI提供商，支持 &quot;vertex&quot; 或 &quot;openai&quot;AI_PROVIDER&#x3D;&quot;vertex&quot;# Vertex AI 配置 (AI_PROVIDER&#x3D;&quot;vertex&quot;时生效)AI_MODEL&#x3D;&quot;gemini-2.5-flash&quot;                     # 使用的视觉模型AI_CREDENTIALS_FILE&#x3D;&quot;xxx-xxx-xxx.json&quot;          # Google Cloud 服务账号的 JSON 密钥文件路径AI_LOCATION&#x3D;&quot;us-central1&quot;                       # Vertex AI 的区域，默认us-central1# OpenAI 兼容格式接口配置 (AI_PROVIDER&#x3D;&quot;openai&quot;时生效)OPENAI_MODEL&#x3D;&quot;gpt-4o-mini&quot;                      # 使用的视觉模型OPENAI_BASE_URL&#x3D;&quot;https:&#x2F;&#x2F;api.openai.com&#x2F;v1&quot;     # OpenAI API URL，默认为官方地址OPENAI_API_KEY&#x3D;&quot;&quot;                               # OpenAI API Key# 服务器配置PORT&#x3D;3000               # 服务器监听的端口，默认3000HOST&#x3D;localhost          # 服务器监听的主机地址# 代理信息USE_PROXY&#x3D;true                          # 是否启用代理，默认为trueHTTP_PROXY&#x3D;&quot;http:&#x2F;&#x2F;127.0.0.1:10809&quot;     # HTTP代理地址HTTPS_PROXY&#x3D;&quot;http:&#x2F;&#x2F;127.0.0.1:10809&quot;    # HTTPS代理地址<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="3-启动项目"><a href="#3-启动项目" class="headerlink" title="3. 启动项目"></a>3. 启动项目</h3><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> start<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>访问 <a href="http://localhost:3000/">http://localhost:3000</a> 即可开始使用。</p><h2 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h2><pre class="line-numbers language-none"><code class="language-none">meme-gallery-system&#x2F;├── MemeImg&#x2F;        # 存放Meme图（支持多级文件夹）├── web&#x2F;          # 前端静态资源├── db&#x2F;          # SQLite 数据库文件目录├── lib&#x2F;          # 后端模块│  ├── db.js       # 数据库操作│  ├── scanner.js     # 图片扫描│  ├── ai.js       # AI 交互逻辑 (Google Vertex AI、OpenAI)│  ├── api.js       # 后端API│  └── websocket.js    # WebSocket.js通信├── config.js       # 配置文件，在此配置AI参数├── server.js       # 后端├── package.json├── Prompt.md       # AI 提示词├── Prompt - GIF.md       # GIF动图 AI 提示词├── xxx-xxx-xxx.json    # 把获取到的GCP账户凭据放在这（仅使用Vertex AI时需要）├── README.md└── .env          # 配置文件，再次配置API密钥<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>目前仍有不少细节待完善，完善后会在GitHub上公开。</p><h2 id="未来打算"><a href="#未来打算" class="headerlink" title="未来打算"></a>未来打算</h2><ul><li><input disabled="" type="checkbox"> 多条件搜索过滤</li><li><input checked="" disabled="" type="checkbox"> GIF等动图支持</li><li><input disabled="" type="checkbox"> 标签字典</li><li><input disabled="" type="checkbox"> 标签页标签云</li></ul><h2 id="版本更新"><a href="#版本更新" class="headerlink" title="版本更新"></a>版本更新</h2><p>1.1.1 - 2026.04.18</p><p>修复首页处理中图标状态更新问题</p><p>1.1.0 - 2026.04.16</p><p>新增GIF动图支持</p><p>1.0.1 - 2026.04.16</p><p>新增标签页跳转搜索页显示，搜索页前后端将符号统一为英文半角符号</p><p>1.0.0 - 2026.04.15</p><p>Meme Classifier横空出世</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/Meme%E5%88%86%E7%B1%BB%E5%99%A8</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/Meme%E5%88%86%E7%B1%BB%E5%99%A8"/>
    <published>2026-04-20T13:31:46.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="Meme-Classifier"><a href="#Meme-Classifier" class="headerlink" title="Meme Classifier"></a><strong>Meme Classifier</strong></h2><p>你是否在相册里屯了上千张Meme图，结果却在关键时刻脑子里已经想好了那张图，手指却在相册里划了三分钟还没找到？</p>
<p><img]]>
    </summary>
    <title>Meme分类器</title>
    <updated>2026-04-20T13:47:04.157Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="文件目录树生成器"><a href="#文件目录树生成器" class="headerlink" title="文件目录树生成器"></a>文件目录树生成器</h2><h3 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h3><p>先看效果图：</p><p><img src="/../../images/%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%E6%A0%91%E7%94%9F%E6%88%90%E5%99%A8/%E9%A1%B5%E9%9D%A2%E5%9B%BE%E7%89%871.4.0.png" alt="文件目录树生成器"></p><p>页面分为三大块，分别是上下两块，上面的这一块分为左侧选择目录区、右侧配置区，一目了然，页面简洁没有一丝多余的设计。</p><h3 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h3><p>这是一个使用Tauri v2写的轻量小工具，作用是快速生成一个目录的文件目录树，以便在README、AI对话中使用</p><p>点击或拖入一个文件夹，并且配置配置项即可生成文件目录树，目前支持的配置项有：</p><ol><li>根目录显示名称——改变目录树根目录显示名</li><li>忽略文件或目录——忽略指定的文件或整个目录，支持使用Glob模式正则批评文件</li><li>文件&#x2F;目录注释——给文件、目录加上说明注释</li><li>包含空目录——默认启用，启用后会在目录树中包括空目录，若希望排除空目录干扰可以关闭</li><li>仅包括空目录——默认关闭，启用后目录树中仅包括空目录，可以用于快速清理空目录</li><li>只读取目录——默认关闭，启用后目录树中只包括目录层级</li><li>包括软连接——默认启用，启用后会在目录树中包括软连接下的内容</li><li>目录层级深度限制——默认为10，限制扫描的层级深度</li></ol><p>生成的效果如下</p><pre class="line-numbers language-none"><code class="language-none">目录结构树生成器    ├── images    │   ├── 目录结构树生成器效果图.ai    │   ├── 目录结构树生成器效果图.png    │   ├── 页面图片.png    │   └── 页面图片1.2.0.png    ├── src    │   ├── css    │   │   ├── default.min.css    │   │   └── styles.css    │   ├── icons    │   ├── js    │   │   ├── highlight.min.js    │   │   ├── markdown.min.js    │   │   └── script.js    │   └── index.html    ├── src-tauri    │   ├── capabilities    │   │   └── default.json    │   ├── gen    │   │   └── schemas    │   │       ├── acl-manifests.json    │   │       ├── capabilities.json    │   │       ├── desktop-schema.json    │   │       └── windows-schema.json    │   ├── icons    │   ├── src    │   │   ├── lib.rs    │   │   └── main.rs    │   ├── .gitignore    │   ├── Cargo.lock    │   ├── Cargo.toml    │   ├── build.rs    │   └── tauri.conf.json    ├── .gitignore    ├── README.md    ├── package-lock.json    └── package.json<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="运行与打包"><a href="#运行与打包" class="headerlink" title="运行与打包"></a>运行与打包</h3><p>安装依赖：</p><pre class="line-numbers language-none"><code class="language-none">npm install<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>开发模式运行：</p><pre class="line-numbers language-none"><code class="language-none">npm tauri run dev<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>打包构建：</p><pre class="line-numbers language-none"><code class="language-none">npm run tauri build<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><details>  <summary>Neutralino旧版</summary>**1. 安装 Neutralinojs CLI (如果你还没安装)**<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">-g</span> @neutralinojs/neu<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><strong>2. 初始化</strong></p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">git</span> clone https://github.com/2010HCY/DirTreeGen.git<span class="token builtin class-name">cd</span> DirTreeGenneu update<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><blockquote><p>执行 <code>neu update</code> 后，CLI 会自动创建 <code>bin/</code> 目录并下载各平台的运行时程序（<code>neutralino-win_x64.exe</code>, <code>neutralino-linux_x64</code>, <code>neutralino-mac_x64</code> 等）。</p></blockquote><p><strong>3. 构建</strong></p><pre class="line-numbers language-none"><code class="language-none">neu build<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>构建成品可以在<code>dist/dir-tree-gen</code>下找到。</p><p>若需要启用开发者工具将<code>neutralino.config.json</code> 中的<code>enableInspector</code> 设置为 <code>true</code> 即可。</p></details><p>GitHub地址：<a href="https://github.com/2010HCY/DirTreeGen">2010HCY&#x2F;DirTreeGen: 快速生成目录结构树</a></p><p>下载地址：<a href="https://github.com/2010HCY/DirTreeGen/releases">Releases · 2010HCY&#x2F;DirTreeGen</a></p><h3 id="更新日志"><a href="#更新日志" class="headerlink" title="更新日志"></a>更新日志</h3><h4 id="1-4-0"><a href="#1-4-0" class="headerlink" title="1.4.0"></a>1.4.0</h4><p>使用Tauri v2重写，并且支持处理软连接。</p><h4 id="1-3-0"><a href="#1-3-0" class="headerlink" title="1.3.0"></a>1.3.0</h4><p>正则使用 Glob 模式</p><h4 id="1-2-1"><a href="#1-2-1" class="headerlink" title="1.2.1"></a>1.2.1</h4><p>修复仅包括空目录模式下目录树不能收尾的BUG</p><h4 id="1-2-0"><a href="#1-2-0" class="headerlink" title="1.2.0"></a>1.2.0</h4><p>新增仅扫描&#x2F;显示空目录功能，便于清理空文件夹。</p><h4 id="1-1-0"><a href="#1-1-0" class="headerlink" title="1.1.0"></a>1.1.0</h4><p>优化扫描逻辑</p><p>修改点击、拖拽文件不立即扫描，在配置完配置项后使用配置项过滤规则进行扫描。<br>避免了仅需根目录文件列表却扫描一整个目录。<br>同时文件层级深度上限提升至999,999，远超NTFS16,000上限。（但是我没保证不会崩溃）<br>现在扫描目录会显示进度了。</p><h4 id="1-0-0"><a href="#1-0-0" class="headerlink" title="1.0.0"></a>1.0.0</h4><p>首个版本</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%E6%A0%91%E7%94%9F%E6%88%90%E5%99%A8</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/%E6%96%87%E4%BB%B6%E7%9B%AE%E5%BD%95%E6%A0%91%E7%94%9F%E6%88%90%E5%99%A8"/>
    <published>2026-04-05T14:40:11.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="文件目录树生成器"><a href="#文件目录树生成器" class="headerlink" title="文件目录树生成器"></a>文件目录树生成器</h2><h3 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h3><p>先看效果图：</p>
<p><img]]>
    </summary>
    <title>文件目录树生成器</title>
    <updated>2026-05-19T10:17:24.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Flash收藏站" scheme="https://hcyhub.com/tags/Flash%E6%94%B6%E8%97%8F%E7%AB%99/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="Flash收藏站"><a href="#Flash收藏站" class="headerlink" title="Flash收藏站"></a>Flash收藏站</h2><p><a href="https://flash.hcyhub.com/">https://flash.hcyhub.com/</a><br>这是我的Flash收藏站，里面收藏了我喜欢的Flash游戏们。</p><p>我为什么要做这个网站？原因是2024年11月24日晚上，那天我抓取了“驾驶TU-95”这个Flash游戏，我小时候因为看不懂英文，一直坠机，那天晚上，我第一次尝试反编译SWF文件，成功汉化了第一个Flash游戏。</p><p>隔天，在昨天胜利的鼓舞下，我又汉化了第二个Flash游戏，也就在那时，我萌生了做一个自己的个人Flash游戏收藏站的想法，发布我自己汉化的游戏，在肝完汉化后随手写两个HTML文件就上传上去了，网站在2024.11.26成功发布。</p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E5%88%9A%E5%88%9A%E5%8F%91%E5%B8%83%E6%97%B6%E7%9A%84%E6%A0%B7%E5%AD%90.png" alt="刚刚发布时的样子"></p><p>可以看到刚刚发布时极为简陋，页面就随手框了几个div容器，颜色都直接使用默认补全的颜色没调，所以就有了第一次修缮：</p><h2 id="第一次页面修缮"><a href="#第一次页面修缮" class="headerlink" title="第一次页面修缮"></a>第一次页面修缮</h2><blockquote><p>2025-03-22 20:20:55</p></blockquote><p>首页图片：<br><img src="../images/我的Flash收藏站/第一次修缮后的首页.png" style="zoom:80%;" /><br>页脚：<br><img src="../images/我的Flash收藏站/第一次修缮后的页脚.png" style="zoom:80%;" /><br>在25年3月份，我装修了下页面，修改了颜色和页脚，新颜色看着舒服多了，这个主题配色也一直沿用至今成为了我最喜欢的风格，在当天，我还为了方便写了俩RSS生成器和Sitemap生成器。（当时还在使用手动创建所有站点文件，后来才搞了SSG一条龙）</p><p>当时写的RSS订阅文件生成器：</p><p>此RSS订阅生成器是通过读取我预留的Json元信息生成的，新链接的时间为第一次运行时间，链接的时间会储存在日志中，xml的优先级大于日志，可以手动修改xml RSS订阅时间，手动修改xml中的时间会在下一次程序运行时被更新进日志。</p><p>Json格式为：</p><pre class="line-numbers language-json" data-language="json"><code class="language-json"><span class="token punctuation">[</span>    <span class="token punctuation">&#123;</span>      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"驾驶TU-95"</span><span class="token punctuation">,</span>      <span class="token property">"desc"</span><span class="token operator">:</span> <span class="token string">"驾驶战略轰炸机TU-95！带有汉化"</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>    <span class="token punctuation">&#123;</span>      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"文具防御"</span><span class="token punctuation">,</span>      <span class="token property">"desc"</span><span class="token operator">:</span> <span class="token string">"使用文具打击来犯之敌！带有汉化"</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><details><summary>RSS生成器代码</summary><pre class="line-numbers language-c++" data-language="c++"><code class="language-c++">#include &lt;iostream&gt;#include &lt;fstream&gt;#include &lt;sstream&gt;#include &lt;string&gt;#include &lt;set&gt;#include &lt;vector&gt;#include &lt;ctime&gt;#include &lt;json.hpp&gt;using json &#x3D; nlohmann::json;&#x2F;&#x2F; RFC-822 格式时间std::string getCurrentTime() &#123;    std::time_t now &#x3D; std::time(nullptr);    char buf[80];    std::strftime(buf, sizeof(buf), &quot;%a, %d %b %Y %H:%M:%S GMT&quot;, std::gmtime(&amp;now));    return std::string(buf);&#125;std::string extractBetween(const std::string&amp; str, const std::string&amp; start_delim, const std::string&amp; end_delim) &#123;    size_t start &#x3D; str.find(start_delim);    if (start &#x3D;&#x3D; std::string::npos) return &quot;&quot;;    start +&#x3D; start_delim.size();    size_t end &#x3D; str.find(end_delim, start);    if (end &#x3D;&#x3D; std::string::npos) return &quot;&quot;;    return str.substr(start, end - start);&#125;json readXmlPubDates(const std::string&amp; xmlFilename) &#123;    json xmlMap &#x3D; json::object();    std::ifstream xmlFile(xmlFilename);    if (!xmlFile.is_open())        return xmlMap;    std::string line;    std::string currentLink;    while (std::getline(xmlFile, line)) &#123;        if (line.find(&quot;&lt;link&gt;&quot;) !&#x3D; std::string::npos) &#123;            currentLink &#x3D; extractBetween(line, &quot;&lt;link&gt;&quot;, &quot;&lt;&#x2F;link&gt;&quot;);        &#125; else if (line.find(&quot;&lt;pubDate&gt;&quot;) !&#x3D; std::string::npos) &#123;            std::string pubDate &#x3D; extractBetween(line, &quot;&lt;pubDate&gt;&quot;, &quot;&lt;&#x2F;pubDate&gt;&quot;);            if (!currentLink.empty()) &#123;                xmlMap[currentLink] &#x3D; pubDate;                currentLink.clear();            &#125;        &#125;    &#125;    xmlFile.close();    return xmlMap;&#125;&#x2F;&#x2F; 加载日志文件（日志是记录链接RSS时间的）json loadLog(const std::string&amp; logFilename) &#123;    json logData;    std::ifstream logFile(logFilename);    if (logFile.is_open())&#123;        try &#123;            logFile &gt;&gt; logData;        &#125; catch (json::parse_error&amp; e) &#123;            std::cerr &lt;&lt; &quot;日志文件解析错误: &quot; &lt;&lt; e.what() &lt;&lt; std::endl;        &#125;        logFile.close();    &#125; else &#123;        logData &#x3D; json::object();    &#125;    return logData;&#125;&#x2F;&#x2F; 保存日志void saveLog(const json&amp; logData, const std::string&amp; logFilename) &#123;    std::ofstream logFile(logFilename);    if (logFile.is_open())&#123;        logFile &lt;&lt; logData.dump(4);        logFile.close();    &#125; else &#123;        std::cerr &lt;&lt; &quot;无法保存日志文件: &quot; &lt;&lt; logFilename &lt;&lt; std::endl;    &#125;&#125;#ifdef _WIN32    #include &lt;windows.h&gt;    #define timegm _mkgmtime#endifint main(int argc, char* argv[]) &#123;    std::string jsonInputFilename &#x3D; &quot;api&#x2F;games_name.json&quot;;    std::string xmlOutputFilename &#x3D; &quot;rss.xml&quot;;    std::string logFilename &#x3D; &quot;rss_log.json&quot;;    &#x2F;&#x2F; --- 1. 读取 JSON  ---    std::ifstream inputFile(jsonInputFilename);    if (!inputFile.is_open())&#123;        std::cerr &lt;&lt; &quot;无法打开文件 &quot; &lt;&lt; jsonInputFilename &lt;&lt; std::endl;        return 1;    &#125;    json jsonData;    inputFile &gt;&gt; jsonData;    inputFile.close();        &#x2F;&#x2F; --- 2. 加载日志 ---    json logData &#x3D; loadLog(logFilename);        &#x2F;&#x2F; --- 3. 尝试读取当前目录下的 rss.xml 中记录的时间（若已运行过） ---    json xmlMap &#x3D; readXmlPubDates(xmlOutputFilename);        &#x2F;&#x2F; 存储JSON链接    std::set&lt;std::string&gt; jsonLinks;        &#x2F;&#x2F; --- 4. 生成 RSS XML 内容 ---    std::ostringstream xmlContent;    xmlContent &lt;&lt; &quot;&lt;?xml version&#x3D;\&quot;1.0\&quot; encoding&#x3D;\&quot;UTF-8\&quot; ?&gt;\n&quot;;    xmlContent &lt;&lt; &quot;&lt;rss version&#x3D;\&quot;2.0\&quot;&gt;\n&quot;;    xmlContent &lt;&lt; &quot;  &lt;channel&gt;\n&quot;;    xmlContent &lt;&lt; &quot;    &lt;title&gt;Flash收藏站&lt;&#x2F;title&gt;\n&quot;;    xmlContent &lt;&lt; &quot;    &lt;link&gt;https:&#x2F;&#x2F;flash.100713.xyz&#x2F;&lt;&#x2F;link&gt;\n&quot;;    xmlContent &lt;&lt; &quot;    &lt;description&gt;最新Flash游戏列表 RSS 订阅&lt;&#x2F;description&gt;\n&quot;;    xmlContent &lt;&lt; &quot;    &lt;language&gt;zh-CN&lt;&#x2F;language&gt;\n&quot;;    xmlContent &lt;&lt; &quot;    &lt;lastBuildDate&gt;&quot; &lt;&lt; getCurrentTime() &lt;&lt; &quot;&lt;&#x2F;lastBuildDate&gt;\n&quot;;        for (const auto&amp; item : jsonData) &#123;        std::string name &#x3D; item[&quot;name&quot;];        std::string desc &#x3D; item[&quot;desc&quot;];        std::string link &#x3D; &quot;https:&#x2F;&#x2F;flash.100713.xyz&#x2F;&quot; + name;        jsonLinks.insert(link);            std::string pubDate;        if (item.contains(&quot;pubDate&quot;)) &#123;            pubDate &#x3D; item[&quot;pubDate&quot;];        &#125; else if (xmlMap.contains(link)) &#123;            pubDate &#x3D; xmlMap[link];        &#125; else if (logData.contains(link)) &#123;            pubDate &#x3D; logData[link];        &#125; else &#123;            pubDate &#x3D; getCurrentTime();        &#125;            if (!logData.contains(link) || logData[link] !&#x3D; pubDate) &#123;            logData[link] &#x3D; pubDate;        &#125;            xmlContent &lt;&lt; &quot;    &lt;item&gt;\n&quot;;        xmlContent &lt;&lt; &quot;      &lt;title&gt;&quot; &lt;&lt; name &lt;&lt; &quot;&lt;&#x2F;title&gt;\n&quot;;        xmlContent &lt;&lt; &quot;      &lt;link&gt;&quot; &lt;&lt; link &lt;&lt; &quot;&lt;&#x2F;link&gt;\n&quot;;        xmlContent &lt;&lt; &quot;      &lt;description&gt;&quot; &lt;&lt; desc &lt;&lt; &quot;&lt;&#x2F;description&gt;\n&quot;;        xmlContent &lt;&lt; &quot;      &lt;pubDate&gt;&quot; &lt;&lt; pubDate &lt;&lt; &quot;&lt;&#x2F;pubDate&gt;\n&quot;;        xmlContent &lt;&lt; &quot;    &lt;&#x2F;item&gt;\n&quot;;    &#125;        std::vector&lt;std::string&gt; keysToRemove;    for (auto it &#x3D; logData.begin(); it !&#x3D; logData.end(); ++it) &#123;        const std::string&amp; link &#x3D; it.key();        if (jsonLinks.find(link) &#x3D;&#x3D; jsonLinks.end()) &#123;            keysToRemove.push_back(link);        &#125;    &#125;    for (const auto&amp; link : keysToRemove) &#123;        logData.erase(link);    &#125;        xmlContent &lt;&lt; &quot;  &lt;&#x2F;channel&gt;\n&quot;;    xmlContent &lt;&lt; &quot;&lt;&#x2F;rss&gt;\n&quot;;        std::ofstream outputFile(xmlOutputFilename);    if (!outputFile.is_open())&#123;        std::cerr &lt;&lt; &quot;无法创建文件 &quot; &lt;&lt; xmlOutputFilename &lt;&lt; std::endl;        return 1;    &#125;    outputFile &lt;&lt; xmlContent.str();    outputFile.close();        &#x2F;&#x2F; --- 更新的日志 ---    saveLog(logData, logFilename);        if (argc &gt; 1 &amp;&amp; std::strcmp(argv[1], &quot;-c&quot;) &#x3D;&#x3D; 0) &#123;        std::cout &lt;&lt; &quot;RSS 订阅链接文件生成完毕&quot; &lt;&lt; xmlOutputFilename &lt;&lt; std::endl;    &#125; else &#123;#ifdef _WIN32        HWND consoleWnd &#x3D; GetConsoleWindow();        if (consoleWnd !&#x3D; NULL) &#123;            ShowWindow(consoleWnd, SW_HIDE);        &#125;        MessageBoxW(NULL, L&quot;RSS 订阅链接文件生成完毕&quot;, L&quot;OK!&quot;, MB_OK);#else        std::cout &lt;&lt; &quot;RSS 订阅链接文件生成完毕&quot; &lt;&lt; xmlOutputFilename &lt;&lt; std::endl;#endif    &#125;    return 0;&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><h3 id="站点地图生成器："><a href="#站点地图生成器：" class="headerlink" title="站点地图生成器："></a>站点地图生成器：</h3><p>此站点地图生成器是通过读取RSS订阅文件来获取链接、链接标题、时间的</p><details><summary>Sitemap生成器代码</summary><pre class="line-numbers language-c++" data-language="c++"><code class="language-c++">#include &lt;iostream&gt;#include &lt;fstream&gt;#include &lt;sstream&gt;#include &lt;string&gt;#include &quot;json.hpp&quot;#include &lt;ctime&gt;#include &lt;iomanip&gt;#include &lt;cstring&gt;#ifdef _WIN32    #include &lt;windows.h&gt;    #define timegm _mkgmtime#endifusing json &#x3D; nlohmann::json;std::string convertToSitemapTime(const std::string &amp;rssTime) &#123;    std::tm tm &#x3D; &#123;&#125;;    std::istringstream iss(rssTime);    iss &gt;&gt; std::get_time(&amp;tm, &quot;%a, %d %b %Y %H:%M:%S GMT&quot;);    if (iss.fail()) &#123;        std::cerr &lt;&lt; &quot;时间格式解析失败: &quot; &lt;&lt; rssTime &lt;&lt; std::endl;        return &quot;&quot;;    &#125;    time_t t &#x3D; timegm(&amp;tm);    std::tm* gmt &#x3D; std::gmtime(&amp;t);        char buf[80];    std::strftime(buf, sizeof(buf), &quot;%Y-%m-%dT%H:%M:%S+00:00&quot;, gmt);    return std::string(buf);&#125;std::string extractTitleFromUrl(const std::string &amp;url) &#123;    size_t pos &#x3D; url.find_last_of(&#39;&#x2F;&#39;);    if (pos &#x3D;&#x3D; std::string::npos || pos + 1 &gt;&#x3D; url.size())        return url;    return url.substr(pos + 1);&#125;int main(int argc, char* argv[]) &#123;    std::setlocale(LC_ALL, &quot;&quot;);        &#x2F;&#x2F; 读取日志文件前面RSS订阅文件生成器的日志    std::string logFilename &#x3D; &quot;rss_log.json&quot;;    std::ifstream logFile(logFilename);    if (!logFile.is_open()) &#123;        std::cerr &lt;&lt; &quot;无法打开日志文件: &quot; &lt;&lt; logFilename &lt;&lt; std::endl;        return 1;    &#125;        json logData;    try &#123;        logFile &gt;&gt; logData;    &#125; catch (json::parse_error &amp;e) &#123;        std::cerr &lt;&lt; &quot;日志文件解析错误: &quot; &lt;&lt; e.what() &lt;&lt; std::endl;        return 1;    &#125;    logFile.close();        &#x2F;&#x2F; 生成 sitemap.xml    std::ofstream sitemapFile(&quot;sitemap.xml&quot;);    if (!sitemapFile.is_open()) &#123;        std::cerr &lt;&lt; &quot;无法创建 sitemap.xml 文件&quot; &lt;&lt; std::endl;        return 1;    &#125;        sitemapFile &lt;&lt; &quot;&lt;?xml version&#x3D;\&quot;1.0\&quot; encoding&#x3D;\&quot;UTF-8\&quot;?&gt;\n&quot;;    sitemapFile &lt;&lt; &quot;&lt;urlset xmlns&#x3D;\&quot;http:&#x2F;&#x2F;www.sitemaps.org&#x2F;schemas&#x2F;sitemap&#x2F;0.9\&quot;&gt;\n&quot;;        for (auto it &#x3D; logData.begin(); it !&#x3D; logData.end(); ++it) &#123;        std::string url &#x3D; it.key();        std::string rssTime &#x3D; it.value();         std::string sitemapTime &#x3D; convertToSitemapTime(rssTime);        std::string title &#x3D; extractTitleFromUrl(url);                sitemapFile &lt;&lt; &quot;  &lt;url&gt;\n&quot;;        sitemapFile &lt;&lt; &quot;    &lt;loc&gt;&quot; &lt;&lt; url &lt;&lt; &quot;&lt;&#x2F;loc&gt;\n&quot;;        sitemapFile &lt;&lt; &quot;    &lt;lastmod&gt;&quot; &lt;&lt; sitemapTime &lt;&lt; &quot;&lt;&#x2F;lastmod&gt;\n&quot;;        sitemapFile &lt;&lt; &quot;    &lt;title&gt;&quot; &lt;&lt; title &lt;&lt; &quot;&lt;&#x2F;title&gt;\n&quot;;        sitemapFile &lt;&lt; &quot;  &lt;&#x2F;url&gt;\n&quot;;    &#125;    sitemapFile &lt;&lt; &quot;&lt;&#x2F;urlset&gt;\n&quot;;    sitemapFile.close();        if (argc &gt; 1 &amp;&amp; std::strcmp(argv[1], &quot;-c&quot;) &#x3D;&#x3D; 0) &#123;        std::cout &lt;&lt; &quot;站点地图生成完毕&quot; &lt;&lt; std::endl;    &#125; else &#123;#ifdef _WIN32        HWND consoleWnd &#x3D; GetConsoleWindow();        if (consoleWnd !&#x3D; NULL) &#123;            ShowWindow(consoleWnd, SW_HIDE);        &#125;                MessageBoxW(NULL, L&quot;站点地图生成完毕&quot;, L&quot;OK!&quot;, MB_OK);#else        std::cout &lt;&lt; &quot;站点地图生成完毕&quot; &lt;&lt; std::endl;#endif    &#125;        return 0;&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><h2 id="收藏站使用SSG生成器生成"><a href="#收藏站使用SSG生成器生成" class="headerlink" title="收藏站使用SSG生成器生成"></a>收藏站使用SSG生成器生成</h2><blockquote><p>2025-10-18 19:29:19</p></blockquote><h3 id="原站点目录"><a href="#原站点目录" class="headerlink" title="原站点目录"></a>原站点目录</h3><img src="./../../images/我的Flash收藏站/原架构.png" style="zoom:80%;" /><p>这，是原来<a href="https://flash.hcyhub.com/">Flash收藏站</a>的站点根目录，可以看到核心部分是：</p><ul><li>SWF ——SWF游戏文件</li><li>Games ——游戏页面HTML文件</li><li>api ——CSS、JS、图标文件、动态返回游戏列表</li><li>FlashWebPub——自己做的快速发布器，新架构弃用</li><li>&#x2F; ——根目录下的首页站点地图RSS生成器等等</li></ul><p>看着分类好像还挺不错的，找什么上哪找都很清晰对吧？是这样没错，但这135个文件全部是我人工一个个创建好的，当时发布游戏可不是说上传下文件就行，游戏页面是要我亲自复制模板大纲然后手动填充的<del>（高级CV工程师名副其实）</del>，每发布一个游戏就得复制一份新的，要是以后想要修改页面样式还得一个个文件去编辑……想想就美好。</p><p>所以得赶在我发布了一大堆游戏前想出一个方法来，最好的办法莫过于：电脑代劳</p><p>电脑被发明出来就是为了处理信息的，很显然能让电脑干的活绝对不应该让人做，所以套模板填充信息这种脏话自然是得丢电脑头上。</p><h3 id="现站点架构"><a href="#现站点架构" class="headerlink" title="现站点架构"></a>现站点架构</h3><img src="./../../images/我的Flash收藏站/现架构.png" style="zoom:80%;" /><p>这是现在的站点目录，相比之下根目录简洁多了，我花了一个下午的时间做了个静态站点生成器（SSG），现在发布文章就不需要人工新建页面了，只需要填写相关信息，一切脏活有生成器代劳，现在的目录结构是：</p><ul><li>layout——模板文件</li><li>public——构建输出目录</li><li>source——数据来源目录<ul><li>api——CSS、JS、列表文件</li><li>Game-data——游戏数据JSON存放目录</li><li>images——游戏图片</li><li>SWF——游戏文件</li></ul></li></ul><p>一目了然，我只需要上传游戏文件、图片，填写游戏数据，剩下的事均由生成器来干，站点地图？RSS？所有游戏的元信息？统统由它生成，我只管上传完文件后敲回车就行，并且首页图片也不再是由客户端获取列表生成，而是提前生成好客户端直接获取。</p><p>舒服多了现在，下次更新我要更新下页面，现在的播放页面效果有点差。（我好像好久没发布新的游戏了）</p><p><a href="https://flash.hcyhub.com/">Flash收藏站</a></p><h2 id="全新页面上线"><a href="#全新页面上线" class="headerlink" title="全新页面上线"></a>全新页面上线</h2><blockquote><p>2026-03-21 13:53:15</p></blockquote><h3 id="本次修改前的旧版页面"><a href="#本次修改前的旧版页面" class="headerlink" title="本次修改前的旧版页面"></a>本次修改前的旧版页面</h3><p><strong>首页：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E9%A6%96%E9%A1%B5.png" alt="首页"></p><p><strong>游玩页面：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E6%B8%B8%E7%8E%A9%E9%A1%B5%E9%9D%A2.png" alt="游玩页面"></p><p>原来的页面怎么说呢，实在是一言难尽，用户体验极差，随便一看问题一大堆，比如首页卡片最后莫名其妙有俩空，游玩页面左右间距不一致下方按钮栏丑的要死，再仔细观察，播放窗口与边栏贴在一起，高度也不一致（边栏下面顶到了按钮栏）。总之就是站着看坐着看躺着看都很难受 <del>闭着眼睛也难受</del>。</p><p>于是在25年12月我开始慢慢修改页面，将其变得更美观使用更舒服。</p><h3 id="新版页面"><a href="#新版页面" class="headerlink" title="新版页面"></a>新版页面</h3><p><strong>新版首页：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E6%96%B0%E7%89%88%E9%A6%96%E9%A1%B5.png" alt="新版首页"></p><p><strong>新版播放页：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E6%96%B0%E7%89%88%E6%92%AD%E6%94%BE%E9%A1%B5.png" alt="新版播放页"></p><p><strong>搜索功能（新增）：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E6%90%9C%E7%B4%A2%E5%8A%9F%E8%83%BD.png" alt="搜索功能"></p><p><strong>下载页面（新增）：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E4%B8%8B%E8%BD%BD%E9%A1%B5%E9%9D%A2.png" alt="下载页面"></p><p><strong>关于（新增）：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E5%85%B3%E4%BA%8E.png" alt="关于"></p><p><strong>友链（新增）：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E5%8F%8B%E9%93%BE.png" alt="友链"></p><p><strong>开发者列表（新增）：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E5%BC%80%E5%8F%91%E8%80%85%E5%88%97%E8%A1%A8.png" alt="开发者列表"></p><p><strong>开发者详情页（新增）：</strong></p><p><img src="/./../../images/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99/%E5%BC%80%E5%8F%91%E8%80%85%E8%AF%A6%E6%83%85%E9%A1%B5.png" alt="开发者详情页"></p><p>新版页面改动的地方非常多，足足五大项（小项修改不列举了，懒得翻日志)：</p><ol><li>加入统一导航栏、页脚</li><li>首页卡片展示区不再会有空了，20个一页（展示区还稍微内缩了一点）</li><li>删掉了播放页的按钮栏，加入显示作者、汉化者、发表日期等信息（目前暂放在边栏，没想好放哪好）<ol><li>原先的下载按钮被合并至边栏下载按钮，在一个页面里显示、下载所有版本。</li><li>返回首页按钮功能由导航栏实现，导航栏明显用着更顺手更符合逻辑。</li><li>复制链接按钮删除（我要它何用。。。）</li></ol></li><li>新增搜索功能，在大量游戏中搜索，避免费劲巴拉翻页半天</li><li>新增关于、友链、开发者汉化者页，丰富内容同时可以快速找到相同作者、汉化者的作品。</li></ol><p>不仅页面外观看着更加舒适，播放窗口页面也改了，原先使用的是embed插入SWF文件，但是播放会出现渲染异常，例如素材外溢与显示错位，新版直接使用Ruffle创建播放器实例到窗口里，播放效果更佳。（由于直接使用Ruffle插入播放窗口了，下次更新还能加个放大缩小页面、全屏的功能。<del>希望不要被我鸽太久</del>）</p><p>——2026 年 2 月 13 日</p><h4 id="2026-2-25更新"><a href="#2026-2-25更新" class="headerlink" title="2026.2.25更新"></a>2026.2.25更新</h4><p>更新了底部翻页按钮，更加令人舒适</p><p>新版：</p><img src="./../../images/我的Flash收藏站/新版翻页按钮.png" alt="新版翻页按钮" style="zoom:50%;" /><p>旧版：</p><img src="./../../images/我的Flash收藏站/旧版翻页按钮.png" alt="旧版翻页按钮" style="zoom:50%;" /><p>页首、侧边栏加上了图标</p><img src="./../../images/我的Flash收藏站/新版页首.png" alt="新版页首" style="zoom:50%;" /><img src="./../../images/我的Flash收藏站/侧边栏.png" alt="侧边栏" style="zoom:50%;" /><p>此次更新加入了些许微交互，给予悬停反馈避免大马猴不会按按钮。关于页介绍页顺便更新了一下。</p><img src="./../../images/我的Flash收藏站/关于页介绍更新.png" alt="关于页介绍更新" style="zoom:50%;" /><p>其他的继续咕。</p><h4 id="2026-2-28更新"><a href="#2026-2-28更新" class="headerlink" title="2026.2.28更新"></a>2026.2.28更新</h4><img src="./../../images/我的Flash收藏站/底部介绍.png" alt="底部介绍" style="zoom:67%;" /><p>更新底部介绍，把游戏相关信息从边栏移至此，免得边栏内容过多。</p><p>并顺便更新了下滚动条</p><h4 id="2026-3-21更新"><a href="#2026-3-21更新" class="headerlink" title="2026.3.21更新"></a>2026.3.21更新</h4><p>将以前创建的多篇收藏站文章合并到一起，也就是本篇。</p><img src="./../../images/我的Flash收藏站/说明区域修改.png" alt="说明区域修改" style="zoom:67%;" /><img src="./../../images/我的Flash收藏站/说明区域修改（移动端）.png" alt="说明区域修改（移动端）" style="zoom:67%;" /><p>今天更新了说明区域，丰富了一下页面内容，在播放页使用首页卡片的图片（优化SEO）</p><p>并且我了解到了个<strong>Schema.org(JSON-LD)<strong>结构化数据，给搜索引擎看的实现富摘要的唯一途径，对于Flash收藏站而言，由于我很反感AI写的、“小编体”的介绍文章，导致我的页面上文章内容都很少，语义贫乏，SEO极低，加入了</strong>Schema.org</strong>后或许能有所改善？</p><h4 id="2026-3-27更新"><a href="#2026-3-27更新" class="headerlink" title="2026.3.27更新"></a>2026.3.27更新</h4><p>又是一次大更新，今天终于是填上了2026 年 2 月 13 日挖的坑——全屏按钮</p><p>今天更新的内容有三个，分别是：</p><ol><li>屏幕键盘</li><li>全屏模式</li><li>多了个显示文件大小的文本内容</li></ol><p>之所以添加屏幕键盘是因为大部分游戏都是需要键盘输入控制的，触摸屏设备在此之前大部分游戏无法游玩，今天我添加屏幕键盘后触摸屏就可以点击打开愉快玩耍了。</p><p>屏幕键盘效果：</p><img src="./../../images/我的Flash收藏站/屏幕键盘（桌面端）.png" alt="屏幕键盘（桌面端）" style="zoom:67%;" /><img src="./../../images/我的Flash收藏站/屏幕键盘（移动端）.png" alt="屏幕键盘（移动端）" style="zoom:67%;" /><p>全屏模式效果：</p><img src="./../../images/我的Flash收藏站/全屏畅玩（桌面端）.png" alt="全屏畅玩（桌面端）" style="zoom:67%;" /><img src="./../../images/我的Flash收藏站/全屏畅玩（移动端）.png" alt="全屏畅玩（移动端）" style="zoom:67%;" /><p>终于是把老早之前的坑给填上了，横屏全屏玩耍更舒服。</p><img src="./../../images/我的Flash收藏站/说明区域新增文件大小显示.png" alt="说明区域新增文件大小显示" style="zoom:67%;" /><p>说明区域给加上了个文件大小信息，没啥大区别纯凑凑字数丰富页面内容。</p><h4 id="2026-3-28更新"><a href="#2026-3-28更新" class="headerlink" title="2026.3.28更新"></a>2026.3.28更新</h4><p>网站上线了487天，今天终于是解决了一开始就存在困扰我很久的漏素材问题。</p><p>之前漏素材长这样：</p><img src="./../../images/我的Flash收藏站/之前漏素材.png" alt="之前漏素材" style="zoom:67%;" /><p>更新后长这样：</p><img src="./../../images/我的Flash收藏站/现在正常显示Flash播放范围.png" alt="现在正常显示Flash播放范围" style="zoom:67%;" /><p>可以看到之前Ruffle的逻辑是尽量填满容器，所以它会把所有空的空间都渲染上，造成把本该在可视范围外隐藏的垃圾素材显示到播放窗口里，像上面这个最终<a href="https://flash.hcyhub.com/Games/%E6%9C%80%E7%BB%88%E5%AF%BC%E5%BC%B9%E9%98%B2%E5%BE%A1%E6%88%98/">导弹防御战</a>还好整体挺干净的，像下面的这个<a href="https://flash.hcyhub.com/Games/%E6%AF%81%E7%81%AD%E4%B9%8B%E5%A1%94/">毁灭之塔</a>：</p><img src="./../../images/我的Flash收藏站/毁灭之塔.png" alt="毁灭之塔" style="zoom:67%;" /><p>这乱七八糟的页面简直想让我把屏幕吃了，这个问题一直困扰着我，我咋设置<code>showAll</code>、<code>letterbox</code>都没用，直到今天彻底忍不了了，控制台输了一下<code>console.table(window.RufflePlayer.config);</code>，然后我看到：</p><table><thead><tr><th align="left">（索引）</th><th align="left">值</th></tr></thead><tbody><tr><td align="left">showSwfDownload</td><td align="left">true</td></tr><tr><td align="left">ignoreOptout</td><td align="left">true</td></tr><tr><td align="left">autoplay</td><td align="left">‘auto’</td></tr><tr><td align="left">unmuteOverlay</td><td align="left">‘visible’</td></tr><tr><td align="left">splashScreen</td><td align="left">true</td></tr><tr><td align="left">openInNewTab</td><td align="left"><em>ƒ</em></td></tr></tbody></table><p>合计着变量压根没有应用？再一检查初始化代码：</p><pre class="line-numbers language-none"><code class="language-none">document.addEventListener(&#39;DOMContentLoaded&#39;, function() &#123;    window.RufflePlayer &#x3D; window.RufflePlayer || &#123;&#125;;    rufflePlayer &#x3D; window.RufflePlayer.newest();    player &#x3D; rufflePlayer.createPlayer(&#123;        allowScriptAccess: true,        scale: &quot;showall&quot;,        forceScale: true,        autoplay: &quot;on&quot;,        backgroundColor: null,        polyfills: true,        allowNetworking: &quot;internal&quot;,    &#125;);<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>发现有个问题，配置项赋值晚了，因为</p><pre class="line-numbers language-none"><code class="language-none">rufflePlayer &#x3D; window.RufflePlayer.newest();  &#x2F;&#x2F; 读取 config（当时未配置是undefined）window.RufflePlayer.config &#x3D; &#123;...&#125;;           &#x2F;&#x2F; 这里我才赋值<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>Ruffle 的<code>scale / letterbox</code>属于 runtime 启动参数，只会在<code>RufflePlayer.newest()</code>调用时从<code>window.RufflePlayer.config</code>读取一次，于是Ruffle就按默认配置运行，结果就是Ruffle使用默认配置默认播放逻辑播放，默认配置下Ruffle会显示所有的素材，包括那些本应该被裁剪的部分。</p><p>而我发现问题的根源后就简单了，之前是”先读取，再赋值“，现在改成”先赋值，再读取“：</p><pre class="line-numbers language-none"><code class="language-none">let player;let rufflePlayer;window.RufflePlayer &#x3D; window.RufflePlayer || &#123;&#125;;window.RufflePlayer.config &#x3D; &#123;    &quot;letterbox&quot;: &quot;on&quot;,    &quot;scale&quot;: &quot;showAll&quot;,    &quot;forceScale&quot;: true,    &quot;autoplay&quot;: &quot;on&quot;,    &quot;unmuteOverlay&quot;: &quot;hidden&quot;&#125;;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>启动无报错，成功解决素材外溢的问题。</p><p>再次运行<code>console.table(window.RufflePlayer.config);</code>，可以看到配置成功应用了：</p><table><thead><tr><th align="left">（索引）</th><th align="left">值</th></tr></thead><tbody><tr><td align="left">showSwfDownload</td><td align="left">true</td></tr><tr><td align="left">ignoreOptout</td><td align="left">true</td></tr><tr><td align="left">autoplay</td><td align="left">‘on’</td></tr><tr><td align="left">unmuteOverlay</td><td align="left">‘hidden’</td></tr><tr><td align="left">splashScreen</td><td align="left">true</td></tr><tr><td align="left">letterbox</td><td align="left">‘on’</td></tr><tr><td align="left">scale</td><td align="left">‘showAll’</td></tr><tr><td align="left">forceScale</td><td align="left">true</td></tr><tr><td align="left">openInNewTab</td><td align="left"><em>ƒ</em></td></tr></tbody></table><img src="./../../images/我的Flash收藏站/毁灭之塔（修复后）.png" alt="毁灭之塔（修复后）" style="zoom:67%;" /><p>强迫症极度舒适😇😇😇</p><img src="./../../images/我的Flash收藏站/侧边栏按钮修改.png" alt="侧边栏按钮修改" style="zoom:67%;" /><p>修改了下按钮样式，更加好看，原先默认按钮样式太丑了</p><h4 id="2026-4-04更新"><a href="#2026-4-04更新" class="headerlink" title="2026.4.04更新"></a>2026.4.04更新</h4><img src="./../../images/我的Flash收藏站/最后更新时间显示.png" alt="最后更新时间显示" style="zoom:67%;" /><p>没错，现在会游玩页会显示最近更新时间了。<del>史诗级大更新</del>，之所以突然给加了个这功能是因为今天汉化好了<a href="https://flash.hcyhub.com/Games/%E6%AF%81%E7%81%AD%E4%B9%8B%E5%A1%94/">毁灭之塔</a>，而毁灭之塔很早以前就发布了，静悄悄的更新页面估计没多少人发现所以加了个最后更新的时间显示，并且滚动到首页卡片流前面。</p><p>今天是2026年4.04日，推广一下我的404页面吧🤪</p><p><a href="https://hcyhub.com/404">https://HcyHub.com/404</a></p><p><a href="https://flash.hcyhub.com/404">https://flash.HcyHub.com/404</a></p><h4 id="2026-6-03-2026-6-12更新"><a href="#2026-6-03-2026-6-12更新" class="headerlink" title="2026.6.03~2026.6.12更新"></a>2026.6.03~2026.6.12更新</h4><p>史诗级更新，新增了分类、标签页，更好管理每一个Flash游戏、动画</p><img src="./../../images/我的Flash收藏站/标签页.png" alt="标签页" style="zoom:67%;" /><img src="./../../images/我的Flash收藏站/分类页.png" alt="分类页" style="zoom:67%;" /><p>同时新增了首页留言板、信息容器：</p><img src="./../../images/我的Flash收藏站/首页-2026.06.12.png" alt="首页-2026.06.12" style="zoom:67%;" /><p>不得不说我设计的药丸按钮是真的好看。</p><p>同时进一步丰富了关于页，加上了FAQ和赞助码：</p><img src="./../../images/我的Flash收藏站/关于页-2026.06.12.png" alt="关于页-2026.06.12" style="zoom:67%;" /><p>另外我决定以后以黄行山这个代号做汉化作品了，因为汉化的受众都是中文用户，英文名Ethaniel不大好记、留下印象。</p><h4 id="2026-10-11更新"><a href="#2026-10-11更新" class="headerlink" title="2026.10.11更新"></a>2026.10.11更新</h4><p>更新了下首页留言本样式，可以显示根评论与子评论的层级嵌套、博主标签了。并且把丑不拉几的翻页按钮改成了滚动到最下面按加载更多按钮加载。</p><p>未来打算自己自定义一个Twikoo的评论区，目前用的是Twikoo官方提供的，感觉不大满意但还凑合。</p><img src="./../../images/我的Flash收藏站/2026.10.11首页留言本更新.png" alt="2026.10.11首页留言本更新" style="zoom:67%;" /><h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><p>我之所以做了这个Flash收藏站，是因为我当时摸索着学会并汉化了第一个Flash游戏驾驶TU-95，汉化完成后却只能自己保存、无人知晓，这种感觉实在难受。所以我就糊了个首页跟播放页匆匆上线了Flash收藏站，用于展示我喜欢的游戏、我的汉化作品、别人的作品，收藏游戏作品供大家游玩。</p><p>这次页面大更新从25年12月左右开始花了差不多三个晚上，有灵感了这修修那改改，改完后上传看着那页面是越看越满意，虽然还是缺少了很多（比如游戏标签、游戏分类），但至少整体视觉一致性明显提升，看着舒服多了。</p><p>写到这里已经是 2026 年 2 月 13 日，页面大更新后一直想写个博客记录下结果拖到现在，马上过年了，马年快乐！</p><p>博客也好久没写了，忙着整音乐空间收藏站等其他子站。未来可能会把博客给移到blog子域下，HcyHub.com做个人空间。</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E6%88%91%E7%9A%84Flash%E6%94%B6%E8%97%8F%E7%AB%99"/>
    <published>2026-03-21T05:53:15.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="Flash收藏站"><a href="#Flash收藏站" class="headerlink" title="Flash收藏站"></a>Flash收藏站</h2><p><a]]>
    </summary>
    <title>我的Flash收藏站</title>
    <updated>2026-10-11T11:24:34.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p>众所周知，注册、登录一个网站，永远要填写手机号→手忙脚乱找手机收验证码，非常麻烦，那有没有什么办法能在电脑上插SIM卡收验证码？肯定有，只需要：</p><ol><li>一张SIM卡（非 <del>奠</del> 电信的），因为该模块背面的卡槽是中卡大小，所以可能还需要个卡套（直接插也能用，注意方向，不好拔出来）</li><li>一个SIM模块，这里我使用SIM800C模块</li><li>SSCOM，也可以使用自己喜欢的串口模块</li><li>电脑、手、聪明的大脑以及一个有信号的人类聚集地</li></ol><img src="./../../images/在电脑上使用SIM卡接码教程/SIM800C模块.webp" style="zoom:30%;" /><blockquote><p>图片上同款模块是板载CH340T USB转串口芯片的，若没安装CH340驱动需要去<a href='https://github.com/WCH-IC/download/releases/tag/CH341' rel="nofollow">安装</a>一下</p></blockquote><p>我使用的是图上的模块，用CH340T USB转串口模块，大虾丁丁做的SSCOM软件因为<a href='http://www.daxia.com' rel="nofollow">大虾电子网</a>已经关了，网上很难找到下载链接，这个是官方发布页：<a href='http://www.daxia.com/sscom/sscom5.13.1.rar' rel="nofollow">http://www.daxia.com/sscom/</a>官方下载地址：<a href='http://www.daxia.com/sscom/sscom5.13.1.rar' rel="nofollow">http://www.daxia.com/sscom/sscom5.13.1.rar</a>，若失效了下载这个<a href='/file/SSCOM 5.13.1.7z' rel="nofollow">SSCOM 5.13.1.7z</a></p><p>关于为什么不能使用奠信的SIM卡，是因为SIM800C 只支持 2G GSM，而中国网络基建情况：</p><table><thead><tr><th>运营商</th><th>2G状态</th></tr></thead><tbody><tr><td>中国移动</td><td>仍有2G</td></tr><tr><td>中国联通</td><td>部分地区保留</td></tr><tr><td>中国电信</td><td>从未使用GSM</td></tr></tbody></table><p>中国奠信在2G时代并没有采用GSM制式，而是采用的CDMA制式(CDMA2000&#x2F;CDMA)</p><h2 id="接码"><a href="#接码" class="headerlink" title="接码"></a>接码</h2><p>把SIM卡插入模块，如果是小卡注意缺口朝外，然后打开SSCOM软件</p><img src="./../../images/在电脑上使用SIM卡接码教程/连接模块.png" style="zoom:80%;" /><p>端口号选模块端口号，不知道是那个可以插拔一下看看那个不见了，波特率选择9600，勾选<strong>加回车换行</strong>，然后输入<code>AT</code>，发送，若回复“OK”就是OK了。若没有回复OK，而是□或其他，那说明可能是没插牢、波特率错了，可以尝试把波特率依次改为<code>9600</code> -&gt; <code>115200</code> -&gt; <code>57600</code>，然后发送AT，那个回复OK就是那个。</p><blockquote><p>注意，一定要在输入框里回车，或者勾选“加回车换行”选项！如果没有回车模块无法识别命令的，模块没有识别到换行符的话只会原样还回（或者忽略，取决于是否开启回显模式）</p></blockquote><p>测试成功后输入<code>AT+CPIN?</code>查看SIM卡状态，若回应为：<code>READY</code>说明SIM卡已就绪</p><pre class="line-numbers language-none"><code class="language-none">[21:02:03.079]发→◇AT+CPIN?□[21:02:03.127]收←◆AT+CPIN?+CPIN: READYOK<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><blockquote><p>可选：输入<code>AT+CSQ</code>查看信号强度，返回值<code>+CSQ: 信号值</code></p><p>输入<code>AT+COPS?</code>查看运营商，返回值<code>+COPS: 0,0,&quot;运营商&quot;</code></p><p>输入<code>AT+CREG?</code>查看网络注册状态，返回值<code>+CREG: 0,1</code>。<code>0,1</code>是已注册本地网络，<code>0,2</code>是搜索中，<code>0,5</code>是已注册漫游网络</p></blockquote><p>当确认模块就绪，SIM卡已正确识别时就可以接码了，当收到短信时模块会主动向串口推送<code>+CMTI: &quot;SM&quot;,1</code>，说明成功接收短信并储存存储器（SM）里，序号1，这时就可以执行以下步骤读取短信：</p><ol><li>输入<code>AT+CMGF=1</code>将模式切换为文本模式<blockquote><p>该命令只是让 AT 指令以文本方式操作短信，不影响短信的实际编码格式。</p></blockquote></li><li>输入<code>AT+CMGR=1</code>读取短信，这里的1就是刚刚CMTI的序号</li></ol><blockquote><p><code>SM</code> 表示 SIM 卡存储，如果配置为 <code>ME</code> 则短信会存在模块内部</p></blockquote><p>如果一切顺利，返回的内容应该是：</p><pre class="line-numbers language-none"><code class="language-none">[21:15:50.491]发→◇AT+CMGF&#x3D;1□[21:15:50.515]收←◆OK[21:15:56.369]发→◇AT+CMGR&#x3D;1□[21:15:56.446]收←◆+CMGR: &quot;REC READ&quot;,&quot;10692994314[21:15:56.479]收←◆27239&quot;,&quot;&quot;,&quot;26&#x2F;03&#x2F;09,19:17:07+32&quot;[21:15:56.512]收←◆301054D454E954D454E93011003700[21:15:56.545]收←◆31003800360034003100204E3A4F6076[21:15:56.577]收←◆84624B673A63627ED19A8C8BC17801FF[21:15:56.611]收←◆0C8BF7572800355206949F51855B8C62[21:15:56.644]收←◆1063627ED130024E3A4FDD8BC18D2653[21:15:56.677]收←◆F75B895168FF0C8BF752FF6CC46F0F6B649A8C8BC178013002OK<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>可以看到成功读取出短信了，<code>+CMGR: &quot;REC READ&quot;,&quot;1069299431427239&quot;,&quot;&quot;,&quot;26/03/09,19:17:07+32&quot;</code>这一行字符串是 SIM800C 的标准短信元数据响应，格式是<code>+CMGR: &quot;状态&quot;,&quot;发件人&quot;,&quot;&quot;,&quot;时间戳&quot;</code></p><p>但是返回的内容是十六进制字符串，一般来说没有人可以直接阅读它，这时候就需要进行解码了，我做了个短信解码小工具，你可以直接在下方的输入框中输入进行解码，比如上面这个例子中我应该粘贴：</p><pre class="line-numbers language-none"><code class="language-none">301054D454E954D454E9301100370031003800360034003100204E3A4F607684624B673A63627ED19A8C8BC17801FF0C8BF7572800355206949F51855B8C621063627ED130024E3A4FDD8BC18D2653F75B895168FF0C8BF752FF6CC46F0F6B649A8C8BC178013002<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>到输入框中，解码结果为：</p><pre class="line-numbers language-none"><code class="language-none">【哔哩哔哩】718641 为你的手机换绑验证码，请在5分钟内完成换绑。为保证账号安全，请勿泄漏此验证码。<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>非常完美~</p><blockquote><p>Tips: 本工具适用于 <strong>UCS2 编码短信（常见于中文短信）</strong>，如果是英文短信直接阅读就行了。</p></blockquote><div id="gsm-decoder-container" style="border: 1px solid #ddd; padding: 20px; border-radius: 8px; max-width: 600px; margin: 20px auto; font-family: sans-serif; background: #f9f9f9;">    <h3 style="margin-top: 0;">短信解码工具</h3>    <p style="font-size: 14px; color: #666;">粘贴从串口收到的 Hex 字符串（如 301054D4...）：</p>    <textarea id="hexInput" placeholder="在此粘贴十六进制字符串..." style="width: 100%; height: 80px; padding: 10px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; resize: vertical;"></textarea>        <button id="decodeBtn" style="margin-top: 10px; width: 100%; padding: 10px; background: #a3a300; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 16px;">开始解码</button>        <div style="margin-top: 20px;">        <p style="font-weight: bold;">解码结果：</p>        <div id="outputArea" style="min-height: 50px; background: white; padding: 10px; border: 1px solid #ddd; border-radius: 4px; word-wrap: break-word; color: #333;"></div>    </div></div><script>    document.getElementById('decodeBtn').addEventListener('click', function() {        const hexStr = document.getElementById('hexInput').value.trim();        const outputArea = document.getElementById('outputArea');        let result = "";        const cleanHex = hexStr.replace(/[^0-9A-Fa-f]/g, '');            if (cleanHex.length === 0) {            outputArea.innerText = "请输入有效的十六进制字符串！";            return;        }            try {            for (let i = 0; i < cleanHex.length; i += 4) {                let chunk = cleanHex.substring(i, i + 4);                if (chunk.length < 4) break;                result += String.fromCharCode(parseInt(chunk, 16));            }            outputArea.innerText = result;        } catch (e) {            outputArea.innerText = "解码出错，请检查输入内容是否为正确的十六进制字符串";        }    });</script><blockquote><p><strong>Tip：</strong></p><p>在读取短信时可以把“加时间戳和分包显示”选项关掉，这样返回的内容就是：</p><pre class="line-numbers language-none"><code class="language-none">+CMGR: &quot;REC READ&quot;,&quot;1069299431427239&quot;,&quot;&quot;,&quot;26&#x2F;03&#x2F;09,19:17:07+32&quot;301054D454E954D454E9301100370031003800360034003100204E3A4F607684624B673A63627ED19A8C8BC17801FF0C8BF7572800355206949F51855B8C621063627ED130024E3A4FDD8BC18D2653F75B895168FF0C8BF752FF6CC46F0F6B649A8C8BC178013002<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>短信内容直接一长串返回无时间戳分包显示干扰，直接复制粘贴很方便</p></blockquote><p>至此，成功实现最基本的在电脑上使用SIM卡模块接码功能，进一步更方便自动转码、系统提醒请等待下篇文章更新~~</p><h2 id="为什么短信内容是十六进制？"><a href="#为什么短信内容是十六进制？" class="headerlink" title="为什么短信内容是十六进制？"></a>为什么短信内容是十六进制？</h2><p>在上述步骤中读取短信时，你会发现返回的内容并不是普通文字，而是一长串类似：</p><pre class="line-numbers language-none"><code class="language-none">301054D454E954D454E930110037003100380036...<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>的十六进制字符串。</p><p>这是因为 <strong>短信在 GSM 网络中并不是直接以文字形式传输的</strong>，而是使用一种叫做 <strong>PDU（Protocol Data Unit）</strong> 的数据结构进行编码。</p><p>短信常见的编码方式有三种：</p><table><thead><tr><th>编码方式</th><th>用途</th></tr></thead><tbody><tr><td>GSM 7-bit</td><td>英文短信</td></tr><tr><td>UCS2</td><td>中文、日文等 Unicode 字符</td></tr><tr><td>8-bit</td><td>二进制数据（基本见不到）</td></tr></tbody></table><p>其中：</p><ul><li><strong>GSM 7-bit</strong>：每个字符使用 7 bit，最多可以发送 <strong>160 个字符</strong></li><li><strong>UCS2</strong>：每个字符使用 <strong>2 字节（16 bit）</strong>，常用于中文短信，最多 <strong>70 个字符</strong></li></ul><p>当短信使用 <strong>UCS2 编码</strong> 时，每个字符会变成：</p><pre class="line-numbers language-none"><code class="language-none">2 字节 &#x3D; 4 个十六进制字符<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>例如：</p><pre class="line-numbers language-none"><code class="language-none">4F60 &#x3D; 你597D &#x3D; 好<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>所以一条短信就会变成类似：</p><pre class="line-numbers language-none"><code class="language-none">4F60597D...<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>的十六进制字符串。</p><p>所以在本文中使用的解码工具，其实就是把：</p><pre class="line-numbers language-none"><code class="language-none">每4个十六进制字符 → 转换为一个Unicode字符<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>从而还原出真正的短信内容。</p><p>顺便提一嘴，有时候解码十六进制字符串后会发现短信内容不完整啊，咋话说到一半没了？为什么短信头部还有个乱码Ԁͺȁ？这是因为短信最多只能发 70 个中文 &#x2F; 160 个英文，因为在 GSM 网络中，一条标准短信的数据大小其实是 <strong>固定的</strong>，叫做 <strong>SMS Payload</strong>，大小为：</p><pre class="line-numbers language-none"><code class="language-none">140 Bytes<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>也就是 <strong>140 字节（1120 bit）</strong>。</p><p>单条短信之所以会出现最大<strong>70 个中文 or 160 个英文</strong>限制，是因为不同编码方式占用空间不同，短信常见编码有两种：</p><table><thead><tr><th>编码</th><th>每个字符占用</th><th>一条短信最多</th></tr></thead><tbody><tr><td>GSM 7-bit（英文）</td><td>7 bit</td><td>160 字符</td></tr><tr><td>UCS2（中文）</td><td>16 bit</td><td>70 字符</td></tr></tbody></table><p>而有的超长短信有不止<strong>70 个中文 or 160 个英文</strong>，这时候短信系统会自动使用 <strong>分段短信（Concatenated SMS）</strong>，也就是把超长短信拆除几节并在短信头部加入一个 <strong>UDH（User Data Header）</strong>记录总段数、当前段序号、同一短信的标识，这时候在SIM800C模块里读取就会发现短信内容不完整，需要把剩下几段一并提取查看才行。</p><p>UDH头部通常表现为：</p><pre class="line-numbers language-none"><code class="language-none">0500037A0201<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>之后正文才开始</p><pre class="line-numbers language-none"><code class="language-none">0500037A02014F60597D<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>由于<code>0500037A0201</code>并不是合法的十六进制字符串，所以会显示为乱码。</p><p>至于这一串UDH头部啥意思可以对照下表：</p><table><thead><tr><th>字节</th><th>含义</th></tr></thead><tbody><tr><td>05</td><td>UDH长度</td></tr><tr><td>00</td><td>信息元素标识 (IEI)</td></tr><tr><td>03</td><td>IE数据长度</td></tr><tr><td>7A</td><td>短信引用号</td></tr><tr><td>02</td><td>总段数</td></tr><tr><td>01</td><td>当前段序</td></tr></tbody></table><h2 id="AT指令大全"><a href="#AT指令大全" class="headerlink" title="AT指令大全"></a>AT指令大全</h2><p>文末附上AT指令大全，感兴趣的可以研究下</p><h3 id="简单联网测试"><a href="#简单联网测试" class="headerlink" title="简单联网测试"></a>简单联网测试</h3><table><thead><tr><th><strong>命令</strong></th><th><strong>说明</strong></th><th><strong>返回值</strong></th></tr></thead><tbody><tr><td>AT</td><td>AT测试指令</td><td>OK</td></tr><tr><td>ATE</td><td>ATE1设置回显，ATE0关闭回显</td><td>OK</td></tr><tr><td>AT+CSQ</td><td>网络信号质量查询，返回信号值</td><td>OK</td></tr><tr><td>AT+CGMR</td><td>查询固件版本</td><td>OK</td></tr><tr><td>AT+CREG?</td><td>查询网络注册状态</td><td>OK</td></tr><tr><td>AT+CGATT?</td><td>检查GPRS附着状态</td><td>OK</td></tr></tbody></table><p><code>AT+CSQ</code> 信号质量反馈</p><p>当发送 <code>AT+CSQ</code> 时，模组会返回：<code>+CSQ: &lt;rssi&gt;,&lt;ber&gt;</code></p><p><code>&lt;rssi&gt;</code> (Received Signal Strength Indication)</p><p>这是信号强度，范围是 <strong>0-31</strong>，以及一个特殊值 <strong>99</strong>。</p><ul><li><strong>0 - 9：</strong> 信号极差，基本无法通信。</li><li><strong>10 - 14：</strong> 信号较弱，偶尔可能断连。</li><li><strong>15 - 20：</strong> 信号良好，可以稳定工作。</li><li><strong>21 - 31：</strong> 信号极好，连接非常稳健。</li><li><strong>99：</strong> 模组未检测到信号或初始化未完成。</li></ul><p><code>AT+CSQ</code> 为什么只有 0-31？因为GSM 为了节省数据量，没有直接返回 dBm，而是返回 <strong>一个等级值</strong>，真实映射换算公式：RSSI &#x3D; -113 + 2 × value (dBm)</p><table><thead><tr><th>CSQ</th><th>信号</th></tr></thead><tbody><tr><td>0</td><td>-113 dBm</td></tr><tr><td>10</td><td>-93 dBm</td></tr><tr><td>20</td><td>-73 dBm</td></tr><tr><td>31</td><td>-51 dBm</td></tr></tbody></table><p><code>&lt;ber&gt;</code> (Bit Error Rate)</p><p>这是误码率。范围是 <strong>0-7</strong>。</p><ul><li><strong>0：</strong> 误码率极低，信号纯净。</li><li><strong>7：</strong> 误码率极高，数据传输可能会频繁出错。</li><li><strong>99：</strong> 未知&#x2F;不可用。</li></ul><h3 id="TCP-IP通信"><a href="#TCP-IP通信" class="headerlink" title="TCP&#x2F;IP通信"></a>TCP&#x2F;IP通信</h3><h4 id="非透传模式下的客户端通信"><a href="#非透传模式下的客户端通信" class="headerlink" title="非透传模式下的客户端通信"></a>非透传模式下的客户端通信</h4><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+CGATT?</td><td>检查GPRS附着状态</td><td>OK</td></tr><tr><td>AT+CSTT&#x3D;”CMNET”</td><td>设置APN</td><td>OK</td></tr><tr><td>AT+CIICR</td><td>建立无线链路</td><td>OK</td></tr><tr><td>AT+CIFSR</td><td>获得本地IP地址</td><td>OK</td></tr><tr><td>AT+CIPSTART&#x3D;”TCP”,”118.190.93.84”,2317</td><td>建立TCP客户端链接</td><td>OK</td></tr><tr><td>AT+CIPSTART&#x3D;”UDP”,”118.190.93.84”,2317</td><td>建立UDP客户端链接</td><td>OK</td></tr><tr><td>AT+CIPSEND&#x3D;&lt;字符长度&gt;</td><td>发送指定长度字符串</td><td>OK</td></tr><tr><td>AT+CIPCLOSE</td><td>关闭链路通信</td><td>OK</td></tr><tr><td>AT+CIPSHUT</td><td>关闭PDP上下文连接</td><td>OK</td></tr></tbody></table><h4 id="透传模式下的客户端通信"><a href="#透传模式下的客户端通信" class="headerlink" title="透传模式下的客户端通信"></a>透传模式下的客户端通信</h4><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+CGATT?</td><td>检查GPRS附着状态</td><td>OK</td></tr><tr><td>AT+CIPMODE&#x3D;1</td><td>设置为透传模式</td><td>OK</td></tr><tr><td>AT+CSTT&#x3D;”CMNET”</td><td>设置APN</td><td>OK</td></tr><tr><td>AT+CIICR</td><td>建立无线链路</td><td>OK</td></tr><tr><td>AT+CIFSR</td><td>获得本地IP地址</td><td>OK</td></tr><tr><td>AT+CIPSTART&#x3D;”TCP”,”118.190.93.84”,2317</td><td>建立TCP客户端链接</td><td>OK</td></tr><tr><td>AT+CIPSTART&#x3D;”UDP”,”118.190.93.84”,2317</td><td>建立UDP客户端链接</td><td>OK</td></tr><tr><td>AT+CIPSEND&#x3D;&lt;字符长度&gt;</td><td>发送指定长度字符串</td><td>OK</td></tr><tr><td>AT+CIPCLOSE</td><td>关闭链路通信</td><td>OK</td></tr><tr><td>AT+CIPSHUT</td><td>关闭PDP上下文连接</td><td>OK</td></tr></tbody></table><h3 id="HTTP通信"><a href="#HTTP通信" class="headerlink" title="HTTP通信"></a>HTTP通信</h3><h4 id="HTTP-GET"><a href="#HTTP-GET" class="headerlink" title="HTTP GET"></a>HTTP GET</h4><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+SAPBR&#x3D;3,1,”Contype”,”GPRS”</td><td>配置承载场景1</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;3,1,”APN”,”CMNET”</td><td>配置承载场景APN</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;1,1</td><td>激活一个 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;2,1</td><td>查询 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;0,1</td><td>关闭 GPRS 上下文.</td><td>OK</td></tr><tr><td>AT+HTTPINIT</td><td>检查HTTP连接状态</td><td>OK</td></tr><tr><td>AT+HTTPPARA&#x3D;”CID”,1</td><td>设置HTTP会话参数</td><td>OK</td></tr><tr><td>AT+HTTPPARA&#x3D;”URL”,”hcyhub.com”</td><td>设置HTTP会话参数</td><td>OK</td></tr><tr><td>AT+HTTPACTION&#x3D;0</td><td>GET会话开始</td><td>OK</td></tr><tr><td>AT+HTTPREAD</td><td>读取HTTP服务器的数据</td><td>OK</td></tr><tr><td>AT+HTTPTERM</td><td>结束HTTP服务</td><td>OK</td></tr></tbody></table><h4 id="HTTP-POST"><a href="#HTTP-POST" class="headerlink" title="HTTP POST"></a>HTTP POST</h4><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+SAPBR&#x3D;3,1,”Contype”,”GPRS”</td><td>配置承载场景1</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;3,1,”APN”,”CMNET”</td><td>配置承载场景APN</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;1,1</td><td>激活一个 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;2,1</td><td>查询 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;0,1</td><td>关闭 GPRS 上下文.</td><td>OK</td></tr><tr><td>AT+HTTPINIT</td><td>检查HTTP连接状态</td><td>OK</td></tr><tr><td>AT+HTTPPARA&#x3D;”CID”,1</td><td>设置HTTP会话参数</td><td>OK</td></tr><tr><td>AT+HTTPPARA&#x3D;”URL”,”hcyhub.com”</td><td>设置HTTP会话参数</td><td>OK</td></tr><tr><td>AT+HTTPDATA&#x3D;100,10000</td><td>上传100字节数据，等待10000毫秒</td><td>OK</td></tr><tr><td>AT+HTTPACTION&#x3D;1</td><td>POST会话开始</td><td>OK</td></tr><tr><td>AT+HTTPTERM</td><td>结束HTTP服务</td><td>OK</td></tr></tbody></table><h3 id="邮件收发"><a href="#邮件收发" class="headerlink" title="邮件收发"></a>邮件收发</h3><blockquote><p>由于现代邮件服务器普遍要求 TLS 加密，该功能在实操的话可能无法直接使用 <del>真男人就给我关掉加密裸奔</del>。</p></blockquote><h4 id="发送邮件"><a href="#发送邮件" class="headerlink" title="发送邮件"></a>发送邮件</h4><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+SAPBR&#x3D;3,1,”Contype”,”GPRS”</td><td>配置承载场景1</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;3,1,”APN”,”CMNET”</td><td>配置承载场景APN</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;1,1</td><td>激活一个 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;2,1</td><td>查询 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;0,1</td><td>关闭 GPRS 上下文.</td><td>OK</td></tr><tr><td>AT+EMAILCID&#x3D;1</td><td>配置电子邮件参数</td><td>OK</td></tr><tr><td>AT+EMAILTO&#x3D;30</td><td>配置 SMTP 会话超时时间（秒）</td><td>OK</td></tr><tr><td>AT+SMTPSRV&#x3D;”smtp.example.com”,25</td><td>设置SMTP服务器地址和端口</td><td>OK</td></tr><tr><td>AT+SMTPAUTH&#x3D;1,”<a href="mailto:&#97;&#100;&#109;&#x69;&#x6e;&#x40;&#101;&#120;&#97;&#x6d;&#112;&#x6c;&#101;&#x2e;&#x63;&#111;&#x6d;">&#97;&#100;&#109;&#x69;&#x6e;&#x40;&#101;&#120;&#97;&#x6d;&#112;&#x6c;&#101;&#x2e;&#x63;&#111;&#x6d;</a>“,”123456”</td><td>设置用户名和密码</td><td>OK</td></tr><tr><td>AT+SMTPFROM&#x3D;”<a href="mailto:&#97;&#100;&#x6d;&#x69;&#x6e;&#x40;&#x65;&#120;&#97;&#x6d;&#x70;&#108;&#101;&#46;&#x63;&#111;&#109;">&#97;&#100;&#x6d;&#x69;&#x6e;&#x40;&#x65;&#120;&#97;&#x6d;&#x70;&#108;&#101;&#46;&#x63;&#111;&#109;</a>“,”admin”</td><td>设置发送方地址和名字</td><td>OK</td></tr><tr><td>AT+SMTPRCPT&#x3D;0,0,”<a href="mailto:&#x61;&#x64;&#109;&#x69;&#x6e;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#x65;&#46;&#x63;&#x6f;&#109;">&#x61;&#x64;&#109;&#x69;&#x6e;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#x65;&#46;&#x63;&#x6f;&#109;</a>“,”admin”</td><td>设置接受方</td><td>OK</td></tr><tr><td>AT+SMTPRCPT&#x3D;1,0,”<a href="mailto:&#97;&#x64;&#109;&#105;&#110;&#x40;&#x65;&#120;&#x61;&#109;&#x70;&#x6c;&#101;&#x2e;&#x63;&#x6f;&#109;">&#97;&#x64;&#109;&#105;&#110;&#x40;&#x65;&#120;&#x61;&#109;&#x70;&#x6c;&#101;&#x2e;&#x63;&#x6f;&#109;</a>“,”admin”</td><td>设置抄送方</td><td>OK</td></tr><tr><td>AT+SMTPSUB&#x3D;”Test”</td><td>设置邮件主题</td><td>OK</td></tr><tr><td>AT+SMTPBODY&#x3D;19</td><td>设置邮件正文</td><td>OK</td></tr><tr><td>This is a new Email</td><td>邮件内容</td><td>OK</td></tr><tr><td>AT+SMTPSEND</td><td>发送邮件</td><td>OK</td></tr></tbody></table><h4 id="收取邮件"><a href="#收取邮件" class="headerlink" title="收取邮件"></a>收取邮件</h4><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+SAPBR&#x3D;3,1,”Contype”,”GPRS”</td><td>配置承载场景1</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;3,1,”APN”,”CMNET”</td><td>配置承载场景APN</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;1,1</td><td>激活一个 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;2,1</td><td>查询 GPRS 上下文</td><td>OK</td></tr><tr><td>AT+SAPBR&#x3D;0,1</td><td>关闭 GPRS 上下文.</td><td>OK</td></tr><tr><td>AT+EMAILCID&#x3D;1</td><td>配置电子邮件参数</td><td>OK</td></tr><tr><td>AT+EMAILTO&#x3D;30</td><td>配置 SMTP 会话超时时间（秒）</td><td>OK</td></tr><tr><td>AT+POP3SRV&#x3D;”pop.example.com”,”<a href="mailto:&#97;&#100;&#109;&#105;&#x6e;&#x40;&#x65;&#x78;&#x61;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#x6f;&#x6d;">&#97;&#100;&#109;&#105;&#x6e;&#x40;&#x65;&#x78;&#x61;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#x6f;&#x6d;</a>“,”123456”,110</td><td>设置 POP3 服务器地址和账户信息</td><td>OK</td></tr><tr><td>AT+POP3IN</td><td>登录POP3 服务器</td><td>OK</td></tr><tr><td>AT+POP3NUM</td><td>得到邮件总数和总的大小</td><td>OK</td></tr><tr><td>AT+POP3LIST&#x3D;1</td><td>得到第一封邮件的大小</td><td>OK</td></tr><tr><td>AT+POP3CMD&#x3D;4,1</td><td>读取第一封邮件</td><td>OK</td></tr><tr><td>AT+POP3READ&#x3D;1460</td><td>读取该邮件内容</td><td>OK</td></tr></tbody></table><h3 id="短信收发"><a href="#短信收发" class="headerlink" title="短信收发"></a>短信收发</h3><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+CMGF&#x3D;1</td><td>设置短信模式为TEXT</td><td>OK</td></tr><tr><td>AT+CMGS&#x3D;”PN”</td><td>设置收信人</td><td>&gt;</td></tr><tr><td>AT+CSCS&#x3D;”UCS2”</td><td>设置信息文本为UCS2类型</td><td>OK</td></tr><tr><td>AT+CSMP&#x3D;17,167,2,8</td><td>设置文本模式参数</td><td>OK</td></tr><tr><td>AT+CMGL&#x3D;”ALL”</td><td>查看所有短信</td><td>所有短信</td></tr><tr><td>AT+CMGR&#x3D;1</td><td>查看槽位为1的短信</td><td>槽位1短信内容</td></tr><tr><td>AT+CMGD&#x3D;1</td><td>删除槽位为1的短信内容</td><td>OK</td></tr><tr><td>AT+CNMI&#x3D;2,2,0,0,0</td><td>直接把收到的短信内容推到串口</td><td>OK</td></tr></tbody></table><p>关于<code>AT+CSMP</code>指令完整语法是<code>AT+CSMP=[fo],[vp],[pid],[dcs]</code>，具体参考下表</p><table><thead><tr><th><strong>参数</strong></th><th><strong>含义</strong></th><th><strong>解释与常用值</strong></th></tr></thead><tbody><tr><td><strong>fo</strong></td><td>First Octet</td><td><strong>第一字节</strong>。决定短信类型和发送选项。常用值 <strong>17</strong>，表示这是一个发送给短信中心（SMSC）的普通短信。</td></tr><tr><td><strong>vp</strong></td><td>Validity Period</td><td><strong>有效期</strong>。决定短信在短信中心存储多久。0-167 表示 5 分钟到 24 小时不等。<strong>167</strong> 通常代表 24 小时（最大有效期）。</td></tr><tr><td><strong>pid</strong></td><td>Protocol ID</td><td><strong>协议标识</strong>。通常设为 <strong>0</strong>，即默认协议。</td></tr><tr><td><strong>dcs</strong></td><td>Data Coding Scheme</td><td><strong>数据编码方案</strong>。这是最重要的！<strong>0</strong> 代表 GSM 7-bit 编码（纯英文）；<strong>8</strong> 代表 UCS2 编码</td></tr></tbody></table><h3 id="蓝牙调试"><a href="#蓝牙调试" class="headerlink" title="蓝牙调试"></a>蓝牙调试</h3><p>没错，SIM800C有蓝牙功能，具体指令：</p><table><thead><tr><th>AT指令</th><th>指令说明</th><th>返回值</th></tr></thead><tbody><tr><td>AT+BTPOWER&#x3D;1</td><td>打开蓝牙电源</td><td>OK</td></tr><tr><td>AT+BTHOST?</td><td>查询蓝牙名称和地址</td><td>返回蓝牙名称和MAC地址</td></tr><tr><td>AT+BTSCAN&#x3D;1,10</td><td>搜索蓝牙附近的设备</td><td>返回搜索到的蓝牙设备信息</td></tr><tr><td>AT+BTPAIR&#x3D;1,1</td><td>数字确认方式响应配对</td><td>OK</td></tr><tr><td>AT+BTACPT&#x3D;1</td><td>接受客户端的连接请求</td><td>OK</td></tr><tr><td>AT+BTSPPSEND</td><td>发送数据</td><td>返回&gt;可以开始输入数据，发送16进制1A结束发送</td></tr><tr><td>AT+BTPOWER&#x3D;0</td><td>断开蓝牙电源</td><td>OK</td></tr></tbody></table>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%9C%A8%E7%94%B5%E8%84%91%E4%B8%8A%E4%BD%BF%E7%94%A8SIM%E5%8D%A1%E6%8E%A5%E7%A0%81%E6%95%99%E7%A8%8B</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%9C%A8%E7%94%B5%E8%84%91%E4%B8%8A%E4%BD%BF%E7%94%A8SIM%E5%8D%A1%E6%8E%A5%E7%A0%81%E6%95%99%E7%A8%8B"/>
    <published>2026-03-09T14:13:03.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p>众所周知，注册、登录一个网站，永远要填写手机号→手忙脚乱找手机收验证码，非常麻烦，那有没有什么办法能在电脑上插SIM卡收验证码？肯定有，只需要：</p>
<ol>
<li>一张SIM卡（非 <del>奠</del>]]>
    </summary>
    <title>在电脑上使用SIM卡接码教程</title>
    <updated>2026-03-09T15:06:33.429Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="干货文章" scheme="https://hcyhub.com/tags/%E5%B9%B2%E8%B4%A7%E6%96%87%E7%AB%A0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><img src="./../../images/微软商店及微软商店安装的应用启用本地代理后无法联网解决办法/微软商店初始化失败.png" alt="微软商店初始化失败" style="zoom:50%;" /><p>很抱歉！出现错误，Microsoft Store初始化失败。</p><p>这个页面绝对不止一个人看过，初始化失败有很多可能的原因，本文讨论的是：启用本地代理后，Microsoft Store 及其安装的 UWP 应用无法联网的原因与解决方法。</p><img src="./../../images/微软商店及微软商店安装的应用启用本地代理后无法联网解决办法/微软纸牌互联网连接问题.png" alt="微软纸牌互联网连接问题" style="zoom: 50%;" /><p>原因其实很简单，因为微软商店及通过微软商店安装的应用、其他微软官方应用（例如Microsoft 照片、Outlook、Xbox）都是UWP应用，UWP 应用运行在 AppContainer 沙盒环境中，默认启用网络隔离防止其访问本地服务造成安全隐患，正常情况下无法访问 localhost，而代理程序在本地端口监听请求，当代理监听在 127.0.0.1 时，UWP 应用无法建立 TCP 连接，表现为网络连接失败或在线功能异常，因此需要解除 UWP 应用的回环访问限制。</p><p>解决办法很简单，在代理软件里找到UWP工具（Clash是在 设置 → UWP 工具，V2rayN在设置 → 解除Win10应用回环代理限制），打开后勾选需要解除限制的UWP应用后点击Save Changes保存即可，也可以点击Exempt All、Exempt  None一键解除限制、启用限制。其中 GUI 中的 AC Name 实际上就是 PackageFamilyName（PFN）</p><img src="./../../images/微软商店及微软商店安装的应用启用本地代理后无法联网解决办法/UWP回环豁免工具.png" alt="UWP回环豁免工具" style="zoom:67%;" /><p>若代理工具没有UWP工具，可以使用Powershell 命令行（需要管理员权限）</p><p>查询所有 UWP PFN：</p><pre class="line-numbers language-none"><code class="language-none">Get-AppxPackage | Select Name, PackageFamilyName<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>or 模糊查找：</p><pre class="line-numbers language-none"><code class="language-none">Get-AppxPackage *名称关键字* | Select Name, PackageFamilyName<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>查询当前已放行列表：</p><pre class="line-numbers language-none"><code class="language-none">CheckNetIsolation LoopbackExempt -s<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>删除已放行条目：</p><pre class="line-numbers language-none"><code class="language-none">CheckNetIsolation LoopbackExempt -d -n&#x3D;这边填应用的PackageFamilyName<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>解除所有UWP应用回环限制：</p><pre class="line-numbers language-none"><code class="language-none">foreach ($n in (get-appxpackage).packagefamilyname) &#123;checknetisolation loopbackexempt -a -n&#x3D;&quot;$n&quot;&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>无法确定应用的 PFN可以直接谷歌下，下面是一些Windows应用的PFN，8wekyb3d8bbwe是微软的发布者ID</p><table><thead><tr><th>应用</th><th>PFN</th></tr></thead><tbody><tr><td>Microsoft Store（微软商店）</td><td>Microsoft.WindowsStore_8wekyb3d8bbwe</td></tr><tr><td>Microsoft 人脉</td><td>microsoft.people_8wekyb3d8bbwe</td></tr><tr><td>Microsoft 便笺</td><td>microsoft.microsoftstickynotes_8wekyb3d8bbwe</td></tr><tr><td>Microsoft 照片</td><td>Microsoft.Windows.Photos_8wekyb3d8bbwe</td></tr><tr><td>Windows 地图</td><td>microsoft.windowsmaps_8wekyb3d8bbwe</td></tr><tr><td>Windows 媒体播放器</td><td>microsoft.zunemusic_8wekyb3d8bbwe</td></tr><tr><td>Windows 录音机</td><td>microsoft.windowssoundrecorder_8wekyb3d8bbwe</td></tr><tr><td>Windows 扫描</td><td>microsoft.windowsscan_8wekyb3d8bbwe</td></tr><tr><td>Windows 时钟</td><td>Microsoft.WindowsAlarms_8wekyb3d8bbwe</td></tr><tr><td>Windows 相机</td><td>Microsoft.WindowsCamera_8wekyb3d8bbwe</td></tr><tr><td>Windows 计算器</td><td>Microsoft.WindowsCalculator_8wekyb3d8bbwe</td></tr><tr><td>Microsoft 游戏服务</td><td>microsoft.gamingservices_8wekyb3d8bbwe</td></tr><tr><td>Solitaire &amp; Casual Games（微软纸牌）</td><td>microsoft.microsoftsolitairecollection_8wekyb3d8bbwe</td></tr></tbody></table><p>在把Microsoft Store和Solitaire &amp; Casual Games加入回环豁免后，再次刷新：</p><img src="./../../images/微软商店及微软商店安装的应用启用本地代理后无法联网解决办法/微软纸牌.png" style="zoom:50%;" /><img src="./../../images/微软商店及微软商店安装的应用启用本地代理后无法联网解决办法/微软商店.png" style="zoom:50%;" /><p>问题解决。</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%BE%AE%E8%BD%AF%E5%95%86%E5%BA%97%E5%8F%8A%E5%BE%AE%E8%BD%AF%E5%95%86%E5%BA%97%E5%AE%89%E8%A3%85%E7%9A%84%E5%BA%94%E7%94%A8%E5%90%AF%E7%94%A8%E6%9C%AC%E5%9C%B0%E4%BB%A3%E7%90%86%E5%90%8E%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%BE%AE%E8%BD%AF%E5%95%86%E5%BA%97%E5%8F%8A%E5%BE%AE%E8%BD%AF%E5%95%86%E5%BA%97%E5%AE%89%E8%A3%85%E7%9A%84%E5%BA%94%E7%94%A8%E5%90%AF%E7%94%A8%E6%9C%AC%E5%9C%B0%E4%BB%A3%E7%90%86%E5%90%8E%E6%97%A0%E6%B3%95%E8%81%94%E7%BD%91%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95"/>
    <published>2026-02-21T08:55:50.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><img src="./../../images/微软商店及微软商店安装的应用启用本地代理后无法联网解决办法/微软商店初始化失败.png" alt="微软商店初始化失败" style="zoom:50%;" />

<p>很抱歉！出现错误，Microsoft Store初始化失败。</p>
<p>这个页面绝对不止一个人看过，初始化失败有很多可能的原因，本文讨论的是：启用本地代理后，Microsoft Store 及其安装的 UWP]]>
    </summary>
    <title>微软商店及微软商店安装的应用启用本地代理后无法联网解决办法</title>
    <updated>2026-02-21T08:55:58.710Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <category term="Blog-Likes" scheme="https://hcyhub.com/tags/Blog-Likes/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Blog-Like-博客点赞插件"><a href="#Blog-Like-博客点赞插件" class="headerlink" title="Blog-Like 博客点赞插件"></a>Blog-Like 博客点赞插件</h1><p>Blog-Like，一个由我开发的简洁好用的点赞插件，<a href="https://github.com/2010HCY/Blog-Like">GitHub地址</a></p><h2 id="特点介绍"><a href="#特点介绍" class="headerlink" title="特点介绍"></a>特点介绍</h2><p>此点赞功能适配Hexo博客，适合任何静态网站，只是步骤有所不同，以下是它的特点：</p><ol><li>免费，支持 Cloudflare &#x2F; LeanCloud &#x2F; 自部署</li><li>简洁，轻轻一点即可完成操作</li><li>小巧，大小仅24.4kb（图像资源20kb）</li><li>易用：Hexo 仅需三步安装</li></ol><p>效果展示：</p><div id="zan" class="clearfix">    <div class="heart" onclick="goodplus(url, flag)"></div>    <br>    <div id="zan_text"></div></div>不仅仅是Hexo，所有静态博客都可以用，只是其他博客需要自己下载代码植入博客，Hexo可以一键安装。<p>我博客的点赞功能就是由它实现的，25年11月份把博客等网站从免费的CloudflarePage迁移到我自己的服务器上了，所以此插件也跟着更新了PHP后端版本，数据掌握在自己的手里，没有免费版的额度焦虑（不过10万次也没啥好焦虑的。。。）</p><p>今年（2026年）又更新了个<strong>OpenResty</strong>后端，高性能。</p><h2 id="快速开始"><a href="#快速开始" class="headerlink" title="快速开始"></a>快速开始</h2><h3 id="后端部署"><a href="#后端部署" class="headerlink" title="后端部署"></a>后端部署</h3><p>后端支持4种部署方法，分别是：</p><h4 id="1-使用Cloudflare做后端（推荐，可白嫖，最简单）"><a href="#1-使用Cloudflare做后端（推荐，可白嫖，最简单）" class="headerlink" title="1. 使用Cloudflare做后端（推荐，可白嫖，最简单）"></a>1. 使用Cloudflare做后端（推荐，可白嫖，最简单）</h4><p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/2010HCY/Blog-Likes-Backend"><img src="https://deploy.workers.cloudflare.com/button" alt="Deploy to Cloudflare Workers"></a></p><p>点击上方按钮一键部署后端，然后绑定自定义域（自带的workers.dev在中国大陆访问不稳定），部署好后默认路由是<code>example.com/like</code></p><h4 id="2-使用PHP做后端（相对简单）"><a href="#2-使用PHP做后端（相对简单）" class="headerlink" title="2. 使用PHP做后端（相对简单）"></a>2. 使用PHP做后端（相对简单）</h4><p><a href="./Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6%E5%90%8E%E7%AB%AF/PHP">PHP部署教程</a></p><h4 id="3-使用OpenResty后端（高性能）"><a href="#3-使用OpenResty后端（高性能）" class="headerlink" title="3. 使用OpenResty后端（高性能）"></a>3. 使用OpenResty后端（高性能）</h4><p><a href="./Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6%E5%90%8E%E7%AB%AF/OpenResty">OpenResty部署教程</a></p><h4 id="4-使用Leancloud做后端（不推荐，中国大陆要备案）"><a href="#4-使用Leancloud做后端（不推荐，中国大陆要备案）" class="headerlink" title="4. 使用Leancloud做后端（不推荐，中国大陆要备案）"></a>4. 使用Leancloud做后端（不推荐，中国大陆要备案）</h4><p><a href="./Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6%E5%90%8E%E7%AB%AF/Leancloud">Leancloud部署教程</a></p><h3 id="前端部署"><a href="#前端部署" class="headerlink" title="前端部署"></a>前端部署</h3><h4 id="安装配置Hexo插件"><a href="#安装配置Hexo插件" class="headerlink" title="安装配置Hexo插件"></a>安装配置Hexo插件</h4><blockquote><p>适用于Hexo框架，其他框架我没用过</p></blockquote><p>在博客根目录粘贴以下命令一键安装</p><pre class="line-numbers language-none"><code class="language-none">npm install hexo-blog-like --save<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>安装好后在博客根目录的<code>_config.yml</code>（<strong>不是你主题的<code>_config.yml</code>！</strong>）添加以下配置项并填写：</p><pre class="line-numbers language-yaml" data-language="yaml"><code class="language-yaml"><span class="token key atrule">Blog-Like</span><span class="token punctuation">:</span>  <span class="token key atrule">enable</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>                   <span class="token comment">#是否启用插件</span>  <span class="token key atrule">AutoInjectLike</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>           <span class="token comment">#是否开启自动添加点赞组件功能，默认关闭</span>  <span class="token key atrule">Backend</span><span class="token punctuation">:</span> Cloudflare            <span class="token comment">#Cloudflare | Leancloud | PHP，默认Cloudflare</span>  <span class="token key atrule">CloudflareBackend</span><span class="token punctuation">:</span>             <span class="token comment">#Cloudflare后端地址</span>  <span class="token key atrule">PHPBackend</span><span class="token punctuation">:</span>                    <span class="token comment">#自部署PHP后端地址</span>  <span class="token key atrule">AppID</span><span class="token punctuation">:</span>                         <span class="token comment">#如果使用Leancloud，在此填写Leancloud ID和KEY</span>  <span class="token key atrule">AppKEY</span><span class="token punctuation">:</span>                        <span class="token comment">#Leancloud KEY</span>  <span class="token key atrule">GoogleAnalytics</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>          <span class="token comment">#是否向谷歌分析发送点赞事件，默认关闭</span>  <span class="token key atrule">GAEventCategory</span><span class="token punctuation">:</span> Engagement    <span class="token comment">#点赞事件类别，默认Engagement</span>  <span class="token key atrule">GAEventAction</span><span class="token punctuation">:</span> Like            <span class="token comment">#事件名称，默认Like</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>后端地址可以用相对路径或绝对路径，例如<code>/api/like</code> or <code>https://example.com/api/like</code></p><p>完事后<code>hexo clean &amp;&amp; hexo g &amp;&amp; hexo s</code>启动博客，在你想要的显示位置（例如文章末尾）插入如下代码块，打开博客瞅瞅效果吧！</p><pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>zan<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>clearfix<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>heart<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token function">goodplus</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> flag<span class="token punctuation">)</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>br</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>zan_text<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><img src="/images/Hexo点赞插件/效果展示.png" style="zoom:80%;" /><p>如果你不想要手动一个个添加，你可以：</p><ol><li>编辑主题的文章模板（通常位于主题&#x2F;主题名&#x2F;目录下的<code>layout/_partial/article.ejs</code>或<code>layout/post.ejs</code>文件）</li><li>将<code>AutoInjectLike</code>设置为true，插件会自动在所有文章末尾加入点赞组件</li></ol><blockquote><p>我使用的主题是<code>matery</code>，该主题把代码段放置在<code>layout/_partial/reprint-statement.ejs</code>文件中最前面效果最好，其他主题视情况而定。</p><img src="/images/Hexo点赞插件/添加点赞组件.png" style="zoom:80%;" /></blockquote><h4 id="手动引入文件"><a href="#手动引入文件" class="headerlink" title="手动引入文件"></a>手动引入文件</h4><p>下载项目根目录下的三个文件<code>zan.js</code>、<code>zan.css</code>、<code>zan.png</code>，手动配置JS文件头的配置项、CSS中的图片路径</p><p>zan.js需要改的地方：</p><pre class="line-numbers language-none"><code class="language-none">&#x2F;&#x2F; &#x3D;&#x3D;&#x3D; 配置项 BEGIN &#x3D;&#x3D;&#x3D;var BLOG_LIKE_CONFIG &#x3D; &#123;    enable: true,    Backend: &quot;Cloudflare&quot;,           &#x2F;&#x2F; Cloudflare | Leancloud | PHP    CloudflareBackend: &quot;&quot;,           &#x2F;&#x2F; Cloudflare后端地址    PHPBackend: &quot;&#x2F;like&quot;,             &#x2F;&#x2F; PHP后端接口地址    AppID: &quot;&quot;,                       &#x2F;&#x2F; Leancloud AppID    AppKEY: &quot;&quot;,                      &#x2F;&#x2F; Leancloud AppKEY    GoogleAnalytics: false,          &#x2F;&#x2F; 是否启用谷歌分析事件追踪，默认关闭    GAEventCategory: &quot;Engagement&quot;,   &#x2F;&#x2F; 事件类别，默认Engagement    GAEventAction: &quot;Like&quot;            &#x2F;&#x2F; 事件操作名称，默认Like&#125;;&#x2F;&#x2F; &#x3D;&#x3D;&#x3D; 配置项 END &#x3D;&#x3D;&#x3D;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>zan.css需要改的地方：</p><pre class="line-numbers language-none"><code class="language-none">#zan .heart &#123;  background: url(zan.png);   &#x2F;* 把zan.png修改成实际图片路径或图床URL *&#x2F;  background-position: left;  background-repeat: no-repeat;  height: 100px;  width: 100px;  background-size: 2900%;  float: left;  display: inline-block;  position: relative;  left: 0;  top: 0;  z-index: 0;&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后在HTML页面<code>&lt;body&gt;</code>标签后<code>&lt;/body&gt;</code>前引入JS、CSS</p><pre class="line-numbers language-none"><code class="language-none">&lt;script type&#x3D;&quot;text&#x2F;javascript&quot; src&#x3D;&quot;js&#x2F;zan.js&quot; &gt;&lt;&#x2F;script&gt;&lt;link rel&#x3D;&quot;stylesheet&quot; href&#x3D;&quot;css&#x2F;zan.css&quot; &#x2F;&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><h3 id="项目目录说明"><a href="#项目目录说明" class="headerlink" title="项目目录说明"></a>项目目录说明</h3><pre class="line-numbers language-none"><code class="language-none">Blog-Like├── Backends&#x2F;        # 后端├── Hexo-Blog-Like&#x2F;  # Hexo插件├── zan.css├── zan.js└── zan.png<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>根目录下的zan.js是完整版JS，适合在非Hexo网站上引入使用，可删除未使用的函数凹一凹空间。</p><h2 id="未来打算"><a href="#未来打算" class="headerlink" title="未来打算"></a>未来打算</h2><ul><li><input checked="" disabled="" type="checkbox"> 此脚本目前没有限制点赞次数，同一个访客可以不停的搓点赞次数，搓个上万次不成问题，未来打算加入一个开关选择是否限制单访客点赞次数，若打开则通过Cookie记录限制只能点一次赞或几次。</li><li><input checked="" disabled="" type="checkbox"> 制作成Hexo插件，可以一键安装使用</li><li><input disabled="" type="checkbox"> 制作多种样式以供选择</li><li><input checked="" disabled="" type="checkbox"> 支持多种存储方式</li><li><input checked="" disabled="" type="checkbox"> 长期接收意见以及维护</li></ul><h2 id="版本更新记录"><a href="#版本更新记录" class="headerlink" title="版本更新记录"></a>版本更新记录</h2><details><summary>点击展开</summary>**v4.0.3 (2026.03.16)**<p>前端JS能够处理同一个页面上多个点赞组件，不再会因为有多组件导致只有第一个组件能正常显示点赞量。</p><p><img src="/images/Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6/%E5%A4%9A%E7%BB%84%E4%BB%B6%E5%8F%AA%E6%9C%89%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%98%BE%E7%A4%BA%E7%82%B9%E8%B5%9E%E9%87%8F.png" alt="多组件只有第一个显示点赞量"></p><p><img src="/images/Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6/%E5%A4%9A%E7%BB%84%E4%BB%B6%E5%90%8C%E6%AD%A5.png" alt="多组件只有第一个显示点赞量"></p><p><strong>v4.0.2 (2026.03.14)</strong></p><p>更新点赞精灵图</p><p>更新前后对比：</p><p><img src="/images/Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6/old-%E6%95%88%E6%9E%9C%E5%B1%95%E7%A4%BA.gif" alt="旧的点赞动画"></p><p><img src="/images/Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6/%E6%95%88%E6%9E%9C%E5%B1%95%E7%A4%BA.gif" alt="更新后的点赞动画"></p><p>分类文件，文档修改</p><p><strong>v4.0.1 (2026.03.12)</strong></p><p>新增自动添加点赞组件到文章末尾功能</p><p><strong>v4.0.0 (2026.03.12)</strong></p><p>不再允许同一个访客多次点赞同一个页面，现版本只允许点一次赞，再次点击取消点赞</p><p>后端地址可以填写相对路径、绝对路径，如<code>/api/like</code> or <code>https://example.com/api/like</code></p><p>新增了OpenResty路由模块</p><p><em><em>注意，v3.</em> 升级到v4.</em> 需要更新后端！**</p><p><strong>v3.0.0 (2025.12.03)</strong></p><p>不再使用URL传参，改为Post JSON，避免爬虫扫接口，添加新的存储PHP<br><em><em>注意，v2.</em> 升级到v3.</em> 需要更新后端！**</p><p><strong>v2.2.2 (2025.5.28)</strong></p><p>添加了谷歌分析发送事件功能，能够在谷歌分析里查看统计数据</p><p><strong>v2.2.1 (2025.5.17)</strong></p><p>添加了速率限制提示，现在你们可以用Cloudflare速率限制规则了</p><p><strong>v2.2.0 (2025.4.20)</strong></p><p>增加了Cloudflare存储点赞数据方式</p><p><strong>v2.1.2 (2025.2.06)</strong></p><p>修复了运行报错。</p><p><strong>v2.1.1 (2025.1.23)</strong></p><p>添加了中国版leancloud适配</p><p><strong>v2.1.0 (2025.1.16)</strong></p><p>修复了多个页面只能点五个赞，新版本把不同URL分开计算</p><p><strong>v2.0.0 (2025.1.15)</strong></p><p>发布npm包，可以在Hexo博客中一键安装咯！</p><p><strong>v1.1.0 (2025.1.15)</strong></p><p>增加了点赞次数限制，使用Cookie记录点赞次数，优化了代码逻辑</p><p><strong>v1.0.0 (2025.1.14)</strong></p><p>博客点赞插件横空出世 </p></details>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/Hexo%E7%82%B9%E8%B5%9E%E6%8F%92%E4%BB%B6"/>
    <published>2025-12-03T12:28:04.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Blog-Like-博客点赞插件"><a href="#Blog-Like-博客点赞插件" class="headerlink" title="Blog-Like 博客点赞插件"></a>Blog-Like 博客点赞插件</h1><p>Blog-Like，一个由我开发的简洁好用的点赞插件，<a href="https://github.com/2010HCY/Blog-Like">GitHub地址</a></p>
<h2]]>
    </summary>
    <title>Hexo点赞插件</title>
    <updated>2026-03-16T14:17:56.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="干货文章" scheme="https://hcyhub.com/tags/%E5%B9%B2%E8%B4%A7%E6%96%87%E7%AB%A0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><img src="./../../images/Adobe系列正版弹窗如何关闭？/正版弹窗.png" alt="正版弹窗" style="zoom:80%;" /><p>如图，之前我用了老长时间AI 2022版一直没弹窗啥的，爽用Adobe Illustrator，但我前阵子用了GenP下载最新版Illustrator会有这个正版弹窗，本想着装回旧的2022版继续爽用，但悲剧的是旧版也会弹窗了……直到昨天，我再一次打开后发现它不给我用了，点击按钮会直接关闭软件，瞄了眼Illustrator正版价格180多一个月，我决定还是自己想办法关掉这个天杀的正版弹窗吧，经过搜索，网上的方法无非就这些：</p><blockquote><ol><li>卸载重装</li><li>使用Adobe官方服务清除工具清除Adobe服务（AdobeCreativeCloudCleanerTool）</li><li>在hosts文件里添加网上流传的Adobe正版验证域名将其解析到127.0.0.1</li><li>禁用Adobe文件夹下的程序联网</li><li>在服务、定时任务里找到Adobe相关服务关掉（我试了下无相关服务）</li><li>找到 Adobe Genuine Service 这个应用并删掉（我试了下未找到）</li></ol></blockquote><p>总结：<strong>没半点用</strong></p><p>我又看了眼Adobe的订阅费用（是的，它特么甚至不是买断的），继续。</p><p>我打开了Illustrator，在任务管理器里我看了下它的子进程，发现有个叫“Creative Cloud lnterprocess Service”的进程（图为我禁用它联网后的样子，此时能正常使用，如果有正版弹窗的话下面还会有一堆其他的子进程）</p><img src="./../../images/Adobe系列正版弹窗如何关闭？/Creative Cloud lnterprocess Service子进程.png" alt="Creative Cloud lnterprocess Service子进程" style="zoom:80%;" /><p>一看你小子就不对劲，于是我顺藤摸瓜，找到了它所在的这个文件夹： <code>C:\Program Files (x86)\Common Files\Adobe\Adobe Desktop Common\IPCBox</code> ，嗯，就你小子一直弹窗影响我白嫖是吧，掐网线，<code>C:\Program Files (x86)\Common Files\Adobe</code>文件夹下所有的应用程序都给我掐网线！</p><p>舒服了。</p><img src="./../../images/Adobe系列正版弹窗如何关闭？/效果.png" alt="效果" style="zoom:80%;" /><p>P.S. 如果有使用代理，需要在代理服务端也屏蔽Adobe域名，代理就是用来绕过防火墙的会导致上述方式失效。</p><p>常见代理客户端屏蔽规则：<br>V2rayN：</p><pre class="line-numbers language-none"><code class="language-none">domain:adobe.io<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>Clash系列：</p><pre class="line-numbers language-yaml" data-language="yaml"><code class="language-yaml"><span class="token key atrule">rules</span><span class="token punctuation">:</span>  <span class="token punctuation">-</span> DOMAIN<span class="token punctuation">-</span>SUFFIX<span class="token punctuation">,</span>adobe.io<span class="token punctuation">,</span>REJECT<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>Host：</p><pre class="line-numbers language-none"><code class="language-none">127.0.0.1 adobe.io<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>Adobe大部分正版验证其实都是跑在adobe.io下的，这域名几乎都是API调用没普通网页，所以直接屏蔽该域名就行了，但是Adobe很鸡贼啊，他们用来正版验证域名有很多，所以有时候还是会弹正版弹窗，解决办法也很简单：</p><ol><li><p>关闭代理软件，直接禁止Adobe所有程序联网（关代理不现实，且联网程序很多容易没禁用干净）</p></li><li><p>直接把Adobe旗下所有域名统统拉黑：</p><pre class="line-numbers language-none"><code class="language-none">*.adobe.com*.adobe.io*.adobecc.com*.adobecces.com*.adobeccstatic.com*.adobedtm.com*.adobeexchange.com*.adobegenuine.com*.adobegov.com*.adobe-identity.com*.adobejanus.com*.adobelogin.com*.adobedc.net*.adobeoobe.com*.adobeprojectm.com*.adobesc.com*.adobe-services.com*.adobess.com*.adobesunbreak.com*.adobetag.com*.behance.net*.ftcdn.net*.typekit.com*.typekit.netslp-statics.astockcdn.net<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>直接把这一整个列表域名都拉黑掉，平时要访问时再临时允许，毕竟比起不开代理上网，不访问Adobe网站的可能性明显更小（谁没事情天天盯着，Adobe又不搞春夏秋冬促）</p></li></ol><p>2025.12.28 补充</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/Adobe%E7%B3%BB%E5%88%97%E6%AD%A3%E7%89%88%E5%BC%B9%E7%AA%97%E5%A6%82%E4%BD%95%E5%85%B3%E9%97%AD%EF%BC%9F</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/Adobe%E7%B3%BB%E5%88%97%E6%AD%A3%E7%89%88%E5%BC%B9%E7%AA%97%E5%A6%82%E4%BD%95%E5%85%B3%E9%97%AD%EF%BC%9F"/>
    <published>2025-10-29T12:34:37.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><img src="./../../images/Adobe系列正版弹窗如何关闭？/正版弹窗.png" alt="正版弹窗" style="zoom:80%;" />

<p>如图，之前我用了老长时间AI 2022版一直没弹窗啥的，爽用Adobe]]>
    </summary>
    <title>Adobe系列正版弹窗如何关闭？</title>
    <updated>2025-12-28T15:21:25.638Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="干货文章" scheme="https://hcyhub.com/tags/%E5%B9%B2%E8%B4%A7%E6%96%87%E7%AB%A0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>今天要下载个100GB的游戏，如果让Steam下载游戏走代理的话肯定不现实，又慢又费流量，那怎么设置才能让Steam下载游戏直连其他走代理？很简单，在路由配置里加这几条规则就行了：</p><pre class="line-numbers language-none"><code class="language-none">domain:*.steamcontent.com,domain:cm.steampowered.com,domain:csgo.wmsj.cn,domain:dl.steam.clngaa.com,domain:dl.steam.ksyna.com,domain:dota2.wmsj.cn,domain:example-example.com,domain:example-example2.com,domain:st.dl.bscstorage.net,domain:st.dl.eccdnx.com,domain:st.dl.pinyuncloud.com,domain:steamchina.com,domain:steamcontent.com,domain:steampipe.steamcontent.tnkjmec.com,domain:steampowered.com.8686c.com,domain:steamstatic.com.8686c.com,domain:steamusercontent.com,domain:wmsjsteam.com,domain:xz.pphimalayanrt.com<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p><img src="/images/%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AE%E8%AE%A9Steam%E6%B8%B8%E6%88%8F%E4%B8%8B%E8%BD%BD%E7%9B%B4%E8%BF%9E%E4%BD%86Steam%E7%BD%91%E9%A1%B5%E8%B5%B0%E4%BB%A3%E7%90%86%EF%BC%9F/%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE.png" alt="路由配置"></p><p>然后观察日志输出：</p><pre class="line-numbers language-none"><code class="language-none">2025&#x2F;10&#x2F;29 20:08:33.231853 [Info] [338609003] app&#x2F;dispatcher: taking detour [direct] for [tcp:cache3-hkg1.steamcontent.com:443]2025&#x2F;10&#x2F;29 20:08:33.231853 from 127.0.0.1:11854 accepted &#x2F;&#x2F;cache3-hkg1.steamcontent.com:443 [http -&gt; direct]2025&#x2F;10&#x2F;29 20:08:33.231853 [Info] [338609003] transport&#x2F;internet&#x2F;tcp: dialing TCP to tcp:cache3-hkg1.steamcontent.com:4432025&#x2F;10&#x2F;29 20:08:33.231853 [Debug] [338609003] transport&#x2F;internet: dialing to tcp:cache3-hkg1.steamcontent.com:443<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><p><code>*.steamcontent.com</code>就是Steam下载游戏的域名，状态是[direct]直连，很显然成功了，可以愉快的下载游戏开玩了，不得不说Steam的CDN就是快，下载轻松跑满带宽。</p><p>现在建议下载游戏还是走代理吧，现在Steam也半墙了速度很慢经常失败，尤其是创意工坊Mod，特殊地区尤为明显 - 2026.2.21</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%A6%82%E4%BD%95%E8%AE%A9Steam%E6%B8%B8%E6%88%8F%E4%B8%8B%E8%BD%BD%E7%9B%B4%E8%BF%9E%E4%BD%86Steam%E7%BD%91%E9%A1%B5%E8%B5%B0%E4%BB%A3%E7%90%86%EF%BC%9F</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%A6%82%E4%BD%95%E8%AE%A9Steam%E6%B8%B8%E6%88%8F%E4%B8%8B%E8%BD%BD%E7%9B%B4%E8%BF%9E%E4%BD%86Steam%E7%BD%91%E9%A1%B5%E8%B5%B0%E4%BB%A3%E7%90%86%EF%BC%9F"/>
    <published>2025-10-29T12:13:02.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>今天要下载个100GB的游戏，如果让Steam下载游戏走代理的话肯定不现实，又慢又费流量，那怎么设置才能让Steam下载游戏直连其他走代理？很简单，在路由配置里加这几条规则就行了：</p>
<pre class="line-numbers language-none"><code]]>
    </summary>
    <title>如何设置让Steam游戏下载直连但Steam网页走代理？</title>
    <updated>2026-02-21T07:25:04.478Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="干货文章" scheme="https://hcyhub.com/tags/%E5%B9%B2%E8%B4%A7%E6%96%87%E7%AB%A0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>本文是我的计算机网络相关知识的知识备忘，旨在忘记时快速回顾，需要时CV。<br>本篇涵盖HTTP协议、现代网络协议分层原理、常见应用&#x2F;传输层协议</p><p>内容包含</p><ol><li>HTTP<ol><li>历代HTTP版本</li><li>HTTP响应头</li><li>HTTP状态码</li></ol></li><li>TCP、UDP</li><li>TLS与SSL</li><li>OSI七层模型</li></ol><h3 id="1-OSI七层模型"><a href="#1-OSI七层模型" class="headerlink" title="1. OSI七层模型"></a>1. OSI七层模型</h3><h4 id="OSI七层模型概览"><a href="#OSI七层模型概览" class="headerlink" title="OSI七层模型概览"></a>OSI七层模型概览</h4><table><thead><tr><th>层级</th><th>名称</th><th>作用和典型协议</th><th>作用</th></tr></thead><tbody><tr><td>7</td><td>应用层</td><td>HTTP, FTP, SMTP, SSH…</td><td>应用间通讯，例如HTTP（浏览器），SMTP（Email）</td></tr><tr><td>6</td><td>表示层</td><td>TLS&#x2F;SSL, JPEG, MPEG</td><td>加密（TLS）、图片&#x2F;视频编码，用于把数据转换成双方看得懂的格式</td></tr><tr><td>5</td><td>会话层</td><td>RPC, NetBIOS, SMB</td><td>负责建立、管理、终止两台计算机间的连接（通信过程）</td></tr><tr><td>4</td><td>传输层</td><td>TCP, UDP</td><td>数据传输控制，最典型的就是大名鼎鼎的TCP</td></tr><tr><td>3</td><td>网络层</td><td>IP, ICMP, IPv6</td><td>跨网路寻址，寻找网络间的两台计算机，例如广域网寻找最佳路由建立通讯</td></tr><tr><td>2</td><td>数据链路层</td><td>Ethernet, PPP, VLAN, ARP</td><td>同一网络下计算机间通讯的链路，例如MAC寻址</td></tr><tr><td>1</td><td>物理层</td><td>光纤，网线，电磁波……</td><td>构成网络的物理设备，传输原始比特流</td></tr></tbody></table><blockquote><p>注：TLS 在 OSI 理论上属表示层，但在实际 TCP&#x2F;IP 架构中常被视为一个介于应用层和传输层之间的独立层次</p></blockquote><p>上面这个表格就是完整的OSI七层模型，OSI（Open System Interconnect）是一个概念性的网络参考模型，由国际标准化组织（ISO）于1985年提出，将网络通信过程分为七个逻辑层，从名字（OSI&#x2F;开放式系统互连）就能看出，它制定的是一套开放的标准通讯协定，让不同设备、系统能够进行互连。</p><p>OSI模型从<strong>第 1 层（物理层）</strong>开始，它是<strong>最基础的层次</strong>，模型的底层。模型中的每一层都<strong>建立在紧邻的下一层提供的服务之上</strong>运行，最终将交付到 <strong>第 7 层（应用层）</strong>，也就是离用户最近的层次。</p><h4 id="详细解释"><a href="#详细解释" class="headerlink" title="详细解释"></a>详细解释</h4><h5 id="物理层（第1层，Physical-Layer）"><a href="#物理层（第1层，Physical-Layer）" class="headerlink" title="物理层（第1层，Physical Layer）"></a>物理层（第1层，Physical Layer）</h5><p>第一场物理层是模型的起点、最底层。物理层负责在计算机间传输原始比特流，用真实的物理介质传输数据，这一层没有任何判断，仅作为比特流传输。</p><p>典型例子就是光纤、网线、无线信号（WiFi和蓝牙）</p><p>顺便说一句，WiFi居然都出WiFi 7了（IEEE 802.11be），我现在用的是WiFi 5。</p><h5 id="数据链路层（第2层，Data-Link-Layer）"><a href="#数据链路层（第2层，Data-Link-Layer）" class="headerlink" title="数据链路层（第2层，Data Link Layer）"></a>数据链路层（第2层，Data Link Layer）</h5><p>此层级负责同一网络间的数据传输，比如局域网下使用MAC地址找到隔壁的NAS下载图片、发文档给打印机打印就是在此层上运行的，数据链路层的作用是稳定的把数据包传输到同一网段下的另一台设备。</p><p>交换机就是数据链路层的典型代表，A设备向B发送数据，交换机通过MAC寻址找到B，然后把数据丢给B处理</p><p>在在TCP&#x2F;IP模型中第一层和第二层合并为网络接口层，因为物理层和数据链路层密切相关，共同负责数据的物理传输和本地寻址。</p><h5 id="网络层（第3层，Network-Layer）"><a href="#网络层（第3层，Network-Layer）" class="headerlink" title="网络层（第3层，Network Layer）"></a>网络层（第3层，Network Layer）</h5><p>网络层负责的是<strong>不同局域网之间的数据转发和寻址</strong>，能让信息穿越大量中继节点，找到全球任意一台联网设备。最核心的是<strong>IP协议、路由选择、分包转发</strong>等。</p><p>比如我现在要访问1.1.1.1这个IP，数据包在网络层传输，我可以通过tracert命令跟踪路由节点，命令输出为：</p><pre class="line-numbers language-none"><code class="language-none">C:\Users\Ethaniel&gt;tracert 1.1.1.1通过最多 30 个跃点跟踪到 one.one.one.one [1.1.1.1] 的路由:  1     3 ms     3 ms     3 ms  192.168.0.1  2     3 ms     3 ms     3 ms  192.168.1.1  3     9 ms     6 ms     6 ms  100.119.0.1  4     *        *        *     请求超时。  5     *        *        *     请求超时。  6     *        *        *     请求超时。  7     *       18 ms     *     202.97.X.X  8     *        *        *     请求超时。  9     *       85 ms    79 ms  202.97.X.X 10     *        *        *     请求超时。 11    79 ms    79 ms    79 ms  162.158.160.37 12    64 ms    66 ms    64 ms  one.one.one.one [1.1.1.1]跟踪完成。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>可以看到从我的电脑到1.1.1.1要经过12个路由，出国路线是CN2 GT（202.97.X.X是电信CN2骨干网）</p><p>请求超时很正常，路由节点设置的原因</p><h5 id="传输层（第4层，Transport-Layer）"><a href="#传输层（第4层，Transport-Layer）" class="headerlink" title="传输层（第4层，Transport Layer）"></a>传输层（第4层，Transport Layer）</h5><p>传输层复制处理两个设备间的可靠（或高效，二选一）通信，它有<strong>端口</strong>、<strong>分段&#x2F;重组</strong>、<strong>流控</strong>、<strong>错误检验</strong>等机制。</p><p>传输层的典型代表是TCP和UDP，为什么说两个设备间通信只能在可靠、高效间二选一？因为协议问题，TCP作为可靠性优先的协议使用三次握手四次挥手，极大程度提高了可靠性，但缺点就是额外开销大，延迟更高；而UDP则是高效优先，什么握手挥手统统没有，一股脑打包数据包发送出去，收没收到不管我的事，用于延迟敏感、小丢包无所谓的场景。</p><p><a href="#TCP%E4%B8%8EUDP">TCP与UDP详细介绍</a></p><p>HTTP获取网页内容、电子邮件这种不容差错的场景通常使用TCP（当然有例外，HTTP 3.0是基于UDP QUIC的）；直播、实时游戏这种要求高速的则使用UDP（电话卡住了没关系，但对方说一句话五分钟后才能听到就很要命了）</p><h5 id="会话层（第5层，Session-Layer）"><a href="#会话层（第5层，Session-Layer）" class="headerlink" title="会话层（第5层，Session Layer）"></a>会话层（第5层，Session Layer）</h5><p>会话层负责建立、管理、终止两个应用进程间的连接（通信过程），常见的协议有SMB之类的网络服务协议</p><p>会话层的会话控制能控制传输方式，常见的有：单工、半双工、全双工，单工传输数据只能由一方发给另一方，例如HDMI、收音机、早期电视；半双工能双向传输数据，但不能同时进行，比如对讲机、上古时期的以太网集线器；全双工传输相当于由两个功能完整方向不一致的单工传输组成，能同时收发，比如USB3.0。</p><p>同步和恢复这个功能也是由会话层提供的，用于传输数据到一半恢复传输。</p><h5 id="表示层（第6层，Presentation-Layer）"><a href="#表示层（第6层，Presentation-Layer）" class="headerlink" title="表示层（第6层，Presentation Layer）"></a>表示层（第6层，Presentation Layer）</h5><p>表示层用于<strong>数据的翻译、加密和压缩</strong>——确保彼此能够处理数据。例如HTTP数据用TLS加密。</p><p>表示层是用于处理数据的，比如解压还原、加密解密，典型例子就是用于加密的TLS。</p><h5 id="应用层（第7层，Application-Layer）"><a href="#应用层（第7层，Application-Layer）" class="headerlink" title="应用层（第7层，Application Layer）"></a>应用层（第7层，Application Layer）</h5><p>应用层为七层模型中的最高层，它规定了终端软件如何与网络好好说话，比如浏览器的HTTP、电子邮件的SMTP，各类软件使用此层的协议使用网络。</p><p>在TCP&#x2F;IP模型中应用层通常与表示层、会话层合并为一个单一的层次：<strong>应用层</strong></p><p>为什么合并OSI的第5、6、7为一层？因为这三层是联系最密切的，比如TLS就需要做到建立安全连接（第五层）、加解密（第六层）；HTTP协议规定了HTTP文本（HTML语法），即特定格式（第六层）是专门为特定协议（第七层）服务的。</p><p>OSI模型七层和TCP&#x2F;IP 四层模型对比</p><table><thead><tr><th>OSI 七层模型</th><th>TCP&#x2F;IP 四层模型</th><th>对应的层级编号</th></tr></thead><tbody><tr><td>L5: 会话层 L6: 表示层 L7: 应用层</td><td>应用层 (Application Layer)</td><td>L5,L6,L7三层合并</td></tr><tr><td>L4: 传输层</td><td>传输层 (Transport Layer)</td><td>L4</td></tr><tr><td>L3: 网络层</td><td>互联网层 (Internet Layer)</td><td>L3</td></tr><tr><td>L1: 物理层 L2: 数据链路层</td><td>网络接口层 (Network Interface Layer)</td><td>L1,L2双层合并</td></tr></tbody></table><hr><h3 id="2-TCP-与-UDP"><a href="#2-TCP-与-UDP" class="headerlink" title="2. TCP 与 UDP"></a>2. TCP 与 UDP</h3><p>TCP和UDP作为第四层传输层最出名最常用的两个协议，分别对应可靠传输、高效传输，比如HTTP用TCP，DNS用UDP</p><table><thead><tr><th>协议</th><th>类型</th><th>发布时间</th><th>主要特性</th><th>优点</th><th>缺点</th></tr></thead><tbody><tr><td>TCP</td><td>传输层协议</td><td>1974</td><td>可靠传输、保证顺序、丢包重传</td><td>可靠</td><td>时延、连接消耗高</td></tr><tr><td>UDP</td><td>传输层协议</td><td>1980</td><td>无连接、不保证送到、不重传</td><td>快、简洁、实时性强</td><td>不保证可靠性</td></tr></tbody></table><h5 id="TCP"><a href="#TCP" class="headerlink" title="TCP"></a>TCP</h5><p>作为可靠性优先的协议，TCP加入了许多机制，如三次握手、四次挥手，错误恢复与容错、差错检测、流量控制。</p><p><strong>三次握手（建立连接）：</strong></p><ol><li><p><strong>客户端</strong>发送SYN请求（请求建立连接）</p></li><li><p><strong>服务器</strong>收到后回复SYN+ACK包（同意建立，同时应答）</p></li><li><p><strong>客户端</strong>再返回ACK包（确认收到）</p><p>连接正式建立</p></li></ol><p><strong>四次挥手（断开连接）：</strong></p><ol><li><p><strong>客户端</strong>发送FIN包（申请关闭连接）</p></li><li><p><strong>服务器</strong>返回ACK（先确认收到关闭请求）</p></li><li><p><strong>服务器</strong>发送FIN（服务器剩余数据也发完，申请断开）</p></li><li><p><strong>客户端</strong>发ACK（最终确认）</p><p>连接安全断开</p></li></ol><p>错误恢复与容错：</p><p>错误恢复主要通过<strong>超时重传</strong>来实现，确保丢失的数据段能够被找回。</p><ol><li><strong>计时启动：</strong> 客户端发送TCP报文段后立即启动<strong>重传计时器</strong></li><li><strong>等待确认：</strong> 客户端等待接收方返回该数据段的ACK确认</li><li><strong>判断丢失并重传：</strong> 如果在计时器<strong>超时</strong>前未收到ACK，客户端认为数据或ACK丢失。</li><li><strong>操作：</strong> 发送方<strong>重传</strong>该数据段。</li></ol><p>差错检测：</p><p>差错检测用于发现数据内容在传输过程中是否被破坏或篡改。</p><ol><li>发送端根据部分数据内容和TCP头部计算一个<strong>校验和</strong>，并将校验和放置在TCP报文段的头部。</li><li>接收方收到报文段后，重新计算校验和</li><li>如果计算结果与报文段中的校验和不匹配，则接收方丢弃该报文段不发送ACK（迫使发送方重传）</li></ol><p>流量控制：</p><p>流量控制用于协调发送方和接收方的速度，防止网速快的一方将另一方淹没，使用滑动窗口控制。</p><ol><li>接收方在ACK报文段中包含一个“窗口大小”字段，窗口大小表示接收方当前<strong>缓冲区还能容纳</strong>多少数据</li><li>发送方严格遵守这个窗口限制，不发送超出接收方窗口大小的数据，并且根据ACK窗口大小字段动态协调速率</li></ol><p>基于上述优点，TCP广泛应用于各种网络通信，比如HTTP、SMTP、FTP、SSH等不容差错的场景。</p><h5 id="UDP"><a href="#UDP" class="headerlink" title="UDP"></a>UDP</h5><p>TCP协议以可靠性为主，UDP就随便多了，UDP的特点是<strong>无连接、无确认、无序列化机制</strong></p><ul><li><strong>无连接</strong>：发送数据前不用花时间握手，直接发，提供目标IP和端口就能扔过去</li><li><strong>无确认</strong>：数据发出不管对面收没收到，丢包不重要</li><li><strong>无序</strong>：收到的包顺序可能和发送顺序不同，排序由应用层负责</li></ul><p>优点：</p><ol><li>简单高效</li><li>无连接、头部小，占带宽少</li><li>实时性强</li></ol><p>缺点：</p><ol><li>不保证数据包全部送达，丢包不重传</li><li>不保证接收到的顺序</li></ol><p>基于上述特点，UDP通常应用于需要实时性高的场景，比如实时对战游戏、直播，以及DNS。毕竟都是实时的东西，没有等待重传的必要（难不成还等待重传过去的战局、视频？），</p><table><thead><tr><th>特征</th><th>TCP</th><th>UDP</th></tr></thead><tbody><tr><td>是否建立连接</td><td>有（握手&#x2F;挥手）</td><td>无</td></tr><tr><td>可靠性</td><td>高，重传纠错</td><td>无，丢了就丢 <del>嫌弃的话自己整条好的线路</del></td></tr><tr><td>数据包排序</td><td>自动排序</td><td>无，应用层处理</td></tr><tr><td>延迟&#x2F;实时性</td><td>稍高（握手&#x2F;流控&#x2F;等待）</td><td>极低（即发即收 <del>收不到拉到</del>）</td></tr><tr><td>性能开销</td><td>稍大（头部、连接、管理等操作多）</td><td>小（几字节头部，无状态）</td></tr><tr><td>用于</td><td>网页、下载文件传输数据</td><td>直播、电话、DNS、在线游戏</td></tr></tbody></table><hr><h3 id="3-TLS-与-SSL"><a href="#3-TLS-与-SSL" class="headerlink" title="3. TLS 与 SSL"></a>3. TLS 与 SSL</h3><h5 id="SSL与TLS"><a href="#SSL与TLS" class="headerlink" title="SSL与TLS"></a>SSL与TLS</h5><p>SSL（Secure Sockets Layer）是最早广泛用于Web安全传输的协议，后续被TLS（Transport Layer Security）取代和升级。</p><p>TLS&#x2F;SSL提供<strong>数据加密</strong>（防止被截获数据）、<strong>身份认证</strong>、<strong>数据完整性校验</strong>，SSL加密是之前使用的加密手段，先已停用被TLS取代，不过SSL证书这个名字倒是遗留下来作为TSL证书的名字了</p><p>SSL证书（X.509证书）是数字证书，由权威CA机构签发，负责加密密钥交换及数据传输，不是协议，而是密钥管理和身份标识，CA签名必须预装CA信任链，才会信这个证书。</p><h5 id="历代TLS-SSL协议"><a href="#历代TLS-SSL协议" class="headerlink" title="历代TLS&#x2F;SSL协议"></a>历代TLS&#x2F;SSL协议</h5><p>TLS 各版本核心区别：</p><table><thead><tr><th>协议版本</th><th>发布时间</th><th>特性</th><th>特点及与前代关系</th><th>状态</th></tr></thead><tbody><tr><td>SSLv2</td><td>1995</td><td>最早期加密协议</td><td>很多严重漏洞</td><td>已弃用</td></tr><tr><td>SSLv3</td><td>1996</td><td>加强了安全</td><td>仍有POODLE漏洞</td><td>已弃用</td></tr><tr><td>TLS 1.0</td><td>1999</td><td>本质上是SSL 3.1</td><td>向后兼容SSL 3，大部分环境停用</td><td>废弃中</td></tr><tr><td>TLS 1.1</td><td>2006</td><td>微升级</td><td>增强算法和协议协商，已极少使用</td><td>废弃中</td></tr><tr><td>TLS 1.2</td><td>2008</td><td>主流</td><td>支持更强的加密单次SHA256等</td><td>主流</td></tr><tr><td>TLS 1.3</td><td>2018</td><td>最新标准</td><td>简化握手步骤，去掉弱算法，前向保密性，不向前兼容</td><td>高安全</td></tr></tbody></table><p>TLS 1.3 特点：</p><ul><li>手续更少，只需要一次或零次往返即可建好加密通道</li><li>禁用过去的MD5、SHA-1等弱加密，强制高安全算法</li><li>完全加密握手内容（更难被窃听、注入）</li><li>前向保密，即使服务器私钥泄露，过去的通信也能保持安全</li><li><strong>移除旧版特性</strong>（不再兼容TLS 1.2的旧加密套件）</li></ul><hr><h3 id="4-HTTP"><a href="#4-HTTP" class="headerlink" title="4. HTTP"></a>4. HTTP</h3><p>HTTP（HyperText Transfer Protocol）是超文本传输协议，是Web最基础的数据交换标准。它定义的是浏览器、服务器如何请求和响应网页、图片、文件等资源。HTTP属于应用层协议，建立在TCP（或QUIC&#x2F;UDP）的基础上。</p><p>同时HTTP还定义了HTML（HyperText Markup Language&#x2F;超文本标记语言）这种标记语言用于描述网页结构看，让浏览器可以读取渲染</p><h5 id="历代HTTP协议"><a href="#历代HTTP协议" class="headerlink" title="历代HTTP协议"></a>历代HTTP协议</h5><table><thead><tr><th>协议</th><th>发布时间</th><th>传输层</th><th>多路复用</th><th>首部压缩</th><th>服务器推送</th><th>队头阻塞</th><th>加密支持</th><th>性能</th><th>优点</th><th>缺点</th></tr></thead><tbody><tr><td>HTTP&#x2F;1.0</td><td>1996</td><td>TCP</td><td>无</td><td>无</td><td>无</td><td>有</td><td>无</td><td>低</td><td>实现简单</td><td>连接浪费，缓存机制弱，无host头法区分虚拟主机</td></tr><tr><td>HTTP&#x2F;1.1</td><td>1997</td><td>TCP</td><td>管道化</td><td>无</td><td>无</td><td>有</td><td>TLS</td><td>中</td><td>持久连接、管道化、支持虚拟主机、缓存机制丰富</td><td>队头阻塞，管道化不完善，连接复用有限</td></tr><tr><td>HTTP&#x2F;2</td><td>2015</td><td>TCP</td><td>有</td><td>HPACK</td><td>有</td><td>有（TCP级）</td><td>TLS</td><td>高</td><td>多路复用、头部压缩、推送技术提升性能，兼容性好</td><td>仍基于TCP，TCP层面队头阻塞（丢一个包需等所有流）</td></tr><tr><td>HTTP&#x2F;3</td><td>2022</td><td>UDP&#x2F;QUIC</td><td>有</td><td>QPACK</td><td>有</td><td>无</td><td>内建TLS</td><td>很高</td><td>基于UDP&#x2F;QUIC，多路复用无队头阻塞，握手快</td><td>UDP部署对CDN&#x2F;防火墙要求高，旧设备兼容性待完善</td></tr></tbody></table><p>各代具体变化详细说明</p><ol><li><strong>HTTP&#x2F;1.0</strong><ul><li>每次请求时都新建TCP连接，响应后关闭，效率低下</li><li>支持最基本的GET、POST等操作，简单明文报文格式，功能有限</li><li>缓存控制不完善、无虚拟主机支持（同IP仅能部署一个网站，无法使用CDN）</li></ul></li><li><strong>HTTP&#x2F;1.1</strong><ul><li>默认支持持久连接，同一连接可多次复用，提升效率</li><li>新增Host头支持虚拟主机，一个IP可承载多个网站</li><li>引入管道化请求，新增更多请求方法（如PUT、DELETE、OPTIONS）</li><li>丰富了缓存控制，支持分块传输、断点续传、带宽优化等</li></ul></li><li><strong>HTTP&#x2F;2</strong><ul><li>使用二进制分帧协议替换文本，所有报文都被封装为二进制帧</li><li>核心引入多路复用，同一TCP连接上可并发多请求，减少队头阻塞</li><li>支持头部压缩（HPACK），带宽更节省</li><li>引入服务器推送，可提前下发关联资源</li></ul></li><li><strong>HTTP&#x2F;3</strong><ul><li>基于UDP的QUIC协议，不再受制于TCP多路复用的队头阻塞</li><li>连接建立更快（0-RTT&#x2F;1-RTT握手），自动加密（内建TLS 1.3）</li><li>客户端可无缝切换网络，丢包恢复、延迟控制性能大幅提升</li></ul></li></ol><h5 id="HTTP状态码全览"><a href="#HTTP状态码全览" class="headerlink" title="HTTP状态码全览"></a>HTTP状态码全览</h5><p>HTTP状态码分为五大类，分别是：</p><ul><li>1XX 信息性响应（Informational）</li><li>2XX 成功响应（Successful）</li><li>3xx 重定向响应（Redirection）</li><li>4xx 客户端错误（Client Error）</li><li>5xx 服务器错误（Server Error）</li></ul><table><thead><tr><th>状态码</th><th>名称</th><th>说明</th></tr></thead><tbody><tr><td><strong>1xx 信息</strong></td><td></td><td></td></tr><tr><td>100</td><td>Continue</td><td>继续，客户端应继续请求</td></tr><tr><td>101</td><td>Switching Protocols</td><td>协议切换（如HTTP升级为WebSocket）</td></tr><tr><td>102</td><td>Processing</td><td>正在处理（WebDAV扩展）</td></tr><tr><td>103</td><td>Early Hints</td><td>预先提示，如可用于提前推送资源头部</td></tr><tr><td><strong>2xx 成功</strong></td><td></td><td></td></tr><tr><td>200</td><td>OK</td><td>请求成功</td></tr><tr><td>201</td><td>Created</td><td>成功创建新资源</td></tr><tr><td>202</td><td>Accepted</td><td>请求已接收，处理中</td></tr><tr><td>203</td><td>Non-Authoritative Information</td><td>非授权信息，代理返回的修改版本</td></tr><tr><td>204</td><td>No Content</td><td>成功，无响应体</td></tr><tr><td>205</td><td>Reset Content</td><td>成功，请重置表单或视图</td></tr><tr><td>206</td><td>Partial Content</td><td>部分内容（如断点续传分片下载）</td></tr><tr><td>207</td><td>Multi-Status</td><td>多状态（WebDAV扩展）</td></tr><tr><td>208</td><td>Already Reported</td><td>已报告（WebDAV扩展）</td></tr><tr><td>226</td><td>IM Used</td><td>已用IM（Delta编码，RFC3229）</td></tr><tr><td><strong>3xx 重定向</strong></td><td></td><td></td></tr><tr><td>300</td><td>Multiple Choices</td><td>多种可选响应</td></tr><tr><td>301</td><td>Moved Permanently</td><td>永久重定向</td></tr><tr><td>302</td><td>Found</td><td>临时重定向</td></tr><tr><td>303</td><td>See Other</td><td>推荐POST提交后跳转的页面，客户端用GET获取</td></tr><tr><td>304</td><td>Not Modified</td><td>客户端缓存未过期，无需传输内容（缓存命中）</td></tr><tr><td>305</td><td>Use Proxy</td><td>需代理访问（弃用）</td></tr><tr><td>307</td><td>Temporary Redirect</td><td>临时重定向（严格要求用原请求方法）</td></tr><tr><td>308</td><td>Permanent Redirect</td><td>永久重定向（严格要求用原请求方法）</td></tr><tr><td><strong>4xx 客户端错误</strong></td><td></td><td></td></tr><tr><td>400</td><td>Bad Request</td><td>错误请求，参数、语法错误</td></tr><tr><td>401</td><td>Unauthorized</td><td>未授权&#x2F;需认证</td></tr><tr><td>402</td><td>Payment Required</td><td>需付费访问（极少用）</td></tr><tr><td>403</td><td>Forbidden</td><td>拒绝访问，无权限</td></tr><tr><td>404</td><td>Not Found</td><td>资源不存在</td></tr><tr><td>405</td><td>Method Not Allowed</td><td>方法不允许</td></tr><tr><td>406</td><td>Not Acceptable</td><td>请求资源内容类型客户端不接受</td></tr><tr><td>407</td><td>Proxy Authentication Required</td><td>需代理认证</td></tr><tr><td>408</td><td>Request Timeout</td><td>请求超时</td></tr><tr><td>409</td><td>Conflict</td><td>资源状态与当前请求冲突（如版本冲突）</td></tr><tr><td>410</td><td>Gone</td><td>已删除（更绝对的404，用于SEO）</td></tr><tr><td>411</td><td>Length Required</td><td>需指定Content-Length头</td></tr><tr><td>412</td><td>Precondition Failed</td><td>前置条件不成立</td></tr><tr><td>413</td><td>Payload Too Large</td><td>请求体过大</td></tr><tr><td>414</td><td>URI Too Long</td><td>请求URI太长</td></tr><tr><td>415</td><td>Unsupported Media Type</td><td>不支持的数据类型</td></tr><tr><td>416</td><td>Range Not Satisfiable</td><td>服务端无法满足Range请求</td></tr><tr><td>417</td><td>Expectation Failed</td><td>Expect头字段无法满足</td></tr><tr><td>418</td><td>I’m a teapot</td><td>我是个茶壶（愚人节彩蛋）</td></tr><tr><td>421</td><td>Misdirected Request</td><td>请求错发到不合适的服务器</td></tr><tr><td>422</td><td>Unprocessable Entity</td><td>请求格式正确，但语义错误无法遵循（WebDAV扩展）</td></tr><tr><td>423</td><td>Locked</td><td>正在访问的资源被锁定（WebDAV扩展）</td></tr><tr><td>424</td><td>Failed Dependency</td><td>由于前一个请求失败，请求失败（WebDAV扩展）</td></tr><tr><td>425</td><td>Too Early</td><td>服务器不愿意冒险处理可能被重播的请求</td></tr><tr><td>426</td><td>Upgrade Required</td><td>服务器拒绝使用当前协议执行请求需要升级协议</td></tr><tr><td>428</td><td>Precondition Required</td><td>源服务器要求请求是有条件的</td></tr><tr><td>429</td><td>Too Many Requests</td><td>请求过快被速率限制了</td></tr><tr><td>431</td><td>Request Header Fields Too Large</td><td>请求头过大服务器不愿意处理</td></tr><tr><td>451</td><td>Unavailable For Legal Reasons</td><td>因法律要求不可用（内容屏蔽）</td></tr><tr><td><strong>5xx 服务器错误</strong></td><td></td><td></td></tr><tr><td>500</td><td>Internal Server Error</td><td>服务器不知道如何处理，服务器崩了</td></tr><tr><td>501</td><td>Not Implemented</td><td>不支持此请求方法</td></tr><tr><td>502</td><td>Bad Gateway</td><td>网关&#x2F;代理错误，连接上游失败</td></tr><tr><td>503</td><td>Service Unavailable</td><td>服务器没准备好响应请求（宕机、过载或维护）</td></tr><tr><td>504</td><td>Gateway Timeout</td><td>网关&#x2F;代理超时</td></tr><tr><td>505</td><td>HTTP Version Not Supported</td><td>不支持的HTTP协议版本</td></tr><tr><td>506</td><td>Variant Also Negotiates</td><td>服务器存在内部配置错误（协商变体出错）</td></tr><tr><td>507</td><td>Insufficient Storage</td><td>存储空间不足（WebDAV扩展）</td></tr><tr><td>508</td><td>Loop Detected</td><td>检测到无限循环（WebDAV扩展）</td></tr><tr><td>510</td><td>Not Extended</td><td>服务器需要对请求进行进一步扩展才能完成请求</td></tr><tr><td>511</td><td>Network Authentication Required</td><td>客户端需要进行身份验证才能获得网络访问权限</td></tr></tbody></table><p><strong>注：</strong> </p><ul><li>某些状态码（如207、422、423、424、507等）为<a href="https://zh.wikipedia.org/wiki/WebDAV">WebDAV </a>扩展。</li><li>418号为彩蛋。</li><li>306、402等较少用或保留。</li><li>428、429、431、451、508等为新标准&#x2F;现代Web安全或流量控制用途。</li><li>103 Early Hints、425 Too Early、226 IM Used等为新协议特性，部分环境才支持。</li></ul><h5 id="HTTP请求方法"><a href="#HTTP请求方法" class="headerlink" title="HTTP请求方法"></a>HTTP请求方法</h5><table><thead><tr><th>方法</th><th>含义&#x2F;用途</th><th>典型应用</th></tr></thead><tbody><tr><td>GET</td><td>获取资源（请求的数据在URL中明文传递）</td><td>网页、图片、接口查询</td></tr><tr><td>POST</td><td>提交数据（请求体里发送），服务器会处理数据并返回结果</td><td>表单提交、登录、注册</td></tr><tr><td>PUT</td><td>用于完整地<strong>替换&#x2F;修改</strong>指定资源，不存在则创建，幂等</td><td>资源整体替换、配置写入</td></tr><tr><td>PATCH</td><td>对资源的<strong>部分内容修改</strong>，不是整体替换</td><td>文档或配置部分更新</td></tr><tr><td>DELETE</td><td>删除指定资源，幂等</td><td>删除数据接口</td></tr><tr><td>OPTIONS</td><td>查询服务器支持哪些 HTTP 方法，以及相关功能（如跨域CORS预检）</td><td>前端跨域请求、接口能力测试</td></tr><tr><td>HEAD</td><td>请求资源的响应头，不返回正文（内容）</td><td>获取网站元信息</td></tr><tr><td>TRACE</td><td>回显服务器收到的请求（调试用），大多服务器禁用</td><td>调试HTTP中转</td></tr><tr><td>CONNECT</td><td>用于代理&#x2F;隧道，比如HTTPS握手前升级到TCP隧道</td><td>代理服务器</td></tr></tbody></table><hr>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%B8%AA%E4%BA%BA%E5%A4%87%E5%BF%98%EF%BC%9A%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE%E5%8E%9F%E7%90%86</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%B8%AA%E4%BA%BA%E5%A4%87%E5%BF%98%EF%BC%9A%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE%E5%8E%9F%E7%90%86"/>
    <published>2025-10-25T10:26:17.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink"]]>
    </summary>
    <title>个人备忘：计算机网络协议原理</title>
    <updated>2025-10-25T14:44:11.815Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="博客发展历程" scheme="https://hcyhub.com/tags/%E5%8D%9A%E5%AE%A2%E5%8F%91%E5%B1%95%E5%8E%86%E7%A8%8B/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>我的博客域名换了好多次，细算一下应当有5次了，之前的域名都是老便宜的垃圾域名，像是超市做活动送的篮子一样，而我的博客就是那随手塞篮子里的东西。</p><p>我对COM这个域名的执念应该有好久好深了，估计可以追溯到我好小好小的时候。我为什么会做这个博客呢？我从小就对那些设计优美的网站很感兴趣，拿着鼠标在那边点点点想知道它是怎么做的，那时的乐趣就是输入一个个网址，然后看着网页加载呈现，多神奇的东西啊！于是我就有了个执念，想要做一个自己的网站、网页，哎，反正只要是浏览器输入域名后能打开、能显示的就是我想要的，所以我在去年翻阅了不少博客框架文档，最后选择了Hexo，做了这个博客，在屏幕上看着这神奇的一幕幕，一点点理解这个网站。</p><p>在它上线的第一个月，我不厌其烦的不停找插件，试图创建一个神奇的网站，在一片片泛红泛黄的字符中我理解了它，也不再觉得它神奇，于是我开始了文字创作，但我文笔一向很烂，手拿着笔只能在纸上点出一个个黑点却画不出一个字，于是我厌倦了它，试图将其埋入硬盘深处随着电荷泄露消散于世间。</p><p>不过我最后还是赶在硬盘丢数据前给它通上了电，因为我看到了我的网站，在 archive.org 上。有人说做博客不是为了让人看到，而是为了维护一片自己在互联网上的自留地，让自己在互联网上留痕，精神永存<del>（拜托没准三秒钟后会地球爆炸万物归于尘土呢）</del>，而我一开始的初衷是为了做一个有趣的东西，一个能留点痕迹的地方。后来发现，其实我更像在修复自己的一段记忆，而不是在做一个网站。</p><p>在这一年多的时间里，它有过不少的域名代号，啥us.kg啦、XYZ数字域名啦、各种野鸡网站的野鸡免费域名，它们的选择从不是精挑细选的，而是随手拿几个英文单词起的英文名、拿奖学金的日子注册的，虽对我而言有重要意义，但终究只是一个临时的，迫于薄薄的钱包而做的妥协。这些便宜的域名虽然不用钱但经常失效，同时大片地区被拦截，大把人把它输成COM，免费域名做得再好，终究也不如COM。</p><p>我原本在5个月前就打算换一个好的域名了，我在冥思苦想后想出了想要注册的域名：TeaHush，但COM太贵了只好退而求其次选择 .link 后缀，看着购物车里的COM，我决定过几个月再买。但……一个 fmily&#x3D;fmily⁰ 的傻逼抢注并用此域名镜像了我的网站，同时发起了对我点赞接口的攻击，显然，这次换域名的计划被搅黄了。</p><p>TeaHush，Tea翠绿的茶叶，Hush，静，大驼峰格式看着美观，读音前短后长易读，多完美的一个名字啊。</p><p>期间我曾试图想一个新的名字，奈何才疏学浅，纸上点满了黑点都画不出一个字母，算了，算了，折腾别的事情吧。但总有个执念让我再想想，终于今天找到了个戳我的名字，HcyHub，我的网名加上Hub，简单的组合就是最好的。</p><blockquote><p>迁移站点整了一下午，虽然有点累，但也真的开心，换成了COM后一下感觉网站都高级了不少</p><p>今天寒露，寒露，九月节，露气寒冷，将凝结也。明天也要该上班的上班该上学的上学了。</p></blockquote>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%8D%A2%E4%BA%86%E4%B8%AA%E6%9B%B4%E9%A1%BA%E7%9C%BC%E7%9A%84%E5%9F%9F%E5%90%8D</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%8D%A2%E4%BA%86%E4%B8%AA%E6%9B%B4%E9%A1%BA%E7%9C%BC%E7%9A%84%E5%9F%9F%E5%90%8D"/>
    <published>2025-10-08T14:33:58.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker"]]>
    </summary>
    <title>换了个更顺眼的域名</title>
    <updated>2025-10-08T15:41:34.245Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Python" scheme="https://hcyhub.com/tags/Python/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="HexoDash"><a href="#HexoDash" class="headerlink" title="HexoDash"></a>HexoDash</h1><p>我经常需要搭配各种插件来折腾 Hexo 博客，因此需要频繁地启动并预览网站，然而，一次次手动开终端输入命令终究是耗尽了我的耐心，经常手滑按错键的我实在是懒得手动敲组合命令，尽管也没多长，既然 Hexo 的常用命令（Hexo g、Hexo d、Hexo s）并不复杂，那我做一个GUI页面直接勾选运行岂不妙哉？于是<strong>HexoDash</strong>就此诞生：</p><p>一个用于Hexo博客的GUI命令助手，通过GUI页面快速完成新建文章、运行生成、部署和预览等常用操作，免去开终端输入命令的麻烦。</p><p>GitHub仓库：<a href="https://github.com/2010HCY/HexoDash">https://github.com/2010HCY/HexoDash</a></p><p>点击下载：<a href="https://github.com/2010HCY/HexoDash/releases/latest/download/HexoDash.exe"><img src="/./images/HexoDash/Download.svg"></a></p><h2 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h2><p>虽然我常用的就三个命令，但考虑到多做一点总不会有错，所以我索性把常见的所有功能都集成进去了，目前包括：</p><ol><li><strong>快速新建</strong>文章、草稿、页面</li><li><strong>快速运行</strong>组合命令，如生成页面、预览页面</li><li>支持带上<strong>尾部参数</strong>进行调试</li><li><strong>一键创建</strong> <code>blog</code> 文件夹并在文件夹下安装 Hexo</li></ol><p>可玩性极高，完全满足日常偷懒。</p><h2 id="软件页面"><a href="#软件页面" class="headerlink" title="软件页面"></a>软件页面</h2><p><img src="/./images/HexoDash/%E4%B8%BB%E9%A1%B5.png"></p><p><img src="/./images/HexoDash/%E5%B0%BE%E9%83%A8%E5%8F%82%E6%95%B0%E5%A4%A7%E5%85%A8.png"></p><h2 id="尾部参数大全"><a href="#尾部参数大全" class="headerlink" title="尾部参数大全"></a>尾部参数大全</h2><p>为了方便使用，我在软件内内置了Hexo参数大全，省的打，直接点一下尾部参数输入框后的信息按钮就会弹出尾部参数大全窗口，直接复制使用，这里再次列出以供复制</p><table><thead><tr><th><strong>Hexo 全局参数</strong></th><th></th></tr></thead><tbody><tr><td><code>--config</code></td><td>自定义配置文件的路径</td></tr><tr><td><code>--cwd</code></td><td>指定 Hexo 网站的根目录</td></tr><tr><td><code>--debug</code></td><td>启用调试模式输出日志</td></tr><tr><td><code>--draft</code></td><td>包含草稿文件生成页面</td></tr><tr><td><code>--safe</code></td><td>安全模式不加载插件脚本</td></tr><tr><td><code>--silent</code></td><td>静默运行隐藏输出信息</td></tr><tr><td><strong>New (新建)</strong></td><td></td></tr><tr><td><code>--path</code></td><td>自定义新建内容文件路径</td></tr><tr><td><code>--replace</code></td><td>强制替换现有文件</td></tr><tr><td><code>--slug</code></td><td>自定义文章 URL 部分</td></tr><tr><td><strong>Generate (生成)</strong></td><td></td></tr><tr><td><code>--deploy</code></td><td>生成完成后执行部署</td></tr><tr><td><code>--watch</code></td><td>监听并自动重新生成</td></tr><tr><td><code>--force</code></td><td>忽略文件缓存重新生成页面</td></tr><tr><td><code>--bail</code></td><td>遇到未处理异常中止</td></tr><tr><td><strong>Deploy (部署)</strong></td><td></td></tr><tr><td><code>--generate</code></td><td>部署前先生成静态文件</td></tr><tr><td><strong>Server (服务器)</strong></td><td></td></tr><tr><td><code>--port</code></td><td>指定运行端口</td></tr><tr><td><code>--host</code></td><td>指定运行IP</td></tr><tr><td><code>--static</code></td><td>禁用监听文件变化</td></tr><tr><td><code>--log</code></td><td>启用日志，输出事件信息</td></tr></tbody></table><h2 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h2><p>截止至2025年10月5日，该程序还是有不少小特性，比如可以多次点击运行按钮创建一大堆互相冲突的预览进程；比如Hexo网站很大时，终端窗口需要等到首个字符输出时才会显示；比如预览进程不会被正常杀掉，但总体来说偷懒是足够了，等我没那么懒的时候我会去修好的</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/HexoDash</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/HexoDash"/>
    <published>2025-10-05T12:11:55.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="HexoDash"><a href="#HexoDash" class="headerlink" title="HexoDash"></a>HexoDash</h1><p>我经常需要搭配各种插件来折腾 Hexo 博客，因此需要频繁地启动并预览网站，然而，一次次手动开终端输入命令终究是耗尽了我的耐心，经常手滑按错键的我实在是懒得手动敲组合命令，尽管也没多长，既然 Hexo 的常用命令（Hexo g、Hexo d、Hexo]]>
    </summary>
    <title>HexoDash</title>
    <updated>2025-10-05T12:48:12.202Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="游戏" scheme="https://hcyhub.com/categories/%E6%B8%B8%E6%88%8F/"/>
    <category term="游戏" scheme="https://hcyhub.com/tags/%E6%B8%B8%E6%88%8F/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="飞翔的波音767-911特别篇"><a href="#飞翔的波音767-911特别篇" class="headerlink" title="飞翔的波音767 - 911特别篇"></a>飞翔的波音767 - 911特别篇</h2><p><img src="/../images/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767.png"></p><p>游戏地址：<a href="https://page.hcyhub.com/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/">https://page.hcyhub.com/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/</a></p><p>跳跃，跳跃，再跳跃！挑战极限，飞跃双子塔！</p><ul><li><p>经典飞翔小鸟玩法的911特殊改版</p></li><li><p>挑战神经系统的延迟</p></li><li><p>轻松愉快的废掉键盘</p></li></ul><p>极简操作，除了跳就是跳！飞跃双子塔！</p><p>游戏内还有徽章系统：</p><p>当得分&#x3D;0时，显示沙特阿拉伯皇家空军军徽；</p><p>当得分&gt;&#x3D;10时，显示美国空军铜牌奖章；</p><p>当得分&gt;&#x3D;20时，显示美国空军银牌奖章；</p><p>当得分&gt;&#x3D;30时，显示美国空军金牌奖章；</p><p>当得分&gt;&#x3D;40时，显示美国空军铂金牌奖章；</p><p><img src="/../images/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/%E9%93%9C%E7%89%8C.svg" alt="铜牌"></p><p><img src="/../images/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/%E9%93%B6%E7%89%8C.svg" alt="银牌"></p><p><img src="/../images/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/%E9%87%91%E7%89%8C.svg" alt="金牌"></p><p><img src="/../images/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767/%E9%93%82%E9%87%91%E7%89%8C.svg" alt="铂金牌"></p><h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><p>咳咳，标题之所以叫911专场是因为我去年9月份时就有这个想法了但一直懒得弄，鸽到现在才做好。</p><p>坠毁音效的“啊——”由疯狂戴夫友情客串</p>]]>
    </content>
    <id>https://hcyhub.com/%E6%B8%B8%E6%88%8F/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767</id>
    <link href="https://hcyhub.com/%E6%B8%B8%E6%88%8F/%E9%A3%9E%E7%BF%94%E7%9A%84%E6%B3%A2%E9%9F%B3767"/>
    <published>2025-07-31T07:38:58.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="飞翔的波音767-911特别篇"><a href="#飞翔的波音767-911特别篇" class="headerlink" title="飞翔的波音767 - 911特别篇"></a>飞翔的波音767 - 911特别篇</h2><p><img]]>
    </summary>
    <title>飞翔的波音767游戏</title>
    <updated>2025-12-01T11:23:59.648Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="轩辕剑"><a href="#轩辕剑" class="headerlink" title="轩辕剑"></a>轩辕剑</h2><p>闲来无事刷SCP档案时发现了SCP-2481-3轩辕剑，轩辕剑之名流传甚广，引人好奇。然而，在我查询其确切起源与完整资料时，发现直接的史料记载寥寥无几，更多是同名的游戏系列，或散见于各类<strong>后世文学作品及类神话志怪古籍</strong>中。查询维基百科发现因其缺乏信息来源、可直接证实的史料，页面简短并无太多的实际信息。因此在开始前我得先说明，<strong>目前并无任何直接的证据能证实轩辕剑在历史上真实存在，它更多是作为传说中的一柄神剑而流传。</strong></p><p>如果不想看无聊的中间部分只想知道轩辕剑是什么可以直接跳转<a href="#%E6%80%BB%E7%BB%93">总结</a>。</p><h3 id="神话传说"><a href="#神话传说" class="headerlink" title="神话传说"></a>神话传说</h3><p>轩辕剑似乎是上古传说中黄帝时期的神兵（差不多是公元前2600多年前吧），并且轩辕剑被认为是中华十大名剑之首，亦被列为上古十大神器之一，是<strong>至高无上力量</strong>的象征，传说能够斩除妖魔。</p><h4 id="传说中的持有者"><a href="#传说中的持有者" class="headerlink" title="传说中的持有者"></a>传说中的持有者</h4><h5 id="黄帝"><a href="#黄帝" class="headerlink" title="黄帝"></a>黄帝</h5><h6 id="轩辕剑的由来传说"><a href="#轩辕剑的由来传说" class="headerlink" title="轩辕剑的由来传说"></a>轩辕剑的由来传说</h6><p>传说中，轩辕剑是黄帝在于蚩尤的大战中因使用落后的石器，难以击败凶猛的九黎族，为了封印蚩尤，听取昆仑山众仙的意见，以首山之铜为原材料，使用精铁上万斤，黄铜五千斤，以及各种珠宝化炼而成的。剑身一面刻日月星辰，一面刻山川草木；剑柄一面书农耕畜养之术，一面书四海一统之策，是传说中的<strong>神兵利刃</strong>。</p><p>轩辕剑是传说中的<strong>神兵利刃</strong>。在某些传说中，轩辕剑也被称为<strong>轩辕夏禹剑</strong>，是一把<strong>圣道之剑</strong>，后传与夏禹，传说夏禹就是靠轩辕剑斩除妖魔，顺利完成治水任务的</p><p>注：以上内容来源于神话传说，并不是史实！</p><h6 id="古籍"><a href="#古籍" class="headerlink" title="古籍"></a>古籍</h6><blockquote><p>黄帝者，号曰轩辕。能劾百神，朝而使之。弱而能言，圣而预知，知物之纪。自以为云师，有龙形。自择亡日，与群臣辞。至于卒，还葬桥山，山崩，柩空无尸，唯剑舄在焉。仙书云：黄帝采首山之铜，铸鼎于荆山之下，鼎成，有龙垂胡髯下迎帝，乃升天。群臣百僚悉持龙髯，从帝而升，攀帝弓及龙髯，拔而弓坠，群臣不得从，望帝而悲号。故后世以其处为鼎湖，名其弓为乌号焉。</p><p>神圣渊玄，邈哉帝皇。暂莅万物，冠名百王。化周六合，数通无方。假葬桥山，超升昊苍。</p><p>——《列仙传》</p></blockquote><p>黄帝，作为上古神话人物中的一员，大家耳熟能详的人物为轩辕剑第一任持有者，在列仙传中关于黄帝的记载中黄帝号轩辕，有驱使、役使神仙的无上权威，</p><blockquote><p>自择亡日，与群臣辞。至于卒，还葬桥山，山崩，柩空无尸，唯剑舄在焉。</p></blockquote><p>这句话明确指出黄帝佩有剑（“剑舄在焉”），但<strong>并未直接指明其名为“轩辕剑”</strong>。这进一步说明，<strong>“轩辕剑”作为一个专有名称的神器，其完整形象和广泛认知是后世逐渐丰富和形成的。</strong></p><p><a href="https://zh.wikisource.org/wiki/%E6%8B%BE%E9%81%BA%E8%A8%98/%E5%8D%B7%E5%8D%81#%E6%98%86%E5%90%BE%E5%B1%B1">拾遺記&#x2F;卷十-昆吾山</a>里是这么记载的：</p><blockquote><h2 id="昆吾山"><a href="#昆吾山" class="headerlink" title="昆吾山"></a>昆吾山</h2><p>昆吾山，其下多赤金，色如火。昔黃帝伐蚩尤，陳兵於此地，掘深百丈，犹未及泉，惟見火光如星。地中多丹，煉石爲銅，銅色靑而利。泉色赤。山草木皆勁利，土亦剛而精。至越王勾踐，使工人以白馬白牛祠昆吾之神，採金鋳之，以成八劍之精：一名掩日，以之指日，則光昼暗。金陰也，陰盛則陽滅。二名断水，以之划水，開即不合。三名轉魄，以之指月，蟾兔爲之倒轉。四名懸翦，飛鳥遊过觸其刃，如斬截焉。五名驚鯢，以之泛海，鯨鯢爲之深入。六曰滅魂，挾之夜行，不逢魑魅。七名卻邪，有妖魅者，見之則伏。八名眞剛，以切玉断金，如削土木矣。以應八方之氣鋳之也。其山有獸，大如兔，毛色如金，食土下之丹石，深穴地以爲窟；亦食銅鉄，膽腎皆如鉄。其雌者色白如銀。昔呉国武庫之中，兵刃鉄器，倶被食尽，而封署依然。王令檢其庫穴，獵得雙兔，一白一黃，殺之，開其腹，而有鉄膽腎，方知兵刃之鉄爲兔所食。王乃召其劍工，令鋳其膽腎以爲劍，一雌一雄，號「干將」者雄，號「鏌鋣」者雌。其劍可以切玉断犀，王深宝之，遂霸其国。後以石匝埋藏。及晉之中興，夜有紫色衝斗牛。張華使雷煥爲豐城縣令，掘而得之。華與煥各宝其一。拭以華陰之土，光耀射人。後華遇害，失劍所在。煥子佩其一劍，过延平津，劍鳴飛入水。及入水尋之，但見雙龍纏屈於潭下，目光如電，遂不敢前取矣。</p></blockquote><p>这段话大意是<strong>昆吾山</strong>山下盛产<strong>红色的铜矿（赤金）</strong>，颜色像火一样。</p><p>从前<strong>黄帝</strong>攻打<strong>蚩尤</strong>的时候，曾经在这里布阵，他们向下挖掘了上百丈深，却<strong>仍然没有挖到泉水</strong>，只看到<strong>火光像星星一样在地下闪烁</strong>。地下有许多<strong>丹砂</strong>，（人们）用丹砂炼石，能够炼出<strong>青色且锋利的铜</strong>。那里的<strong>泉水是红色的</strong>。山上的<strong>草木都非常坚韧锋利</strong>，泥土也<strong>坚硬而精纯</strong>。</p><p>文献中记载的昆吾山可能就是神话中首山的原型，炼制轩辕剑的地方，里面提到的铜则是轩辕剑的原材料，神话故事可能是以此创作的，但其实《拾遗记》本身就是一部汇集古代异闻、志怪传说的著作……</p><p>因此，与其说轩辕剑是“人们对于力量的崇拜而创造的神话产物”，不如说<strong>《拾遗记》</strong>是轩辕剑神话形象逐渐丰满的重要推手之一。</p><h5 id="后续持有者"><a href="#后续持有者" class="headerlink" title="后续持有者"></a>后续持有者</h5><p>关于轩辕剑这柄剑的记载很少，也就一些小说一样的古籍有提到啥黄帝铸造传于夏禹，可信度低，纯粹神话</p><h3 id="其他来源"><a href="#其他来源" class="headerlink" title="其他来源"></a>其他来源</h3><p>综上所述，轩辕剑作为一个特定名称的神器，并未出现在确凿的史实中。提及它的古籍<strong>数量稀少</strong>，多为<strong>神话志怪小说或后人的演绎之作</strong>，其内容也相当简单，难以构成完整的设定体系。因此无法从史实层面证实轩辕剑的存在。轩辕剑的形象内涵更多是在<strong>历代的文学创作与民间传说</strong>中不断丰满的，而非基于可考证的历史事件。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>关于轩辕剑的记载极为稀少，并且大多都是带有较强神话色彩的，可信度低，总结下来就是：</p><ol><li><strong>没有任何证据证明轩辕剑存在，轩辕剑更多是作为</strong>力量和神权的象征而<strong>存在于传说中</strong></li><li>神话传说中轩辕剑为黄帝所有，黄帝用其击败击败敌人创造神话</li><li>轩辕剑常被尊为为十大名剑之首，十大名器之一</li></ol><p>轩辕剑更多是作为神器的象征，是古人对于力量的崇拜而创造的一柄并不存在的剑，在历代文学作品中轩辕剑被赋予了斩妖除魔、无穷力量的设定，在一些神话中作为斩除邪祟的武器，并且在之后的历史长河中作为强者的象征反复出场，现代有以轩辕剑为名的游戏，武侠小说中也以轩辕剑为终极武器，强者横扫天下的利器。</p><p>轩辕剑大概率是不存在的，但这也不妨碍它作为一个象征，手握最强神器，谁与争锋？</p><hr><h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><h4 id="十大名剑"><a href="#十大名剑" class="headerlink" title="十大名剑"></a>十大名剑</h4><blockquote><p>排名从上至下，此列表主要流行于现代仙侠文学和游戏设定中</p></blockquote><p>圣道之剑——轩辕剑</p><p>仁道之剑——湛泸</p><p>帝道之剑——赤霄</p><p>威道之剑——泰阿</p><p>高洁之剑——龙渊</p><p>挚情之剑——干将、莫邪</p><p>勇绝之剑——鱼肠</p><p>尊贵之剑——纯钧</p><p>高雅之剑——承影</p><h4 id="上古十大神器"><a href="#上古十大神器" class="headerlink" title="上古十大神器"></a>上古十大神器</h4><blockquote><p>排名不分先后，纯纯神话数值怪</p></blockquote><p>东皇钟：天界之门</p><p>轩辕剑：最强力量</p><p>盘古斧：穿梭太虚</p><p>炼妖壶：炼化万物</p><p>昊天塔：吸星换月</p><p>伏羲琴：操纵心灵</p><p>神农鼎：熬炼仙药</p><p>崆峒印：不老源泉</p><p>昆仑镜：时空穿梭</p><p>女娲石：复活再生</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E8%BD%A9%E8%BE%95%E5%89%91</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E8%BD%A9%E8%BE%95%E5%89%91"/>
    <published>2025-07-12T07:02:24.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="轩辕剑"><a href="#轩辕剑" class="headerlink"]]>
    </summary>
    <title>轩辕剑</title>
    <updated>2025-07-12T07:04:42.776Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="3D打印" scheme="https://hcyhub.com/tags/3D%E6%89%93%E5%8D%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><img src="./../../images/祥云福禄葫芦/葫芦.jpg" style="zoom:80%;" /><blockquote><p>看看！新鲜出炉的小葫芦</p></blockquote><p>前阵子闲着没事，就想着打印个小葫芦玩玩。其实我一直挺喜欢葫芦的造型，圆乎乎的，对称，反正就是莫名喜欢，看着就挺顺眼。不过上次打印的时候没注意尺寸，结果出来一个mini of mini版，还没我拇指大，不过细节很到位，就是太小了不便欣赏。</p><img src="./../../images/祥云福禄葫芦/对比.jpg" style="zoom:80%;" /><blockquote><p>瞧瞧，这大小差距，不过小小的也挺可爱的，至少细节都很到位</p></blockquote><p>这次打印就修改好了，直接把长宽高都放大3倍，体积放大了足足27倍。打印好后大小刚刚好，握在手里别在腰间都刚刚好 ，打磨后手感圆润，分量也挺足的，72.4克，差不多一个鸡蛋重。表面的花纹清晰可见，细节很到位，带出去耍肯定好玩。</p><p>放在桌子上，和之前的小葫芦们摆一起还挺协调。偶尔转头看一眼，心情也能好点。其实这类小东西没啥实际用处，但就是觉得挺有意思的，装饰也挺好看的，下面是我的小葫芦们，一共有6个，还差一个集齐7个，七个葫芦娃~</p><img src="./../../images/祥云福禄葫芦/我的葫芦们.jpg" style="zoom:80%;" /><p>这个葫芦好看吧，如果觉得好看可以试试自己打印，STL模型文件我放下面了，可以自行下载</p><p><a href="./../../images/祥云福禄葫芦/祥云福禄葫芦.stl" download style="display:block;text-align:center;">祥云福禄葫芦.stl</a><img src="./../../images/祥云福禄葫芦/葫芦.png" style="zoom:67%;" /></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%A5%A5%E4%BA%91%E7%A6%8F%E7%A6%84%E8%91%AB%E8%8A%A6</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%A5%A5%E4%BA%91%E7%A6%8F%E7%A6%84%E8%91%AB%E8%8A%A6"/>
    <published>2025-07-05T14:47:00.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><img src="./../../images/祥云福禄葫芦/葫芦.jpg" style="zoom:80%;" />

<blockquote>
<p>看看！新鲜出炉的小葫芦</p>
</blockquote>
<p>前阵子闲着没事，就想着打印个小葫芦玩玩。其实我一直挺喜欢葫芦的造型，圆乎乎的，对称，反正就是莫名喜欢，看着就挺顺眼。不过上次打印的时候没注意尺寸，结果出来一个mini of]]>
    </summary>
    <title>祥云福禄葫芦</title>
    <updated>2025-07-05T14:55:42.685Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>物理安全密钥，是作为验证身份提高安全性的小玩意，当我第一次发现谷歌账号可以绑定安全密钥时我心里就痒痒的，物理安全密钥小巧的外观也很吸引人，再加上我很喜欢折腾各种各样的小东西，所以我一直很想要一个物理安全密钥，但苦于Yubikey贵得要死，而且没有开源相关内容内部是个黑箱，所以我一直没打算买个安全密钥。（要是把Yubikey价格后面的美元去掉我可能还会考虑买它，老外的东西就是这样，去掉货币单位价格刚好）</p><p>正好这阵子刷论坛时看到有人用RP2350制作物理密钥，发现挺简单的，再加上我自己本来就想要一个安全密钥，遂花32大洋买了个RP2350-One制作安全密钥，毕竟，能用几十块钱体验一把“小众产品”，何乐而不为？</p><p>不过鉴于制作教程网上很多了，大家都是重复的文章重复的内容没啥意思，所以本文的着重点是细节，以及后续使用。</p><blockquote><p><strong>制作教程来自<a href="https://linux.do/t/topic/580783" target="noindex">此帖子</a>，我仅作细节补充</strong></p></blockquote><h2 id="制作"><a href="#制作" class="headerlink" title="制作"></a>制作</h2><p>制作类教程网上很多，这里就简单重复一遍<a href="https://linux.do/t/topic/580783" target="noindex">此帖子</a>，着重说明重点</p><h3 id="买硬件"><a href="#买硬件" class="headerlink" title="买硬件"></a>买硬件</h3><p>Pico Keys 支持 RP2040 RP2350以及ESP32，但通常是使用树莓派芯片烧录。</p><p>芯片推荐选择RP2350，因为RP2040没有安全启动，也没有内置安全硬件，理论上可以直接读取出密钥；而RP2350则添加了安全启动，即从此只能运行此固件。另外RP2350还可以给固件签名，然后让此芯片只能运行签名过的固件，不能运行其他未签名存在安全隐患固件，以此提高安全性。（缺点就是麻烦，还有就是容易变砖）</p><p>当然ESP32系列也能做安全密钥，直接使用线刷跳过配置步骤，不过需要注意的是ESP32有爆出来过漏洞可以Flash直读密钥，这些要注意。</p><p>我选择的是RP2350-One做安全密钥，价格高达32大洋。</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/RP2350-One.jpg" style="zoom:80%;" /><h3 id="烧录、配置"><a href="#烧录、配置" class="headerlink" title="烧录、配置"></a>烧录、配置</h3><ol><li>下载固件</li></ol><p>首先你要到<a href="https://www.picokeys.com/getting-started/#wp-block-themeisle-blocks-advanced-heading-13146b4b">Pico Keys官网</a>下载固件，找到下载，Firmware固件类型选择Pico Fido，供应商和芯片型号根据实际填写，我选的是我买的微雪RP2350-One，然后点击Download下载uf2固件</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/下载固件.png" style="zoom:80%;" /><ol start="2"><li>烧录</li></ol><p>按住Boot键然后把开发板插入电脑，此时它会被处理成一个U盘一样的设备，在文件管理器里出现过U盘图标打开，然后把固件拖进去，复制好后固件会自动加载，文件管理器窗口将会被关闭。</p><p>刷好后开发板上的灯应该会长亮，时不时灭一下，如果没有也不用紧张。</p><ol start="3"><li>配置</li></ol><p>前往 <a href="https://www.picokeys.com/pico-commissioner/">Pico Commissioner - Pico Keys</a>进行调试需要设置几个值</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/调试.png" alt="调试" style="zoom:80%;" /><ul><li>设置 Vendor 为 YubiKey 4&#x2F;5，这需要根据你的设备更改</li><li>VID:PID 参考这篇文章 <a href="https://support.yubico.com/hc/en-us/articles/360016614920-YubiKey-USB-ID-values">YubiKey USB ID 值</a> ，我们需要让电脑知道此设备是一个多协议YubiKey 5安全密钥，所以要将USB Vendor ID设置为YubiKey 的 USB ID 值，设置为 <code>1050:0407</code>（YubiKey 5 NFC (OTP+FIDO+CCID)）</li><li>Product Name 设置为 <code>yubico yubikey</code>，这样才能使用YubiKey软件管理</li><li>LED brightness 是LED亮度设置，一般来说设置低一点避免瞎眼，如果有外壳可以考虑设置高一点，我是设置为 <code>1</code></li><li>Options 开启 <code>LED dimmable</code> <code>Secure Boot</code> <code>Secure Lock</code> 这三个选项，分别是LED控制、安全启动和安全锁，但开启Secure Boot前一定要考虑清楚，一旦开启，这个芯片从此以后只能使用 Pico Keys 官方签名过的固件，如果不希望从此只能运行官方固件但希望开启安全锁可以使用 <a href="https://github.com/polhenarejos/pico-fido/issues/106">自签名</a> ）</li></ul><p>然后点击Commission via WebUSB进行调试，设备选择pico keys。调试好后可以点击Commission via WebAuthn按钮进行测试，第一次使用Windows会让你设置PIN，也就是密码，之后使用此密钥、查看密钥信息都需要输入此PIN。</p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>好了，密钥制作完成，以上部分都是来自<a href="https://linux.do/t/topic/580783" target="noindex">此帖子</a>的，我仅作细节补充</p><p>此物理密钥使用起来很舒服，不用费劲巴拉的找手机获取2FA验证码，只需要插入物理密钥轻轻一按即可，小巧玲珑的可以很方便的携带（别弄丢了）。</p><p>不过为了保险起见建议做两个密钥，互相为备份不用担心丢了全抓瞎</p><p>Pico Keys兼容YubiKey，所以可以很方便的在 <a href="https://www.yubico.com/products/yubico-authenticator/">Yubico Authenticator</a>，<a href="https://www.yubico.com/support/download/yubikey-manager/"> YubiKey Manager</a>，<a href="https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#windows-installation">ykman</a>软件里管理密钥，我下载的是<a href="https://www.yubico.com/products/yubico-authenticator/">Yubico Authenticator</a>，打开<a href="https://www.yubico.com/products/yubico-authenticator/">Yubico Authenticator</a>可以看到页面很简洁，<del>完全长在了我的审美上</del>，一共有账户、通行密钥、槽位三大功能，接下来依次说明。</p><h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><p>注意，密钥的 S&#x2F;N （序列号）是机密信息，最好不要在网上公开它。</p><p>密钥的使用方法是在需要按按键时按下Boot键，不要在插入时按，那是刷固件的。</p><p>另外Boot键没有长按功能，想要触发长按的话请连续按两下。</p><h3 id="账户"><a href="#账户" class="headerlink" title="账户"></a>账户</h3><blockquote><p> 此功能是生成OATH验证码（基于时间的动态2FA）或HOTP验证码（基于次数的动态2FA）</p></blockquote><p>此功能是生成两步验证代码的，功能和谷歌的<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&pcampaignid=web_share">Google 身份验证器</a>一样，不同的是两步验证密钥是存放在刚刚制作的物理安全密钥里，不会存在硬盘里。</p><p>此为基于时间的2FA动态验证码（OATH）</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/账户.png" style="zoom:80%;" /><p>添加两步验证代码也很简单，点击右上角的添加账户即可，可以手动输入密钥，也可扫描二维码，为了安全性也可以设置下密码。</p><h3 id="通行密钥"><a href="#通行密钥" class="headerlink" title="通行密钥"></a>通行密钥</h3><blockquote><p>查看网站创建的通行密钥</p></blockquote><p>通行密钥是你在网站上创建的，比如GitHub的通行密钥，进入此区域需要输入PIN，你可以在里面查看自己密钥凭证。注意哈，一定不要透露这里面的内容。</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/通行密钥.png" style="zoom:80%;" /><h3 id="槽位"><a href="#槽位" class="headerlink" title="槽位"></a>槽位</h3><blockquote><p>设置安全密钥的按键功能</p></blockquote><p>最有意思的功能无疑是这个槽位设置了，它是设置按下按钮时触发的操作的，比如可以按下按钮自动输入一次性2FA密码。</p><p>它可以做到：</p><ol><li>按下按键自动输入静态密码登录电脑</li><li>按下按键自动生成并输入基于次数的一次性2FA代码</li><li>自动应答验证…</li></ol><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/槽位.png" style="zoom:80%;" /><p>这里拿自动输入密码登录电脑举例</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/静态密码.png" style="zoom:80%;" /><p>选择短按或长按，设置静态密码，键盘选择US（英文键盘），然后输入你的电脑密码，这里可以勾选<code>附加回车</code>，这样会自动回车。</p><p>效果：</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/效果.gif" style="zoom:80%;" /><p>按下按键会模拟键盘输入指定密码，并回车确认。</p><p>此密码数据完全存放于物理密钥中，不依赖任何软件，输入密码的过程是物理密钥模仿键盘输入的，不需要安装任何软件即可使用。（必须连接USB才能输入）</p><p>有两个槽位，一个是短按，另一个是长按，注意，长按Boot键没有效果的，自制的物理密钥要连续按两下。</p><h3 id="自定义图标"><a href="#自定义图标" class="headerlink" title="自定义图标"></a>自定义图标</h3><blockquote><p>自定义Yubico Authenticator里显示的图标，使其更易于管理</p></blockquote><p>可以看到我的页面中各个服务都有它们的图标，看着一眼就知道是什么。</p><img src="./../../images/30元制作一个超好玩的物理安全密钥Pico Keys/账户.png" style="zoom:80%;" /><p>而Yubico Authenticator默认是没有图标只有字母的，需要手动自定义图标包，你可以选择去<a href="https://github.com/beemdevelopment/Aegis/blob/master/docs/iconpacks.md">查看Aegis 图标包格式</a>然后一个个自定义图标，也可以选择使用<a href="https://aegis-icons.github.io/">Aegis预制图标包</a></p><h2 id="完毕"><a href="#完毕" class="headerlink" title="完毕"></a>完毕</h2><p>好了，折腾完毕，现在可以愉快的使用此物理密钥的各种功能了！按一下解锁电脑，按一下登录账号，真好玩不是么？</p><p>不过要记住不要把此密钥放在潮湿的地方，不然容易生锈损坏密钥，也不要傻乎乎的不备份把密钥丢了，虽然用密钥解锁电脑很帅，但等密钥丢了找密钥的样子也很狼狈</p><p>另外密钥的OATH、HOTP验证码功能真好用</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/32%E5%85%83%E5%88%B6%E4%BD%9C%E4%B8%80%E4%B8%AA%E8%B6%85%E5%A5%BD%E7%8E%A9%E7%9A%84%E7%89%A9%E7%90%86%E5%AE%89%E5%85%A8%E5%AF%86%E9%92%A5Pico%20Keys</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/32%E5%85%83%E5%88%B6%E4%BD%9C%E4%B8%80%E4%B8%AA%E8%B6%85%E5%A5%BD%E7%8E%A9%E7%9A%84%E7%89%A9%E7%90%86%E5%AE%89%E5%85%A8%E5%AF%86%E9%92%A5Pico%20Keys"/>
    <published>2025-06-30T08:21:29.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink"]]>
    </summary>
    <title>32元制作一个超好玩的物理安全密钥Pico Keys</title>
    <updated>2025-12-01T11:26:15.841Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前情摘要"><a href="#前情摘要" class="headerlink" title="前情摘要"></a>前情摘要</h2><p>[从存储到分发：使用Backblaze B2私有桶和Cloudflare Workers公开分发原声音轨](从存储到分发：使用Backblaze B2私有桶和Cloudflare Workers公开分发原声音轨)</p><p>上一次更新我将我的音乐存储到Backblaze B2私有桶里，使用Workers公开访问，但引申出了个问题，那就是音乐加载依赖于Workers，消耗Workers额度并且API地址容易被刷，安全性稳定性不佳。</p><p>且由于文件是需要从Backblaze那拉取，经过Cloudflare绕一圈，所以整体延迟偏高，速度也很慢，在应对多用户并发性能极烂，因此我开始寻找一个替代方案，一番搜索后，锁定了CloudflarePages</p><h2 id="CloudflarePages的优势"><a href="#CloudflarePages的优势" class="headerlink" title="CloudflarePages的优势"></a>CloudflarePages的优势</h2><h3 id="存储空间"><a href="#存储空间" class="headerlink" title="存储空间"></a>存储空间</h3><p>首先得明确一下Pages的限制，之前我一直以为单个Pages最多只能存放25MB文件，直到我看到了这个帖子：<a href="https://linux.do/t/topic/723578?u=ethaniel">【再来薅一把 Cloudflare】教你怎么把Cloudflare pages变成不限速&amp;不限文件大小的网盘用</a>（非公开帖子）后才猛然发现，25MB是单个文件的大小限制，CloudflarePages只做以下限制</p><table><thead><tr><th>类型</th><th>限制</th><th>说明</th></tr></thead><tbody><tr><td>文件数量</td><td>20000个</td><td>两万个，小网站用起来绰绰有余了，中大型可能就不够用了</td></tr><tr><td>单文件大小</td><td>25MB</td><td>Cloudflare可能是有考虑到图片文件，因此设置25MB，对于我而言很宽松了</td></tr><tr><td>并发构建</td><td>1</td><td>一个账户一次只能构建一个Pages项目，没啥影响</td></tr></tbody></table><p>这意味着什么？意味着只要我的良心不会痛，理论上我可以用Pages存放2万个25MB的文件，足足可以存放500000MB（488.28125GB）！当然我不会那么缺德去滥用，我只存点音乐。</p><h3 id="其他优势"><a href="#其他优势" class="headerlink" title="其他优势"></a>其他优势</h3><p>存储容量完美满足我的需求，不仅如此，Pages还有其他的优点：</p><ol><li>CDN，Pages原生支持Cloudflare的CDN，并且能通过_headers文件自定义缓存标头</li><li>TTFB延迟，由于Pages不用绕来绕去的请求文件，文件是直接请求Cloudflare服务器的，所以TTFB延迟极低</li><li>并发性能优，纯静态文件托管，比Workers好很多</li></ol><h2 id="迁移"><a href="#迁移" class="headerlink" title="迁移"></a>迁移</h2><p>迁移站点很简单，Cloudflare提供了wrangler命令行，我只配置了下wrangler.toml和_headers然后就可以直接用</p><pre class="line-numbers language-none"><code class="language-none">wrangler pages deploy<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>一键上传部署了。整个过程就上传时费了点时间，其他的一分钟搞定。</p><h2 id="性能"><a href="#性能" class="headerlink" title="性能"></a>性能</h2><p>这个是我使用Workers+B2部署的性能效果：</p><img src="./../../images/优化了下我的音乐空间网站性能/Workers+B2.png" style="zoom:80%;" /><p>可以看到下载完这个文件足足花了18秒，而这是Pages的表现：</p><img src="./../../images/优化了下我的音乐空间网站性能/Pages.png" style="zoom:80%;" /><p>可以看到，速度极快，2秒搞定</p><p>这是它们的性能对比</p><table><thead><tr><th>指标</th><th>Cloudflare Pages</th><th>Workers + B2</th><th>评价</th></tr></thead><tbody><tr><td>TTFB</td><td>723.19 ms</td><td>870.83 ms</td><td>TTFB更低，若使用默认分配的.pages.dev域名会更低</td></tr><tr><td>下载时间</td><td>563.56 ms</td><td>19.52 s</td><td>Pages完胜，慢悠悠的Workers加载很慢</td></tr><tr><td>总共用时</td><td>1.29 s</td><td>20.40 s</td><td>Pages完胜</td></tr></tbody></table><p>上述测试数据为海外节点测速，若使用默认分配的.pages.dev域名TTFB会更低，因为分配的是更优质的IP，缺点是大陆可能被屏蔽。（若你的自定义域分配到的IP质量好的话就没有这回事，我是因为我的域名分配到了垃圾IP）</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%BC%98%E5%8C%96%E4%BA%86%E4%B8%8B%E6%88%91%E7%9A%84%E9%9F%B3%E4%B9%90%E7%A9%BA%E9%97%B4%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%BC%98%E5%8C%96%E4%BA%86%E4%B8%8B%E6%88%91%E7%9A%84%E9%9F%B3%E4%B9%90%E7%A9%BA%E9%97%B4%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD"/>
    <published>2025-06-26T07:19:21.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前情摘要"><a href="#前情摘要" class="headerlink" title="前情摘要"></a>前情摘要</h2><p>[从存储到分发：使用Backblaze B2私有桶和Cloudflare Workers公开分发原声音轨](从存储到分发：使用Backblaze B2私有桶和Cloudflare Workers公开分发原声音轨)</p>
<p>上一次更新我将我的音乐存储到Backblaze]]>
    </summary>
    <title>优化了下我的音乐空间网站性能</title>
    <updated>2025-06-26T07:19:24.257Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>玩Flash游戏时难度太高打不过去？希望改存档一键拿神装横扫天下？你需要这个FlashSol文件编辑器！</p><h2 id="工具页面"><a href="#工具页面" class="headerlink" title="工具页面"></a>工具页面</h2><p>页面好看操作简单明了，界面如下图：</p><img src="./../../images/FlashSol编辑器/层级嵌套显示.png" style="zoom:67%;" /><img src="./../../images/FlashSol编辑器/平铺显示.png" style="zoom:67%;" /><img src="./../../images/FlashSol编辑器/修改变量.png" style="zoom:67%;" /><h2 id="功能说明"><a href="#功能说明" class="headerlink" title="功能说明"></a>功能说明</h2><h3 id="视图"><a href="#视图" class="headerlink" title="视图"></a>视图</h3><p>本工具有两种视图，分别是层级嵌套（树状模式）和平铺显示（大表格模式）他们的特点是：</p><ol><li>层级嵌套（树状模式）：最直观体现SOL多层结构，像操作文件管理器那样一个数组是一个“文件夹”，最直观、最好体现原有结构、层级</li><li>平铺显示（大表格模式）：把多层嵌套的数据拍平，直接在一页里滚动查找有关数据，适合喜欢这样的人<del>我个人喜欢层级嵌套</del></li></ol><h3 id="变量类型"><a href="#变量类型" class="headerlink" title="变量类型"></a>变量类型</h3><p>在本工具中，你可以创建、编辑以下变量类型：</p><h4 id="1-数值-Number"><a href="#1-数值-Number" class="headerlink" title="1. 数值 (Number)"></a>1. 数值 (Number)</h4><p>在 Flash 引擎中，数值通常表现为双精度浮点数（IEEE-754 Double Precision）。但在 AMF3 编码中，如果是整数，会优先被优化为 29 位带符号整数（U29）进行存储。</p><p><strong>取值范围</strong>：</p><p>**整数 (AMF3 优化范围)**：$-2^{28}$ 至 $2^{28} - 1$（即 <code>-268,435,456</code> 至 <code>268,435,455</code>）。在此范围内的整数体积占用最小。</p><p>**浮点数 (双精度)**：约为 $\pm 5.0 \times 10^{-324}$ 至 $\pm 1.79 \times 10^{308}$。</p><p><strong>修改建议</strong>：虽然Sol文件本身支持储存极大的数值，但是要考虑游戏本身是否能够处理如此大的数值不报错、溢出变负，所以建议不要贪多。</p><h4 id="2-字符串-String"><a href="#2-字符串-String" class="headerlink" title="2. 字符串 (String)"></a>2. 字符串 (String)</h4><p>用 UTF-8 编码的文本字符流。</p><p><strong>取值范围</strong>：</p><p><strong>字符长度</strong>：理论上限为 $2^{28}-1$ 个字节（约 268MB）。</p><p><strong>实际限制</strong>：受限于 Flash 运行时的本地存储配额（默认通常为 100KB，超出需用户授权，上限一般不超过几MB）。</p><p><strong>修改建议</strong>：字符串这个一般是用于修改玩家名字、装备 ID、哈希校验码等。不支持直接换行，只能是单行字符串。建议参考变量名含义修改，比如看到<code>Player Name</code>是玩家名的意思，若值也和你的名字对上了就说明对了</p><h4 id="3-布尔值-Boolean"><a href="#3-布尔值-Boolean" class="headerlink" title="3. 布尔值 (Boolean)"></a>3. 布尔值 (Boolean)</h4><p>1 字节大小的逻辑开关。</p><p><strong>取值范围</strong>：有且只有两个值：<code>true</code>（真 &#x2F; 开启 &#x2F; 激活）或 <code>false</code>（假 &#x2F; 关闭 &#x2F; 未激活）。</p><p><strong>修改建议</strong>：常用于储存是否解锁该武器、是否通过本关卡等等。建议参考变量名含义修改，比如<code>weapons</code>武器分类下的AK47 False，大概率是AK47这个武器解锁状态为否。</p><h4 id="4-XML-数据-XML"><a href="#4-XML-数据-XML" class="headerlink" title="4. XML 数据 (XML)"></a>4. XML 数据 (XML)</h4><p>原生 XML 格式序列化存储的文档结构。</p><p><strong>格式规范</strong>：必须是符合标准的 XML 语法规范（即必须有闭合标签，如 <code>&lt;root&gt;&lt;item id=&quot;1&quot;/&gt;&lt;/root&gt;</code>）。</p><p><strong>修改建议</strong>：部分游戏会把一整套关卡配置、卡牌属性或者背包数据塞进一个 XML 里存储。修改时<strong>千万千万要注意标签闭合与转义字符</strong>，语法错误大概率会导致游戏直接无法读取该变量然后报错，在保存修改前可以丢VS Code之类代码编辑器看看语法是否正确。</p><h4 id="5-数组-Array"><a href="#5-数组-Array" class="headerlink" title="5. 数组 (Array)"></a>5. 数组 (Array)</h4><p>可以是带索引的严格数组（Strict Array）或者键值对形式的 ECMA 数组（Associative Array &#x2F; Object），在本工具中体现为多个变量的文件夹。</p><ul><li><strong>取值范围</strong>：可容纳 $0$ 到 $2^{32} - 1$ 个元素。数组中的每一个子元素，都可以是上述的任意一种（包括接下来的二进制数据）数据类型。</li><li><strong>修改建议</strong>：在本工具中，数组的值会显示为 <code>[包含 X 个项目]</code>，数组本身没有值，只可修改其名字、类型或删除。一般修改是需要双击进入子级去修改具体的数值或对象。</li></ul><h4 id="6-二进制数据-ByteArray-Binary-Data"><a href="#6-二进制数据-ByteArray-Binary-Data" class="headerlink" title="6. 二进制数据 (ByteArray &#x2F; Binary Data)"></a>6. 二进制数据 (ByteArray &#x2F; Binary Data)</h4><p>AMF3 引入的 <code>ByteArray</code>（字节数组），用于存储原始的二进制数据流。</p><p><strong>取值范围</strong>：任意字节序列（Byte sequence），长度受 Flash 内存和存储配额限制。</p><p><strong>修改建议</strong>：本工具中显示为二进制数据的16进制转储，可尝试转换成字符串看看是否是简单二进制字符串。</p><h3 id="搜索、筛选"><a href="#搜索、筛选" class="headerlink" title="搜索、筛选"></a>搜索、筛选</h3><p>顾名思义，你可以按条件搜搜内容、筛选显示的内容。</p><p>搜索可供选择的是搜索匹配的对象、类型，筛选可按照类型过滤显示内容。</p><img src="./../../images/FlashSol编辑器/搜索.png" style="zoom:67%;" /><img src="./../../images/FlashSol编辑器/筛选.png" style="zoom:67%;" /><h2 id="下载、体验地址"><a href="#下载、体验地址" class="headerlink" title="下载、体验地址"></a>下载、体验地址</h2><p>你可以在<a href="https://page.hcyhub.com/%E5%B0%8F%E5%B7%A5%E5%85%B7/FlashSol%E7%BC%96%E8%BE%91%E5%99%A8/">FlashSol编辑器网页版</a>中快速在线编辑Sol文件，或者下载<a href="https://flash.hcyhub.com/SolEditor.exe">桌面应用</a>以供离线修改</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/FlashSol%E7%BC%96%E8%BE%91%E5%99%A8</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/FlashSol%E7%BC%96%E8%BE%91%E5%99%A8"/>
    <published>2025-06-14T02:58:50.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>玩Flash游戏时难度太高打不过去？希望改存档一键拿神装横扫天下？你需要这个FlashSol文件编辑器！</p>
<h2 id="工具页面"><a href="#工具页面" class="headerlink" title="工具页面"></a>工具页面</h2><p>页面好看操作简单明了，界面如下图：</p>
<img src="./../../images/FlashSol编辑器/层级嵌套显示.png" style="zoom:67%;"]]>
    </summary>
    <title>FlashSol编辑器</title>
    <updated>2026-06-14T03:08:29.441Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="博客发展历程" scheme="https://hcyhub.com/tags/%E5%8D%9A%E5%AE%A2%E5%8F%91%E5%B1%95%E5%8E%86%E7%A8%8B/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="Aipic更新"><a href="#Aipic更新" class="headerlink" title="Aipic更新"></a>Aipic更新</h2><p><strong>v1.1.0 (2025.5.30)</strong></p><p>添加了负面提示词、质量遵循度参数支持，AI翻译提示词功能仍遥遥无期</p><p>现在此项目有了更为完善的参数设置，基本完善，不过，AI翻译提示词的功能还在遥远的未来，暂时只能搁置。</p><p>现在Aipic已经比较完善了，于是我便有了新的折腾目标，研究提示词生成好看的图片。</p><h2 id="关于生图效果"><a href="#关于生图效果" class="headerlink" title="关于生图效果"></a>关于生图效果</h2><p>因为Cloudflare提供的模型是专门用来生图的模型，并不是类似GPT 4o那样的多模态模型，所以生图效果和提示词关系很大，多模态模型因为本身就有一定的语言能力，所以可以使用很简单的语言生成效果很好的图片。</p><p>比如“一只小猫”，多模态模型可以生成一只在草坪上的猫猫，但stable-diffusion-xl-base-1.0却会生成一只很有赛博朋克风格的猫（低情商：狗屁不通的电子垃圾；高情商：赛博朋克风格🤣）。</p><p>多模态的提示词和专门生图的提示词有点差别，多模态模型你可以描述很抽象的东西、形态，但专门生图的模型就不能很好的理解一些描述（当然，更大更好的生图模型此方面缺陷不明显，<del>说人话就是得加钱</del>），比如它们不能理解过于抽象情绪化的描述，比如“高兴的场景”，这样的提示词大概率会出现一个咧着嘴笑的怪物的…<del>（加钱换更好的模型可以解决）</del></p><p>当然，多模态也是有一点缺陷的，就是画面和同等级的专业生图模型比起来会有些逊色，比如这是使用博客首页图片同款提示词找GPT 4o生成的效果：</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/ChatGPT生成的.png" style="zoom:50%;" /><p>生成图片风格整体和其他专业生图模型效果差不多，但整体效果一般般，画面过于空旷了，细节也不大好。</p><p>所以Cloudflare的模型虽然没有多聪明先进，但其实在一些特殊的它们擅长的场景效果还是挺不错的，并非一定要是其他多模态才是最好的<del>（我还是那句话，得加钱）</del>，好用的工具是在会用的人手里的才好用，我决定让stable-diffusion-xl-base-1.0好好发挥，做点有意义的事。<del>（当然我不会想要说让）</del></p><h2 id="博客更新"><a href="#博客更新" class="headerlink" title="博客更新"></a>博客更新</h2><p>现在琢磨透模型的脾气后，我也忍不住想要找点啥事做，有好东西首先肯定是先造福自己啦，正好博客的首页图老早就想要换了，所以我便第一个拿自己的博客开刀。</p><p>我决定生成张更符合网站气质的首页图，先来回顾一下之前使用的老图片吧：<br><img src="/medias/banner/0.webp"></p><p>这张偏红的图片，其实用久了让人感到压抑，而且和我一直追求的页面风格“<strong>美观与易用兼备</strong>，<strong>内容与功能分明</strong>”（来自GPT 4.1的认可）并不相符，所以我动手调整，通过Aipic自己生成张更完美的首页图片。</p><p>第一版成品出炉：</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/1.jpg" style="zoom:80%;" /><p>嗯~好看，整体气质倒是美观许多，但感觉还是差了点什么，这版的山太突出了，而且颜色也没有我想象中的那么治愈，于是继续微调，第二版来了：</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/1.png" style="zoom:80%;" /><p>Nice！第二版就好看多了，色调温和自然，毛绒绒的草丛看着就格外治愈，远处的山也恰到好处的若隐若现隐入背景，细节把控得刚刚好，舒服~</p><p>好图片配好首页，有了好图片就是更换首页啦，我专门生成了一张图片用作首页图，这是更换后的效果：</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/首页.png" style="zoom:80%;" /><p>看着非常舒服，视觉与心灵上的治愈，页面整体的淡绿配色很让人安心，同时也更符合我的风格。</p><p>页首按钮我也顺便改了下，一直觉得这红彤彤的按钮有点突兀，略带压力感，看着就不好看令人有点烦躁，这是改版前：</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/页首按钮改版前.png" style="zoom:80%;" /><p>而新版和整体配色风格呼应，看着真是舒服多了，这是改版后的：</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/页首按钮改版后.png" style="zoom:80%;" /><p>颜色更加好看贴合我的配色主题，就相当舒服~</p><p>有了免费的生图，页面焕然一新（就是提示词不好写，多模态模型提示词其实更好写一点），欢迎留言你的想做的图片样式，或许我可以做出来？</p><p>最后附上一组用第二版提示词生成的图片，未来我还会尝试更多不同风格的（啥？电子邮件签名？这个得再等等…）</p><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/2.png" style="zoom:80%;" /><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/3.png" style="zoom:80%;" /><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/4.png" style="zoom:80%;" /><img src="./../../images/从昨天的Aipic项目继续，分享几张我生成的图片/5.png" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E4%BB%8E%E6%98%A8%E5%A4%A9%E7%9A%84Aipic%E9%A1%B9%E7%9B%AE%E7%BB%A7%E7%BB%AD%EF%BC%8C%E5%88%86%E4%BA%AB%E5%87%A0%E5%BC%A0%E6%88%91%E7%94%9F%E6%88%90%E7%9A%84%E5%9B%BE%E7%89%87</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E4%BB%8E%E6%98%A8%E5%A4%A9%E7%9A%84Aipic%E9%A1%B9%E7%9B%AE%E7%BB%A7%E7%BB%AD%EF%BC%8C%E5%88%86%E4%BA%AB%E5%87%A0%E5%BC%A0%E6%88%91%E7%94%9F%E6%88%90%E7%9A%84%E5%9B%BE%E7%89%87"/>
    <published>2025-05-31T06:38:23.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="Aipic更新"><a href="#Aipic更新" class="headerlink" title="Aipic更新"></a>Aipic更新</h2><p><strong>v1.1.0]]>
    </summary>
    <title>从昨天的Aipic项目继续，分享几张我生成的图片</title>
    <updated>2025-05-31T07:02:22.049Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="程序代码" scheme="https://hcyhub.com/tags/%E7%A8%8B%E5%BA%8F%E4%BB%A3%E7%A0%81/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Aipic"><a href="#Aipic" class="headerlink" title="Aipic"></a>Aipic</h1><p><img src="/../../images/Aipic/1920%C3%97400.png"></p><p>相关链接：<a href="">博文</a> | <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/2010HCY/Aipic">一键部署</a> | <a href="https://github.com/2010HCY/Aipic">GitHub页面</a></p><p>此项目使用Cloudflare免费提供的AI模型生成图片，使用CloudflareWorkers搭建。</p><p>有多个模型切换功能，支持以下模型：</p><pre class="line-numbers language-none"><code class="language-none">dreamshaper-8-lcm (优化的照片级真实感模型)stable-diffusion-xl-base-1.0 (高质量通用模型)stable-diffusion-xl-lightning (快速生成模型)flux-1-schnell (Black Forest Labs 12B参数模型)<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><p>可以设置生成的图像大小（flux-1-schnell不行，flux-1-schnell默认生成400×400的）</p><p>Cloudflare还提供以下模型</p><pre class="line-numbers language-none"><code class="language-none">stable-diffusion-v1-5-img2img (图像到图像转换模型)stable-diffusion-v1-5-inpainting (图像修复模型)<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>不过需要一张参考图片，我暂时没搞懂<del>坐等PR</del></p><p>以下是页面预览，页面还是保持了我特有的风格，十分好看：</p><img src="../../images/Aipic/Demo.png" style="zoom:80%;" /><h2 id="关于AI模型"><a href="#关于AI模型" class="headerlink" title="关于AI模型"></a>关于AI模型</h2><p>stable-diffusion-xl-base-1.0是我个人感觉质量最高的一个，但很容易出黑图，速度还可以，就是把分辨率拉满2048×2048的话会超时（免费版Workers单次Http请求最多30秒）</p><p>另外分辨率也不建议拉的过低，过低的话会出现乱七八糟无法描述的东西<del>（祂们看着你）</del>，建议拉到400以上。</p><p>消耗方面不高，我今天测试跑了差不多几十张图，也就消耗了1.56k神经元（每天免费10K）</p><p>dreamshaper-8-lcm模型说是优化的照片级真实感，但其实也没有多真实，感觉一般般有点类卡通。</p><p>目前支持的四种模型中文支持都很烂，所以提示词要使用英文。（未来此项目可能会接入Cloudflare提供的文字生成AI翻译提示词为英文，希望不要咕咕咕了）</p><p>如果喜欢我<del>优秀制作高雅的品味</del>的项目，就给<a href="https://github.com/2010HCY/Aipic">此项目</a>点个Star或给我的<a href="">博文</a>点个赞吧。最后再分享点stable-diffusion-xl-base-1.0生成的美图吧。</p><img src="../../images/Aipic/DemoImg1.png" style="zoom:80%;" /><img src="../../images/Aipic/DemoImg2.png" style="zoom:80%;" /><img src="../../images/Aipic/DemoImg3.png" style="zoom:80%;" /><img src="../../images/Aipic/1920×1080.png" style="zoom:80%;" /><img src="../../images/Aipic/512×512.png" style="zoom:80%;" /><p><del>不得不说我的风格审美就是好</del></p><p>最近维护着不少有意思的小玩具，最近有得忙喽，休息会，待会用这个AI生成我的个性电子邮件签名！是的没错，继HTML、富文本签名这两个版本，我又打算制作图片版本，敬请期待~</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/Aipic%E5%9B%BE%E7%89%87%E7%94%9F%E6%88%90%E9%A1%B9%E7%9B%AE</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/Aipic%E5%9B%BE%E7%89%87%E7%94%9F%E6%88%90%E9%A1%B9%E7%9B%AE"/>
    <published>2025-05-29T13:42:21.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Aipic"><a href="#Aipic" class="headerlink" title="Aipic"></a>Aipic</h1><p><img src="/../../images/Aipic/1920%C3%97400.png"></p>
<p>相关链接：<a href="">博文</a> | <a]]>
    </summary>
    <title>Aipic图片生成项目</title>
    <updated>2025-06-06T01:45:21.627Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p><img src="/./../../images/2FA%E9%A1%B5%E9%9D%A2.png"></p><p>如图，我刚刚输入2FA时发现我的MEGA的2FA代码是000003！非常罕见，下次会不会来个000001？</p><p><del>又水了一篇文章</del></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/2FA%E4%BB%A3%E7%A0%81%E5%87%BA%E7%8E%B0%E4%BA%86%E6%9E%81%E5%93%81%E6%95%B0%E5%AD%97000003%EF%BC%81</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/2FA%E4%BB%A3%E7%A0%81%E5%87%BA%E7%8E%B0%E4%BA%86%E6%9E%81%E5%93%81%E6%95%B0%E5%AD%97000003%EF%BC%81"/>
    <published>2025-05-28T03:06:22.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p><img]]>
    </summary>
    <title>我的2FA代码出现了极品数字000003！</title>
    <updated>2025-06-06T01:48:56.723Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="博客发展历程" scheme="https://hcyhub.com/tags/%E5%8D%9A%E5%AE%A2%E5%8F%91%E5%B1%95%E5%8E%86%E7%A8%8B/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="清理电脑"><a href="#清理电脑" class="headerlink" title="清理电脑"></a>清理电脑</h2><p>今天打算清理以下我的电子空间，就先从电脑开始吧</p><img src="./../../images/整理了下电脑桌面，清理文件，舒服了/桌面.png" style="zoom:80%;" />这是桌面，整理后特干净整洁，以前是整个桌面都堆满了我的文件、到处下载的代码文件<img src="./../../images/整理了下电脑桌面，清理文件，舒服了/下载.png" style="zoom:80%;" />下载文件夹，现在整理后干净多了，以前是70多个文件夹，翻要翻半天<img src="./../../images/整理了下电脑桌面，清理文件，舒服了/文档.png" style="zoom:80%;" />文档文件夹，是我存放东西最多的地方，放了一堆杂七杂八的配置文件啥啥啥的，收藏库哈哈<img src="./../../images/整理了下电脑桌面，清理文件，舒服了/素材.png" style="zoom:80%;" />子文件夹素材，这里塞了一堆我收集的屌图、好看的图片，之前丢桌面很不美观，现在塞这个文件夹里清爽多了 ~~（眼不见心不烦）~~<p>顺便一提，我刚刚删了不少文档里的文件夹，全是卸载程序后的残留。<del>咋软件都不会清理干净后再从我的电脑上消失</del></p><h2 id="修博客"><a href="#修博客" class="headerlink" title="修博客"></a>修博客</h2><h3 id="友链"><a href="#友链" class="headerlink" title="友链"></a>友链</h3><p>今天把博客的友链复活了，之前不知道找谁交换友链就删了，今天复活了友链页面，不用主题的页面，我自己自定义了下友链样式，好看。做博客的意义之一估计就是可以做出符合自己审美的作品了吧？看着自己的想法实现的感觉真好的。</p><p><a href="/friends">友链页面</a></p><p>友链页面概览：<br><img src="./../../images/整理了下电脑桌面，清理文件，舒服了/友链.png" style="zoom:80%;" /></p><img src="./../../images/整理了下电脑桌面，清理文件，舒服了/动态友链.png" style="zoom:80%;" /><h3 id="评论区"><a href="#评论区" class="headerlink" title="评论区"></a>评论区</h3><p>彻底修好了评论区的样式问题，舒服。</p><p>修复前：</p><img src="./../../images/整理了下电脑桌面，清理文件，舒服了/修复前.png" style="zoom:80%;" /><p>修复后：</p><img src="./../../images/整理了下电脑桌面，清理文件，舒服了/修复后.png" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%95%B4%E7%90%86%E4%BA%86%E4%B8%8B%E7%94%B5%E8%84%91%E6%A1%8C%E9%9D%A2%EF%BC%8C%E9%A1%BA%E4%BE%BF%E4%BF%AE%E4%BA%86%E4%BF%AE%E5%8D%9A%E5%AE%A2%EF%BC%8C%E8%88%92%E6%9C%8D</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%95%B4%E7%90%86%E4%BA%86%E4%B8%8B%E7%94%B5%E8%84%91%E6%A1%8C%E9%9D%A2%EF%BC%8C%E9%A1%BA%E4%BE%BF%E4%BF%AE%E4%BA%86%E4%BF%AE%E5%8D%9A%E5%AE%A2%EF%BC%8C%E8%88%92%E6%9C%8D"/>
    <published>2025-05-26T09:37:49.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="清理电脑"><a href="#清理电脑" class="headerlink" title="清理电脑"></a>清理电脑</h2><p>今天打算清理以下我的电子空间，就先从电脑开始吧</p>
<img src="./../../images/整理了下电脑桌面，清理文件，舒服了/桌面.png" style="zoom:80%;" />
这是桌面，整理后特干净整洁，以前是整个桌面都堆满了我的文件、到处下载的代码文件

<img]]>
    </summary>
    <title>整理了下电脑桌面，顺便修了修博客，舒服</title>
    <updated>2025-05-26T09:40:19.090Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>所有来到我的博客的人都应该有看到，我博客的首页有一张地球的图片，那可不是一张普通的不会变化图片，它是会根据时间变化更新的，黑色的背景中那一颗蓝色星球时而隐在阴影中，时而又在太阳的照耀下像一颗蓝宝石，而就在刚刚，我发现了个有意思的现象</p><h2 id="随时间变化的大小"><a href="#随时间变化的大小" class="headerlink" title="随时间变化的大小"></a>随时间变化的大小</h2><img src="./../../images/我博客的首页图，记录着地球的心跳/存储空间曲线图.png" style="zoom:80%;" /><p>这，是过去24小时地球图片占用的空间曲线图，看这条平滑起伏的蓝色曲线，是不是有种莫名的舒适感？它不像那些杂乱无章的数据，而是充满了规律性。你会发现，图片的大小随着时间推移，先是慢慢减小，到达一个<strong>低谷</strong>后，又开始缓缓增加，然后达到一个<strong>高峰</strong>，随后再次减小，周而复始。而这<strong>有节律的波动</strong>，第一次看到就抓住了我的目光。</p><p>为什么图片大小会如此规律地跟随时间变化呢？这背后正是地球自转带来的昼夜更替在起作用。随着地球的自转，卫星捕捉到的地球影像中，处于白天与处于夜晚（阴影）区域的面积会持续变化。这种<strong>光影面积的消长</strong>，直接决定了画面的细节丰富程度。</p><p>这是因为地球随着时间变化，因为自转，会有始终有一部分区域背对于太阳没入阴影中，而地球图片上，随时间变化阴影的面积也会不断增加、减少，当地球图片上能看到的地方全沉浸在黑暗中时，图片就是漆黑一片（毕竟黑夜里看不到太多东西）：</p><img src="./../../images/我博客的首页图，记录着地球的心跳/全在阴影中.png" style="zoom:80%;" /><p>你看，几乎漆黑一片。在这时，图片上的区域背对太阳，在一片漆黑的画面里，由于缺乏光照细节，图片的细节也十分少，可以被高度压缩，文件大小会下降到最低点，大概只有 20KB 左右。这就像是地球进入了<strong>“休息”阶段</strong>，心跳的低谷；</p><p>相反，当地球的这一面正好面向太阳、被阳光完全照亮时：</p><img src="./../../images/我博客的首页图，记录着地球的心跳/全在阳光下.png" style="zoom:80%;" /><p>这时云层、陆地纹理、海洋反光等细节拉满，画面信息量巨大。图片难以被大幅压缩，文件大小也会随之飙升跃升至约 480KB 的高峰。这仿佛是地球进入了<strong>“活跃”阶段</strong>，心跳的巅峰。 </p><p>正是地球永不停歇的自转，周而复始地改变着卫星视野下的光照面积和画面细节，从而直接体现在了图片文件大小的规律性波动上。每一次大小的<strong>起伏</strong>，都精确地契合着地球昼夜的更迭周期，就像是星球在有规律地<strong>律动</strong>，而这律动，就像地球的心跳一样</p><img src="./../../images/我博客的首页图，记录着地球的心跳/地球的心跳.png" style="zoom:80%;" /><p>所以，这张静静躺在存储桶里的地球图片，它的大小变化曲线，简直就是地球自转、昼夜交替最诚实的“心电图”！每一次峰谷的循环，都是地球的一次<strong>“脉动”</strong>，安静而有力地展现地球那无声而有力的脉搏。</p><h2 id="完了"><a href="#完了" class="headerlink" title="完了"></a>完了</h2><p>这个有趣的现象是我今天阅读昨日数据分析时发现的，在冰冷的代码与数据背后，也可能藏着有趣的规律。有时候，技术本身产生的副产品也并非毫无价值，就比如今天的这个大小曲线，给我提供了一个全新的视角，这个曲线不但是大小曲线，还是光照面积曲线、地球脉动曲线，多么有意思啊</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%88%91%E5%8D%9A%E5%AE%A2%E7%9A%84%E9%A6%96%E9%A1%B5%E5%9B%BE%EF%BC%8C%E8%AE%B0%E5%BD%95%E7%9D%80%E5%9C%B0%E7%90%83%E7%9A%84%E5%BF%83%E8%B7%B3</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%88%91%E5%8D%9A%E5%AE%A2%E7%9A%84%E9%A6%96%E9%A1%B5%E5%9B%BE%EF%BC%8C%E8%AE%B0%E5%BD%95%E7%9D%80%E5%9C%B0%E7%90%83%E7%9A%84%E5%BF%83%E8%B7%B3"/>
    <published>2025-05-19T05:27:33.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>所有来到我的博客的人都应该有看到，我博客的首页有一张地球的图片，那可不是一张普通的不会变化图片，它是会根据时间变化更新的，黑色的背景中那一颗蓝色星球时而隐在阴影中，时而又在太阳的照耀下像一颗蓝宝石，而就在刚刚，我发现了个有意思的现象</p>
<h2 id="随时间变化的大小"><a]]>
    </summary>
    <title>我博客的首页图，记录着地球的心跳</title>
    <updated>2025-06-06T01:46:33.059Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="为啥要防止R2被刷？"><a href="#为啥要防止R2被刷？" class="headerlink" title="为啥要防止R2被刷？"></a>为啥要防止R2被刷？</h2><p>Cloudflare的R2免费额度十分大方，流量无限，1000万次B类请求并带有CDN缓存</p><img src="./../../images/CloudflareR2防刷请求方法分享/R2免费额度.png" style="zoom:80%;" /><p>如此大方的免费额度，一切看着十分美好，但问题是：</p><ol><li>404类请求是算入B类操作的</li><li>带URL参数的请求可以绕过缓存</li></ol><p>所以这就导致R2的请求数可以很方便的绕过CDN刷R2，刷子们只需要不同请求不存在的文件或带上URL参数，那么每一下请求都会结结实实的打在R2上，1000万请求也扛不住一台2C2G的小鸡锲而不舍的刷上半天啊，为了避免我的账单爆表，所以有必要研究下怎么保护好我的钱包。</p><h2 id="规避高昂成本操作"><a href="#规避高昂成本操作" class="headerlink" title="规避高昂成本操作"></a>规避高昂成本操作</h2><h3 id="会计费的操作"><a href="#会计费的操作" class="headerlink" title="会计费的操作"></a>会计费的操作</h3><p>我研究一下CloudflareR2那些操作会算入计费操作，经过研究，我得出以下结论：</p><p>1.<strong>A类操作</strong>是<strong>创建存储桶</strong>、<strong>写入对象</strong>操作，成本较高</p><table><thead><tr><th>会计入次数的操作</th><th>写入、复制、列出对象或分片对象</th><th>设置桶CORS</th><th>对象生命周期配置</th></tr></thead><tbody><tr><td>不计次的操作</td><td>删除对象、中止分片上传</td><td>删除存储桶</td><td></td></tr></tbody></table><p>2.<strong>B类操作</strong>是出口操作，成本较低</p><table><thead><tr><th>会计入次数的操作</th><th>常规的下载、取出文件</th><th>请求不存在的文件404页面</th><th>携带URL参数的请求</th></tr></thead><tbody><tr><td>不计次的操作</td><td>被CDN缓存的文件</td><td>未到达R2的请求<del>(废话)</del></td><td></td></tr></tbody></table><p>3.存储空间，这个免费存储空间可不是说你最多只能使用10GB，是根据使用你的<strong>使用情况</strong>来进行计费的，是<strong>每月使用量</strong></p><p>我打几个比方：</p><table><thead><tr><th>第一天操作</th><th>接下来的30天操作</th><th>月底结算</th></tr></thead><tbody><tr><td>存入10GB整的文件</td><td>不做任何操作</td><td>10 GB * (30&#x2F;30) &#x3D;10GB&#x2F;月，恭喜，免费！</td></tr><tr><td>存入299.99GB整文件</td><td>在接下来的29天内清空存储库</td><td>299.99GB * (1&#x2F;30) ≈ 9.99GB&#x2F;月，恭喜，免费！</td></tr><tr><td>存入301GB整文件</td><td>在接下来的29天内清空存储库</td><td>301GB * (1&#x2F;30) ≈ 10.03GB&#x2F;月，收取0.03GB费用</td></tr></tbody></table><p>R2定价的计算公式就是取你每一天使用的存储的最大值（例如峰值299.99GB），然后计算在<strong>30天内的占比</strong>，最后计算<strong>每一天峰值</strong>使用的存储在30天内的占比<strong>总和</strong>，若没有超过10GB即免费。</p><p>（每月使用量）&#x3D; (\frac{P_1 + P_2 + P_3 + … + P_{30}}{30})</p><h3 id="如何规避？"><a href="#如何规避？" class="headerlink" title="如何规避？"></a>如何规避？</h3><p>所以，根据以上信息，我得出以下减少R2费用结论：</p><ol><li>少写入、复制文件</li><li>多用<strong>CDN</strong>缓存公开的文件</li><li>将404、带URL参数的请求统统<strong>拦截</strong></li><li>不要存放过大文件</li></ol><h2 id="开始规避"><a href="#开始规避" class="headerlink" title="开始规避"></a>开始规避</h2><h3 id="1-设置缓存"><a href="#1-设置缓存" class="headerlink" title="1.设置缓存"></a>1.设置缓存</h3><p>首先第一条是设置CDN，这个最简单有效还能提速，设置方法很简单，用<strong>Cache Rules规矩</strong>就好了</p><img src="./../../images/CloudflareR2防刷请求方法分享/Cache Rules规则配置.png" style="zoom:80%;" /><p>输入你的R2自定义公开域，然后设置匹配规则，下面选择符合缓存规则，然后再在下面根据你的需要设置下缓存TTL即可，注意要把<strong>忽略查询字符串</strong>打开，这样才会防止一堆携带URL参数的请求刷爆你的R2</p><h3 id="防刷B类请求"><a href="#防刷B类请求" class="headerlink" title="防刷B类请求"></a>防刷B类请求</h3><p>想要防止一堆随机发送访问无效路径的请求刷我R2的B类请求，我便使用如下规则：</p><pre class="line-numbers language-none"><code class="language-none">(http.host eq &quot;earthcdn.teahush.link&quot; and not (http.request.full_uri eq &quot;https:&#x2F;&#x2F;earthcdn.teahush.link&#x2F;latest.png&quot; or http.request.full_uri eq &quot;https:&#x2F;&#x2F;earthcdn.teahush.link&#x2F;888.png&quot;))<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>效果：</p><ul><li>白名单上的latest.png</li></ul><img src="./../../images/CloudflareR2防刷请求方法分享/白名单内的文件路径请求.png" style="zoom:80%;" /><ul><li>不在白名单上的666.png：</li></ul><img src="./../../images/CloudflareR2防刷请求方法分享/无效路径请求.png" style="zoom:80%;" /><p>访问不存在路径的请求将会被拦截</p><p>如何使用？只需要修改<code>earthcdn.teahush.link</code>为你的R2公开访问域，然后<code>(http.host eq &quot;earthcdn.teahush.link&quot; and not ()</code>后的括号里添加你的文件路径即可，格式为<code>earthcdn.teahush.link&quot; and not (http.request.full_uri eq &quot;https://你的R2访问域/文件名&quot; or http.request.full_uri eq &quot;https://你的R2访问域/路径/文件名&quot;)</code>，每两个文件路径间用or连接，将编辑好的表达式输入图片上的方框内就好了</p><img src="./../../images/CloudflareR2防刷请求方法分享/R2防404攻击.png" style="zoom:80%;" /><p>将你有存放文件的地址都添加进去，这样就会拦截掉一切请求无效路径的请求，防止404攻击。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>折腾半天就为了防止账单爆表，弄完后感觉还不如直接开CDN、速率限制，若网站火爆乖乖付款升级套餐🤣</p><p>写这类表达式还挺有意思的，很好玩，就是很容易写错了把整个站点搞下线，嗯，研究了半天表达式，我写了17个方案，感觉我已经成机器人思维了。<del>My programming is complete. I am now… myself.</del></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/CloudflareR2%E9%98%B2%E5%88%B7%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%E5%88%86%E4%BA%AB</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/CloudflareR2%E9%98%B2%E5%88%B7%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%E5%88%86%E4%BA%AB"/>
    <published>2025-05-17T09:45:25.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="为啥要防止R2被刷？"><a href="#为啥要防止R2被刷？" class="headerlink" title="为啥要防止R2被刷？"></a>为啥要防止R2被刷？</h2><p>Cloudflare的R2免费额度十分大方，流量无限，1000万次B类请求并带有CDN缓存</p>
<img src="./../../images/CloudflareR2防刷请求方法分享/R2免费额度.png"]]>
    </summary>
    <title>CloudflareR2防刷请求方法分享</title>
    <updated>2025-05-17T10:08:48.613Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="树洞" scheme="https://hcyhub.com/tags/%E6%A0%91%E6%B4%9E/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><blockquote><p>叠甲：本文没有任何挂人的意思，纯吐槽我这个傻逼白干活的发泄一下，QQ群里的名字都是网名，不包含真实信息，我没有挂任何人的联系方式、隐私信息。</p><p>好叠甲完毕，正文开始</p></blockquote><p>事情是这样的，4月9日我在一个Flash交流群里水群，这时主角登场了，找我提取素材的人加群了，它的QQ小号名字叫”<strong>海</strong>“，下面就叫他”海“。<strong>海</strong>加群后第一时间发送信息询问有谁会提取游戏素材，它愿意<strong>红包付费</strong></p><p><img src="./../../images/记一次帮别人提取素材结果白干的经历/进群提出付费提取.png" style="zoom:80%;" />我看到后便发消息询问是什么游戏，它回复要 贴贴素材、怪物人物这些序列针图片，游戏名叫<strong>西西火影世界</strong>。</p><h2 id="开始提取素材"><a href="#开始提取素材" class="headerlink" title="开始提取素材"></a>开始提取素材</h2><p>我便搜索、查询了这个游戏，找到了相关信息，经确认得知这游戏是个上古时期早就停服的游戏，只剩几个民营的服务器。</p><img src="./../../images/记一次帮别人提取素材结果白干的经历/询问是否是这个游戏.png" style="zoom:80%;" /><p>但由于年代久远不好找到相关文件，抓取又费劲，我本来是想当没看见的，但<strong>海</strong>提出了<strong>100红包报酬</strong>，费点功夫赚个100挺不错的，当时我都盘算着弄完后买点啥犒劳自己了。</p><img src="./../../images/记一次帮别人提取素材结果白干的经历/提出100红包报酬.png" style="zoom:80%;" /><p>得到了有报酬这个”<strong>肯定</strong>“的保证后我就开始提取了，提取过程省略，简单来说就是花了一下午抓取服务器后端的完整文件，然后发现是Java服务器+SWF素材文件，挺有意思的，提取完后是237 MB 6,106张图片7首音乐。</p><h2 id="提取完成，海消失"><a href="#提取完成，海消失" class="headerlink" title="提取完成，海消失"></a>提取完成，海消失</h2><p>接下来就是和<strong>海</strong>进行交涉了，我发送截图过去，但它一直扯什么序列帧、素材大小对不上，一直发令人费解感觉像是外星口音的语音（语音内容为隐私，不放），我实在烦了便将部分素材打包发送给它了，它接受得很快。</p><p>很好，接下来就是说电脑坏了，嗯我一开始还想现在应该没有人会用这么蹩脚的接口推辞，结果还真是推辞，一会电脑坏了一会上班没时间看，我发送的预览视频也不看，直接玩消失，一个月后的今天还是消失，我点开它的QQ个人卡片一看心都凉了，是一个2级小号（截图时过了一个月它升5级了，说明它这一个月<strong>有上线</strong>，但就是不理我），我那时就感觉基本无望了，一个月过去了它仍然在消失。</p><img src="./../../images/记一次帮别人提取素材结果白干的经历/海.png" style="zoom:80%;" /><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>我看到了海它的信息，我花费大量时间给它提取，等我提取完后它直接消失，我被当成猴耍，白干了，而且我现在也不知道它到底是出于何种目的来耍我，它在这一个月间有登录QQ，等级从<strong>2级升到了5级</strong>，但它就是不理我，该兑现的承诺也没有，我现在还保存这素材、提取时写的脚本，但我永远也等不到我的100报酬了</p><p>我…</p><img src="./../../images/小丑.webp" style="zoom:80%;" /><details>  <summary>我与海的完整聊天记录</summary>  <img src="./../../images/记一次帮别人提取素材结果白干的经历/和海的完整聊天记录.png" style="zoom:80%;" /></details>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%B8%AE%E5%88%AB%E4%BA%BA%E6%8F%90%E5%8F%96%E7%B4%A0%E6%9D%90%E7%BB%93%E6%9E%9C%E7%99%BD%E5%B9%B2%E7%9A%84%E7%BB%8F%E5%8E%86</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%B8%AE%E5%88%AB%E4%BA%BA%E6%8F%90%E5%8F%96%E7%B4%A0%E6%9D%90%E7%BB%93%E6%9E%9C%E7%99%BD%E5%B9%B2%E7%9A%84%E7%BB%8F%E5%8E%86"/>
    <published>2025-05-12T11:19:46.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="起因"><a href="#起因" class="headerlink"]]>
    </summary>
    <title>记一次帮别人提取素材结果白干的经历</title>
    <updated>2025-05-12T11:29:33.494Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>众所周知，谷歌的服务在中国大陆总是有股神秘力量在干扰，而谷歌分析也不能幸免于难，总是无法使用</p><p><img src="/./../../images/%E7%94%A8%E7%AC%AC%E4%B8%80%E6%96%B9%E6%A8%A1%E5%BC%8F%E4%BC%98%E9%9B%85%E7%9A%84%E7%BB%95%E8%BF%87%E5%B0%81%E9%94%81%E8%B0%B7%E6%AD%8C%E5%88%86%E6%9E%90%E7%9A%84%E7%A5%9E%E7%A7%98%E5%8A%9B%E9%87%8F/ERROR.png"></p><p>而作为一个有强迫症的人，控制台里这个报错简直令我感觉浑身上下有无数只蚂蚁在爬，坐立难安，正好今天看见Cloudflare多了个新玩具 标记管理——Google 标记 ，这不得好好研究研究？</p><img src="./../../images/用第一方模式优雅的绕过封锁谷歌分析的神秘力量/Google 标记管理.png" style="zoom:80%;" /><p>经过研究，这个<strong>“第一方模式的 Google 标记”</strong>是一个可以完美解决谷歌分析在中国大陆无法使用的好东西，我先简单介绍一下原理：</p><p>传统的谷歌分析是通过在head里安装谷歌分析代码，然后谷歌分析代码向谷歌的后端 <a href="https://www.googletagmanager.com/gtag/js?id=%E8%BF%99%E9%87%8C%E6%98%AF%E4%BD%A0%E7%9A%84%E6%A0%87%E8%AE%B0ID">https://www.googletagmanager.com/gtag/js?id=这里是你的标记ID</a> 发送分析数据，而<a href="https://www.googletagmanager.com/">https://www.googletagmanager.com</a> 这个网址可以说是几乎不可能打得开、使用，这玩意放在你的页面里就纯粹是为了多加个报错，淦。</p><p>而这个<strong>“第一方模式的 Google 标记”</strong>（这读起来咋跟咒语一样？）就不一样了，它不再是直接向谷歌发送数据请求，而是先向你的域名下的一个路径（例如&#x2F;analytics）发送数据，然后&#x2F;analytics路径的路由再向谷歌发送数据，等于说是加了个中转者，帮你中转数据，完美的绕开了神秘的力量，让分析数据可以走你的网站线路，只要能访问你的网站，就能使用谷歌分析！</p><img src="./../../images/用第一方模式优雅的绕过封锁谷歌分析的神秘力量/示意图.png" style="zoom:80%;" /><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>首先你的网站域名要托管在Cloudflare上，并且有开小黄云，然后到你的Cloudflare主页，下拉找到标记管理——Google 标记，点击打开，然后选择你的域名，看到如下界面了吗？</p><img src="./../../images/用第一方模式优雅的绕过封锁谷歌分析的神秘力量/Google 标记管理.png" style="zoom:80%;" /><p>点击那个更新配置按钮，在标记ID里填入你的谷歌分析的标记ID，标记ID是这玩意：</p><pre class="line-numbers language-none"><code class="language-none">&lt;!-- Google tag (gtag.js) --&gt;&lt;script async src&#x3D;&quot;https:&#x2F;&#x2F;www.googletagmanager.com&#x2F;gtag&#x2F;js?id&#x3D;G-0P4JLHJL9R&quot;&gt;&lt;&#x2F;script&gt;&lt;script&gt;  window.dataLayer &#x3D; window.dataLayer || [];  function gtag()&#123;dataLayer.push(arguments);&#125;  gtag(&#39;js&#39;, new Date());  gtag(&#39;config&#39;, &#39;G-这个就是你的标记ID&#39;);&lt;&#x2F;script&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>度量路径是你想要的后端路径，如果站点域名是100713.xyz，度量路径是&#x2F;analytics，那么分析数据会发送到<a href="https://100713.xyz/analytics">https://100713.xyz/analytics</a> 下，但你要确保原来这个路径下面没有其他的东西。</p><p>设置标记这个也打开，这样更省事。</p><img src="./../../images/用第一方模式优雅的绕过封锁谷歌分析的神秘力量/配置界面.png" style="zoom:80%;" /><p>配置好后点击保存，然后你就可以直接在你的网站上删掉原来的谷歌分析代码块，然后直接使用了！确认配置是否成功你可以按F12开发者工具里的网络选项里搜索&#x2F;analytics（搜索你的度量路径名），看到有请求该路径的加载请求就说明成功了：</p><img src="./../../images/用第一方模式优雅的绕过封锁谷歌分析的神秘力量/配置验证.png" style="zoom:80%;" /><p>如果你有多个子域名创建了不同的分析项目，你应该在head标签里加入：</p><pre class="line-numbers language-none"><code class="language-none">&lt;script&gt;  window.dataLayer &#x3D; window.dataLayer || [];  function gtag()&#123;dataLayer.push(arguments);&#125;  gtag(&#39;js&#39;, new Date());  gtag(&#39;config&#39;, &#39;G-你的标记ID&#39;);&lt;&#x2F;script&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后关闭Cloudflare的自动安装和设置 Google 标记，这样才能不同的网站区分不同分析项目，关闭Cloudflare的自动安装和设置 Google 标记后Cloudflare只会往你的head标签里塞</p><pre class="line-numbers language-none"><code class="language-none">&lt;script&gt;(function(w,i,g)&#123;w[g]&#x3D;w[g]||[];if(typeof w[g].push&#x3D;&#x3D;&#39;function&#39;)w[g].push(i)&#125;) (window,&#39;G-你在控制台里设置的ID&#39;,&#39;google_tags_first_party&#39;);&lt;&#x2F;script&gt; &lt;script async&#x3D;&quot;&quot; src&#x3D;&quot;&#x2F;analytics&#x2F;&quot;&gt;&lt;&#x2F;script&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>虽然里面有你在控制台里设置的ID，但如果你在子域名的网站中设置了</p><pre class="line-numbers language-none"><code class="language-none">&lt;script&gt;      window.dataLayer &#x3D; window.dataLayer || [];      function gtag()&#123;dataLayer.push(arguments);&#125;      gtag(&#39;js&#39;, new Date());            gtag(&#39;config&#39;, &#39;G-子域名ID&#39;);    &lt;&#x2F;script&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>子域名的ID优先级会更高，数据将会发送到子域名ID的谷歌分析应用下。</p><h2 id="完事"><a href="#完事" class="headerlink" title="完事"></a>完事</h2><p>点个赞？这可是我第一次为了写文章画流程图呢。如果你有什么不懂、不理解、不确定的地方，欢迎留言提问</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E7%94%A8%E7%AC%AC%E4%B8%80%E6%96%B9%E6%A8%A1%E5%BC%8F%E4%BC%98%E9%9B%85%E7%9A%84%E7%BB%95%E8%BF%87%E5%B0%81%E9%94%81%E8%B0%B7%E6%AD%8C%E5%88%86%E6%9E%90%E7%9A%84%E7%A5%9E%E7%A7%98%E5%8A%9B%E9%87%8F</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E7%94%A8%E7%AC%AC%E4%B8%80%E6%96%B9%E6%A8%A1%E5%BC%8F%E4%BC%98%E9%9B%85%E7%9A%84%E7%BB%95%E8%BF%87%E5%B0%81%E9%94%81%E8%B0%B7%E6%AD%8C%E5%88%86%E6%9E%90%E7%9A%84%E7%A5%9E%E7%A7%98%E5%8A%9B%E9%87%8F"/>
    <published>2025-04-28T06:45:21.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>众所周知，谷歌的服务在中国大陆总是有股神秘力量在干扰，而谷歌分析也不能幸免于难，总是无法使用</p>
<p><img]]>
    </summary>
    <title>用第一方模式优雅的绕过封锁谷歌分析的神秘力量</title>
    <updated>2025-06-06T01:47:41.291Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="树葡萄"><a href="#树葡萄" class="headerlink" title="树葡萄"></a>树葡萄</h2><p>昨天去九日山玩，回家时在路边看到了个树葡萄采摘基地，远远望去，一棵棵像灌木一样的小树树干上挂满了黑色的小葡萄，这不得去看看？</p><img src="./../../images/你们见过树葡萄吗？/DSC00038.JPG" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00047.JPG" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00055.JPG" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00056.JPG" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00057.JPG" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00061.JPG" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00066.JPG" style="zoom:80%;" /><p>树葡萄的果子硬硬的，不像葡萄一样是薄皮，前几天下了雨，摘的时候每颗果子都亮晶晶的，像黑珍珠一样，老板说可以边采边吃，随便吃，我试了下，很甜，树葡萄的吃法是先用牙齿轻轻咬一个缝，然后用嘴把果肉给吸出来，我吃到的每一个果子都好甜，就是皮有点涩，果肉相对少了点</p><img src="./../../images/你们见过树葡萄吗？/DSC00070.JPG" alt="叶子" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00071.JPG" alt="叶子" style="zoom:80%;" /><img src="./../../images/你们见过树葡萄吗？/DSC00074.JPG" alt="叶子" style="zoom:80%;" /><p>树葡萄的叶子是小小片的一丛丛的，还挺好看的呢。</p><p>这个树葡萄种植园不大，在南安的一个不起眼的小路边上，听老板说这树葡萄是2002年引进的，种了20多年呢。</p><p>树葡萄采摘园的具体位置我也描述不清了，挺有意思的经历</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E4%BD%A0%E4%BB%AC%E8%A7%81%E8%BF%87%E6%A0%91%E8%91%A1%E8%90%84%E5%90%97%EF%BC%9F</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E4%BD%A0%E4%BB%AC%E8%A7%81%E8%BF%87%E6%A0%91%E8%91%A1%E8%90%84%E5%90%97%EF%BC%9F"/>
    <published>2025-04-27T06:41:01.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="树葡萄"><a href="#树葡萄" class="headerlink" title="树葡萄"></a>树葡萄</h2><p>昨天去九日山玩，回家时在路边看到了个树葡萄采摘基地，远远望去，一棵棵像灌木一样的小树树干上挂满了黑色的小葡萄，这不得去看看？</p>
<img src="./../../images/你们见过树葡萄吗？/DSC00038.JPG" style="zoom:80%;" />

<img]]>
    </summary>
    <title>你们见过树葡萄吗？长在树上的葡萄</title>
    <updated>2025-10-07T06:38:13.107Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Twikoo-backup"><a href="#Twikoo-backup" class="headerlink" title="Twikoo-backup"></a>Twikoo-backup</h1><img src="./../../images/评论不怕丢！使用Cloudflare大善人每日自动备份Twikoo评论数据/页面.png" style="zoom:80%;" /><p>项目地址：<a href="https://github.com/2010HCY/twikoo-backup">https://github.com/2010HCY/twikoo-backup</a></p><p>一键部署：<br><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/2010HCY/twikoo-backup"><img src="https://deploy.workers.cloudflare.com/button" alt="Deploy to Cloudflare Workers"></a></p><p>如果你的博客使用的是Twikoo评论系统，并且还是按官方教程白嫖的MongoDB，那要注意MongoDB在你长时间没有使用数据库时是会回收空间的，而且更要命的是它还不会发邮件通知，我的数据库就是差点被回收，好在我及时发现了评论系统不能用，及时恢复了账号，要不然数据啥子的都没了。</p><p>所以，为了避免数据丢失，我写了个备份项目，使用Cloudflare新出的“玩具”：workflows工作流 进行自动备份，备份数据将储存在D1数据库里，省心好用。它可以使用CloudflareWorkers工作流实现自动备份，也可以手动备份，备份将在每天00：00自动运行。并且部署不难很简单，一键部署，一键备份，一键导出，简单的UI也十分好看。</p><p>若Twikoo评论数据出现丢失、恶意污染，导出备份也十分方便，你可以在浏览器里一键下载最新备份，下载文件名为<code>twikoo-comment-备份日期.json</code></p><img src="./../../images/评论不怕丢！使用Cloudflare大善人每日自动备份Twikoo评论数据/备份成功.png" style="zoom:80%;" /><p>部署很简单，点击一键部署按钮，然后根据提示设置数据库名，部署好后到Workers的设置里设置下变量，</p><p>变量说明</p><pre class="line-numbers language-none"><code class="language-none">TWIKOO_URL &#x3D; &quot;https:&#x2F;&#x2F;xxxxx&#x2F;.netlify&#x2F;functions&#x2F;twikoo&quot; #你的Twikoo后端地址TWIKOO_PASSWORD &#x3D; &quot;xxxxx&quot;  #你的Twikoo后端密码BACKUP_KEEP_DAYS &#x3D; &quot;3&quot; #工作流将保存几份备份<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><p>然后打开Workers页面，点击开始备份或等待次日00：00自动备份，若下方出现了历史备份就说明成功了</p><img src="./../../images/评论不怕丢！使用Cloudflare大善人每日自动备份Twikoo评论数据/配置.png" style="zoom:80%;" /><p>接下来打算研究研究Cloudflare新出玩具工作流还能干什么</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E8%AF%84%E8%AE%BA%E4%B8%8D%E6%80%95%E4%B8%A2%EF%BC%81%E4%BD%BF%E7%94%A8Cloudflare%E5%A4%A7%E5%96%84%E4%BA%BA%E6%AF%8F%E6%97%A5%E8%87%AA%E5%8A%A8%E5%A4%87%E4%BB%BDTwikoo%E8%AF%84%E8%AE%BA%E6%95%B0%E6%8D%AE</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E8%AF%84%E8%AE%BA%E4%B8%8D%E6%80%95%E4%B8%A2%EF%BC%81%E4%BD%BF%E7%94%A8Cloudflare%E5%A4%A7%E5%96%84%E4%BA%BA%E6%AF%8F%E6%97%A5%E8%87%AA%E5%8A%A8%E5%A4%87%E4%BB%BDTwikoo%E8%AF%84%E8%AE%BA%E6%95%B0%E6%8D%AE"/>
    <published>2025-04-21T04:04:05.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Twikoo-backup"><a href="#Twikoo-backup" class="headerlink" title="Twikoo-backup"></a>Twikoo-backup</h1><img src="./../../images/评论不怕丢！使用Cloudflare大善人每日自动备份Twikoo评论数据/页面.png" style="zoom:80%;" />

<p>项目地址：<a]]>
    </summary>
    <title>评论不怕丢！使用Cloudflare大善人每日自动备份Twikoo评论数据</title>
    <updated>2025-06-06T01:47:09.906Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="个性签名" scheme="https://hcyhub.com/tags/%E4%B8%AA%E6%80%A7%E7%AD%BE%E5%90%8D/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="设计我的电子邮件签名"><a href="#设计我的电子邮件签名" class="headerlink" title="设计我的电子邮件签名"></a>设计我的电子邮件签名</h2><p>平时发邮件总感觉文字签名太普通了，想弄个专属的“个人名片”放在邮件底部，既能显得有点逼格，也能顺便介绍下自己，让对方稍微了解一下我。于是我自己动手设计了一个电子邮件签名，过程里碰了不少坑，整了几版才搞定，折腾完后写篇文章给大家讲讲HTML邮件的槽点和我自己梳理一下设计过程。</p><p>首先要讲的是：</p><h2 id="个人电子邮件签名应该包括什么？"><a href="#个人电子邮件签名应该包括什么？" class="headerlink" title="个人电子邮件签名应该包括什么？"></a>个人电子邮件签名应该包括什么？</h2><p>首先要有你的名字 <del>要不然叫什么签名</del>，毫无疑问，这将是签名的基石。名字呢应该在一个显眼的位置，想想你们收到的名片，名字通常位于中间部分，并且相对靠上、字号更大。</p><p>其次是联系方式，个人的电子邮件签名肯定不用考虑什么商业因素，因此不必放过多的联系方式，联系方式放你发送邮件的邮箱地址即可（也就是你的常用个人邮箱啦）。</p><p>为什么要放发件地址？对方不会自己看邮件发件人吗？其实放发件地址是为了更快的告诉对方你的身份，毕竟大多数普通人打开邮件是直接先看标题再看正文的，发件人那行小字大多是直接忽视，尤其是在快速浏览邮件时。而在签名里放置邮箱可以让对方快速知道你是谁，并且可以记住你的地址，方便下次联系、回信。</p><p>然后是一段个性签名之类的，可以 <del>展现B格</del> 让对方知道你是啥类型的人，是展现个人风格和品味的好地方。如果你是发邮件交朋友的话还可以给对方留一个第一印象，所以不要瞎选个性签名，到时个性签名和人设撞了就尴尬了。</p><p>还有就是你的头像，这个很重要，我可以毫不过分的说头像是互联网的身份证照，文字给人的印象是需要去理解才能记住，而一张具有个性的图片通常看一眼就能留下印象。不信你们可以去试试把自己的社交账号头像改掉，看看还有多少人能认出你（那些名字很有特色的除外啊）。</p><p>最后是一些小装饰，比如你的博客、个人项目页面之类的，这一方面可以 <del>引流</del> 让对方知道了解你的途径，一方面可以让页面不那么空。这里我选择放我的网站链接和网站账户。</p><p>总结一下就是：</p><ol><li><strong>醒目的全名：</strong> 清晰地表明你的身份。</li><li><strong>常用邮箱地址：</strong> 方便对方快速识别和记住你的联系方式。</li><li><strong>个人头像：</strong> 重要的视觉元素，有助于留下深刻印象。</li><li><strong>个性签名（可选，尽量加上）：</strong> 展现你的个人风格或信仰。</li><li><strong>个人链接（可选）：</strong> 提供了解你的更多途径。</li></ol><h2 id="开始设计"><a href="#开始设计" class="headerlink" title="开始设计"></a>开始设计</h2><h3 id="原型：H5版"><a href="#原型：H5版" class="headerlink" title="原型：H5版"></a>原型：H5版</h3><h4 id="1-0版"><a href="#1-0版" class="headerlink" title="1.0版"></a>1.0版</h4><p>初版是所有内容居中显示，最开始打算把我的头像放顶上，后来发现太难看了，所以我删了，但总体也不咋好看。</p><img src="./../../images/我的个人电子邮件签名/原型1.0版.png" style="zoom:80%;" /><p>可以看到这个版本还是比较简单，用它做文章末尾的装饰或许还行，但作为邮件名片显然有点不够格了。</p><details>  <summary>点击展开代码</summary><pre class="line-numbers language-none"><code class="language-none">&lt;div style&#x3D;&quot;  background: linear-gradient(135deg, #B2C89E, #eef1de);  padding: 15px;   border-radius: 10px;   margin: auto;  max-width: 600px;   font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif;   color: #a3a300;   box-shadow: 0 4px 10px rgba(0,0,0,0.1);  border: 1px solid #ddd;&quot;&gt;    &lt;!-- 姓名 --&gt;    &lt;div style&#x3D;&quot;text-align: center; font-weight: bold; font-size: 1.4em; margin-bottom: 0;&quot;&gt;        Ethaniel    &lt;&#x2F;div&gt;    &lt;!-- 个性签名部分 --&gt;    &lt;div style&#x3D;&quot;margin-top: 2px; font-style: italic; font-size: 0.85em; text-align: center;&quot;&gt;        &quot;用音乐记录生活，用代码连接未来。&quot;    &lt;&#x2F;div&gt;    &lt;hr style&#x3D;&quot;border: none; height: 1px; background-color: #a3a300; margin: 10px 0;&quot;&gt;    &lt;!-- 联系方式 --&gt;    &lt;div        style&#x3D;&quot;text-align: center; margin-top: 10px; font-size: 0.9em; display: flex; align-items: center; justify-content: center;&quot;&gt;        &lt;svg xmlns&#x3D;&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 24 24&quot; fill&#x3D;&quot;none&quot; stroke&#x3D;&quot;#a3a300&quot;            stroke-width&#x3D;&quot;2&quot; stroke-linecap&#x3D;&quot;round&quot; stroke-linejoin&#x3D;&quot;round&quot; style&#x3D;&quot;vertical-align: middle;&quot;&gt;            &lt;rect x&#x3D;&quot;3&quot; y&#x3D;&quot;5&quot; width&#x3D;&quot;18&quot; height&#x3D;&quot;14&quot; rx&#x3D;&quot;2&quot; ry&#x3D;&quot;2&quot; &#x2F;&gt;            &lt;polyline points&#x3D;&quot;3,5 12,13 21,5&quot; &#x2F;&gt;        &lt;&#x2F;svg&gt;        &lt;a href&#x3D;&quot;mailto:Ethaniel@100713.xyz&quot;            style&#x3D;&quot;margin-left: 5px; color: #a3a300; text-decoration: none;&quot;&gt;Ethaniel@100713.xyz&lt;&#x2F;a&gt;    &lt;&#x2F;div&gt;    &lt;div style&#x3D;&quot;text-align: center; line-height: 1.6; margin-top: 3px;&quot;&gt;        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;music.100713.xyz&quot; style&#x3D;&quot;color: #a3a300; text-decoration: none; margin: 0 8px;&quot;&gt;音乐空间&lt;&#x2F;a&gt;        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;100713.xyz&quot; style&#x3D;&quot;color: #a3a300; text-decoration: none; margin: 0 8px;&quot;&gt;博客&lt;&#x2F;a&gt;        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;flash.100713.xyz&quot; style&#x3D;&quot;color: #a3a300; text-decoration: none; margin: 0 8px;&quot;&gt;Flash收藏站&lt;&#x2F;a&gt;    &lt;&#x2F;div&gt;    &lt;div style&#x3D;&quot;text-align: center; margin-top: 5px;&quot;&gt;        &lt;!-- GitHub --&gt;        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;github.com&#x2F;2010HCY&quot; target&#x3D;&quot;_blank&quot;            style&#x3D;&quot;margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;&quot;&gt;            &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 24 24&quot; fill&#x3D;&quot;currentColor&quot; style&#x3D;&quot;margin-right: 4px;&quot;&gt;                &lt;path                    d&#x3D;&quot;M12 0C5.372 0 0 5.372 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.82-.258.82-.577 0-.285-.011-1.041-.017-2.046-3.338.726-4.042-1.611-4.042-1.611-.546-1.387-1.333-1.757-1.333-1.757-1.089-.744.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.832 2.807 1.303 3.492.996.108-.775.418-1.305.762-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.31.468-2.381 1.236-3.222-.124-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.301 1.23.956-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.29-1.552 3.295-1.23 3.295-1.23.654 1.653.243 2.873.119 3.176.77.841 1.235 1.912 1.235 3.222 0 4.61-2.807 5.624-5.479 5.921.43.371.813 1.096.813 2.209 0 1.595-.015 2.878-.015 3.273 0 .321.219.694.825.576C20.565 21.796 24 17.298 24 12c0-6.628-5.372-12-12-12z&quot; &#x2F;&gt;            &lt;&#x2F;svg&gt;            &lt;span style&#x3D;&quot;vertical-align: middle;&quot;&gt;GitHub&lt;&#x2F;span&gt;        &lt;&#x2F;a&gt;        &lt;!-- LinuxDO --&gt;        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;linux.do&#x2F;u&#x2F;ethaniel&#x2F;summary&quot; target&#x3D;&quot;_blank&quot;            style&#x3D;&quot;margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;&quot;&gt;            &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 120 120&quot; fill&#x3D;&quot;currentColor&quot; style&#x3D;&quot;margin-right: 4px; &quot;&gt;                &lt;clipPath id&#x3D;&quot;a&quot;&gt;                    &lt;circle cx&#x3D;&quot;60&quot; cy&#x3D;&quot;60&quot; r&#x3D;&quot;47&quot; &#x2F;&gt;                &lt;&#x2F;clipPath&gt;                &lt;circle fill&#x3D;&quot;#f0f0f0&quot; cx&#x3D;&quot;60&quot; cy&#x3D;&quot;60&quot; r&#x3D;&quot;50&quot; &#x2F;&gt;                &lt;rect fill&#x3D;&quot;#1c1c1e&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;10&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;30&quot; &#x2F;&gt;                &lt;rect fill&#x3D;&quot;#f0f0f0&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;40&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;40&quot; &#x2F;&gt;                &lt;rect fill&#x3D;&quot;#ffb003&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;80&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;30&quot; &#x2F;&gt;            &lt;&#x2F;svg&gt;            &lt;span style&#x3D;&quot;vertical-align: middle;&quot;&gt;LinuxDO&lt;&#x2F;span&gt;        &lt;&#x2F;a&gt;        &lt;!-- Steam --&gt;        &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;steamcommunity.com&#x2F;id&#x2F;2010hcy&#x2F;&quot; target&#x3D;&quot;_blank&quot;            style&#x3D;&quot;margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;&quot;&gt;            &lt;svg xmlns&#x3D;&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 256 259&quot;                style&#x3D;&quot;margin-right: 4px;&quot;&gt;                &lt;path                    d&#x3D;&quot;M127.779 0C60.42 0 5.24 52.412 0 119.014l68.724 28.674a35.812 35.812 0 0 1 20.426-6.366c.682 0 1.356.019 2.02.056l30.566-44.71v-.626c0-26.903 21.69-48.796 48.353-48.796 26.662 0 48.352 21.893 48.352 48.796 0 26.902-21.69 48.804-48.352 48.804-.37 0-.73-.009-1.098-.018l-43.593 31.377c.028.582.046 1.163.046 1.735 0 20.204-16.283 36.636-36.294 36.636-17.566 0-32.263-12.658-35.584-29.412L4.41 164.654c15.223 54.313 64.673 94.132 123.369 94.132 70.818 0 128.221-57.938 128.221-129.393C256 57.93 198.597 0 127.779 0zM80.352 196.332l-15.749-6.568c2.787 5.867 7.621 10.775 14.033 13.47 13.857 5.83 29.836-.803 35.612-14.799a27.555 27.555 0 0 0 .046-21.035c-2.768-6.79-7.999-12.086-14.706-14.909-6.67-2.795-13.811-2.694-20.085-.304l16.275 6.79c10.222 4.3 15.056 16.145 10.794 26.46-4.253 10.314-15.998 15.195-26.22 10.895zm121.957-100.29c0-17.925-14.457-32.52-32.217-32.52-17.769 0-32.226 14.595-32.226 32.52 0 17.926 14.457 32.512 32.226 32.512 17.76 0 32.217-14.586 32.217-32.512zm-56.37-.055c0-13.488 10.84-24.42 24.2-24.42 13.368 0 24.208 10.932 24.208 24.42 0 13.488-10.84 24.421-24.209 24.421-13.359 0-24.2-10.933-24.2-24.42z&quot;                    fill&#x3D;&quot;#1A1918&quot; &#x2F;&gt;            &lt;&#x2F;svg&gt;            &lt;span style&#x3D;&quot;vertical-align: middle;&quot;&gt;Steam&lt;&#x2F;span&gt;        &lt;&#x2F;a&gt;    &lt;&#x2F;div&gt;&lt;&#x2F;div&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><p>效果如下（部分老旧浏览器可能出现错乱，因为博客CSS原因可能会有所不同）</p><details>  <summary>点击展开查看效果</summary><div style="  background: linear-gradient(135deg, #B2C89E, #eef1de);  padding: 15px;   border-radius: 10px;   margin: auto;  max-width: 600px;   font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;   color: #a3a300;   box-shadow: 0 4px 10px rgba(0,0,0,0.1);  border: 1px solid #ddd;">    <!-- 姓名 -->    <div style="text-align: center; font-weight: bold; font-size: 1.4em; margin-bottom: 0;">        Ethaniel    </div>    <!-- 个性签名部分 -->    <div style="margin-top: 2px; font-style: italic; font-size: 0.85em; text-align: center;">        "用音乐记录生活，用代码连接未来。"    </div>    <hr style="border: none; height: 1px; background-color: #a3a300; margin: 10px 0;">    <!-- 联系方式 -->    <div        style="text-align: center; margin-top: 10px; font-size: 0.9em; display: flex; align-items: center; justify-content: center;">        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#a3a300"            stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: middle;">            <rect x="3" y="5" width="18" height="14" rx="2" ry="2" />            <polyline points="3,5 12,13 21,5" />        </svg>        <a href="mailto:Ethaniel@100713.xyz"            style="margin-left: 5px; color: #a3a300; text-decoration: none;">Ethaniel@100713.xyz</a>    </div>    <div style="text-align: center; line-height: 1.6; margin-top: 3px;">        <a href="https://music.100713.xyz" style="color: #a3a300; text-decoration: none; margin: 0 8px;">音乐空间</a>        <a href="https://100713.xyz" style="color: #a3a300; text-decoration: none; margin: 0 8px;">博客</a>        <a href="https://flash.100713.xyz" style="color: #a3a300; text-decoration: none; margin: 0 8px;">Flash收藏站</a>    </div>    <div style="text-align: center; margin-top: 5px;">        <!-- GitHub -->        <a href="https://github.com/2010HCY" target="_blank"            style="margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;">            <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="margin-right: 4px;">                <path                    d="M12 0C5.372 0 0 5.372 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.82-.258.82-.577 0-.285-.011-1.041-.017-2.046-3.338.726-4.042-1.611-4.042-1.611-.546-1.387-1.333-1.757-1.333-1.757-1.089-.744.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.832 2.807 1.303 3.492.996.108-.775.418-1.305.762-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.31.468-2.381 1.236-3.222-.124-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.301 1.23.956-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.29-1.552 3.295-1.23 3.295-1.23.654 1.653.243 2.873.119 3.176.77.841 1.235 1.912 1.235 3.222 0 4.61-2.807 5.624-5.479 5.921.43.371.813 1.096.813 2.209 0 1.595-.015 2.878-.015 3.273 0 .321.219.694.825.576C20.565 21.796 24 17.298 24 12c0-6.628-5.372-12-12-12z" />            </svg>            <span style="vertical-align: middle;">GitHub</span>        </a>        <!-- LinuxDO -->        <a href="https://linux.do/u/ethaniel/summary" target="_blank"            style="margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;">            <svg width="20" height="20" viewBox="0 0 120 120" fill="currentColor" style="margin-right: 4px; ">                <clipPath id="a">                    <circle cx="60" cy="60" r="47" />                </clipPath>                <circle fill="#f0f0f0" cx="60" cy="60" r="50" />                <rect fill="#1c1c1e" clip-path="url(#a)" x="10" y="10" width="100" height="30" />                <rect fill="#f0f0f0" clip-path="url(#a)" x="10" y="40" width="100" height="40" />                <rect fill="#ffb003" clip-path="url(#a)" x="10" y="80" width="100" height="30" />            </svg>            <span style="vertical-align: middle;">LinuxDO</span>        </a>        <!-- Steam -->        <a href="https://steamcommunity.com/id/2010hcy/" target="_blank"            style="margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;">            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 259"                style="margin-right: 4px;">                <path                    d="M127.779 0C60.42 0 5.24 52.412 0 119.014l68.724 28.674a35.812 35.812 0 0 1 20.426-6.366c.682 0 1.356.019 2.02.056l30.566-44.71v-.626c0-26.903 21.69-48.796 48.353-48.796 26.662 0 48.352 21.893 48.352 48.796 0 26.902-21.69 48.804-48.352 48.804-.37 0-.73-.009-1.098-.018l-43.593 31.377c.028.582.046 1.163.046 1.735 0 20.204-16.283 36.636-36.294 36.636-17.566 0-32.263-12.658-35.584-29.412L4.41 164.654c15.223 54.313 64.673 94.132 123.369 94.132 70.818 0 128.221-57.938 128.221-129.393C256 57.93 198.597 0 127.779 0zM80.352 196.332l-15.749-6.568c2.787 5.867 7.621 10.775 14.033 13.47 13.857 5.83 29.836-.803 35.612-14.799a27.555 27.555 0 0 0 .046-21.035c-2.768-6.79-7.999-12.086-14.706-14.909-6.67-2.795-13.811-2.694-20.085-.304l16.275 6.79c10.222 4.3 15.056 16.145 10.794 26.46-4.253 10.314-15.998 15.195-26.22 10.895zm121.957-100.29c0-17.925-14.457-32.52-32.217-32.52-17.769 0-32.226 14.595-32.226 32.52 0 17.926 14.457 32.512 32.226 32.512 17.76 0 32.217-14.586 32.217-32.512zm-56.37-.055c0-13.488 10.84-24.42 24.2-24.42 13.368 0 24.208 10.932 24.208 24.42 0 13.488-10.84 24.421-24.209 24.421-13.359 0-24.2-10.933-24.2-24.42z"                    fill="#1A1918" />            </svg>            <span style="vertical-align: middle;">Steam</span>        </a>    </div></div></details><h4 id="1-1版"><a href="#1-1版" class="headerlink" title="1.1版"></a>1.1版</h4><img src="./../../images/我的个人电子邮件签名/原型1.1版.png" style="zoom:80%;" /><p>这个版本更好看，更完美，这个版本的布局是左右结构，左边是我的头像logo，右边是我的名字、签名、邮箱等等，这个版本就是最终的样子，接下来干的事都是做兼容性适配。</p><details>  <summary>点击展开代码</summary><pre class="line-numbers language-none"><code class="language-none">&lt;div style&#x3D;&quot;  display: flex;  align-items: center;  background: linear-gradient(135deg, #B2C89E, #eef1de);  padding: 15px;   border-radius: 10px;   margin: auto;  width: 100%;  max-width: 600px;  max-height: 165px;  font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif;   color: #a3a300;   box-shadow: 0 4px 10px rgba(0,0,0,0.1);  border: 1px solid #ddd;&quot;&gt;    &lt;!-- Logo区域 --&gt;    &lt;div style&#x3D;&quot;width: 120px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;&quot;&gt;        &lt;img style&#x3D;&quot;height: 100%; width: 120px;&quot;            src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkAQMAAABEgsN2AAAABlBMVEWhz1Hw8PBzFgw4AAAAnklEQVR4Ae3aMQqAMAwF0IIH8Ei9mkftERyd1MVOWVrBUvD98cPLHpJ0vcieKIqiKIrqUFt6UoujFitFURRFURRFURRFzaBKak+OKj&#x2F;DzlosdXyhKIqiKIqiKIqiqI9U1w4b9+WQpi2boiiKoiiKoiiKosYrF3CKoiiKoiiKoihq&#x2F;C9xUC2&#x2F;xDGFoiiKoiiKoiiKomZQvaEoiqKoH6kbFYxkM&#x2F;0L5boAAAAASUVORK5CYII&#x3D;&quot;&gt;    &lt;&#x2F;div&gt;    &lt;!-- 右侧内容部分 --&gt;    &lt;div style&#x3D;&quot;flex:1; display:flex; flex-direction: column; justify-content: center; margin-left: 15px;&quot;&gt;        &lt;div style&#x3D;&quot;text-align: left; font-weight: bold; font-size: 1.4em; margin-bottom: 0;&quot;&gt;            Ethaniel        &lt;&#x2F;div&gt;        &lt;div style&#x3D;&quot;margin-top: 0px; font-style: italic; font-size: 0.85em; text-align: left;&quot;&gt;            &quot;用音乐记录生活，用代码连接未来。&quot;        &lt;&#x2F;div&gt;        &lt;hr style&#x3D;&quot;border: none; height: 1px; background-color: #a3a300; margin: 5px 0;&quot;&gt;        &lt;div style&#x3D;&quot;text-align: left; margin-top: 2px; font-size: 0.9em; align-items: center; justify-content: center;&quot;&gt;            &lt;svg xmlns&#x3D;&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 24 24&quot; fill&#x3D;&quot;none&quot;                stroke&#x3D;&quot;#a3a300&quot; stroke-width&#x3D;&quot;2&quot; stroke-linecap&#x3D;&quot;round&quot; stroke-linejoin&#x3D;&quot;round&quot;                style&#x3D;&quot;vertical-align: middle;&quot;&gt;                &lt;rect x&#x3D;&quot;3&quot; y&#x3D;&quot;5&quot; width&#x3D;&quot;18&quot; height&#x3D;&quot;14&quot; rx&#x3D;&quot;2&quot; ry&#x3D;&quot;2&quot; &#x2F;&gt;                &lt;polyline points&#x3D;&quot;3,5 12,13 21,5&quot; &#x2F;&gt;            &lt;&#x2F;svg&gt;            &lt;a href&#x3D;&quot;mailto:Ethaniel@100713.xyz&quot;                style&#x3D;&quot;margin-left: 5px; color: #a3a300; text-decoration: none; &quot;&gt;Ethaniel@100713.xyz&lt;&#x2F;a&gt;        &lt;&#x2F;div&gt;        &lt;div style&#x3D;&quot;margin-left: 0px; text-align: left; line-height: 1.6; margin-top: 2px;&quot;&gt;            &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;music.100713.xyz&quot; style&#x3D;&quot;color: #a3a300; text-decoration: none;&quot;&gt;音乐空间&lt;&#x2F;a&gt;            &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;100713.xyz&quot; style&#x3D;&quot;color: #a3a300; text-decoration: none; margin: 0 8px;&quot;&gt;博客&lt;&#x2F;a&gt;            &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;flash.100713.xyz&quot;                style&#x3D;&quot;color: #a3a300; text-decoration: none; margin: 0 8px;&quot;&gt;Flash收藏站&lt;&#x2F;a&gt;        &lt;&#x2F;div&gt;        &lt;div style&#x3D;&quot;text-align: left; margin-top: 2px;&quot;&gt;            &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;github.com&#x2F;2010HCY&quot; target&#x3D;&quot;_blank&quot;                style&#x3D;&quot;display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;&quot;&gt;                &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 24 24&quot; fill&#x3D;&quot;currentColor&quot; style&#x3D;&quot;margin-right: 4px;&quot;&gt;                    &lt;path                        d&#x3D;&quot;M12 0C5.372 0 0 5.372 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.82-.258.82-.577 0-.285-.011-1.041-.017-2.046-3.338.726-4.042-1.611-4.042-1.611-.546-1.387-1.333-1.757-1.333-1.757-1.089-.744.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.832 2.807 1.303 3.492.996.108-.775.418-1.305.762-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.31.468-2.381 1.236-3.222-.124-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.301 1.23.956-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.29-1.552 3.295-1.23 3.295-1.23.654 1.653.243 2.873.119 3.176.77.841 1.235 1.912 1.235 3.222 0 4.61-2.807 5.624-5.479 5.921.43.371.813 1.096.813 2.209 0 1.595-.015 2.878-.015 3.273 0 .321.219.694.825.576C20.565 21.796 24 17.298 24 12c0-6.628-5.372-12-12-12z&quot; &#x2F;&gt;                &lt;&#x2F;svg&gt;                &lt;span style&#x3D;&quot;vertical-align: middle;&quot;&gt;GitHub&lt;&#x2F;span&gt;            &lt;&#x2F;a&gt;            &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;linux.do&#x2F;u&#x2F;ethaniel&#x2F;summary&quot; target&#x3D;&quot;_blank&quot;                style&#x3D;&quot;margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;&quot;&gt;                &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 120 120&quot; fill&#x3D;&quot;currentColor&quot; style&#x3D;&quot;margin-right: 4px; &quot;&gt;                    &lt;clipPath id&#x3D;&quot;a&quot;&gt;                        &lt;circle cx&#x3D;&quot;60&quot; cy&#x3D;&quot;60&quot; r&#x3D;&quot;47&quot; &#x2F;&gt;                    &lt;&#x2F;clipPath&gt;                    &lt;circle fill&#x3D;&quot;#f0f0f0&quot; cx&#x3D;&quot;60&quot; cy&#x3D;&quot;60&quot; r&#x3D;&quot;50&quot; &#x2F;&gt;                    &lt;rect fill&#x3D;&quot;#1c1c1e&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;10&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;30&quot; &#x2F;&gt;                    &lt;rect fill&#x3D;&quot;#f0f0f0&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;40&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;40&quot; &#x2F;&gt;                    &lt;rect fill&#x3D;&quot;#ffb003&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;80&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;30&quot; &#x2F;&gt;                &lt;&#x2F;svg&gt;                &lt;span style&#x3D;&quot;vertical-align: middle;&quot;&gt;LinuxDO&lt;&#x2F;span&gt;            &lt;&#x2F;a&gt;            &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;steamcommunity.com&#x2F;id&#x2F;2010hcy&#x2F;&quot; target&#x3D;&quot;_blank&quot;                style&#x3D;&quot;margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;&quot;&gt;                &lt;svg xmlns&#x3D;&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 256 259&quot;                    style&#x3D;&quot;margin-right: 4px;&quot;&gt;                    &lt;path                        d&#x3D;&quot;M127.779 0C60.42 0 5.24 52.412 0 119.014l68.724 28.674a35.812 35.812 0 0 1 20.426-6.366c.682 0 1.356.019 2.02.056l30.566-44.71v-.626c0-26.903 21.69-48.796 48.353-48.796 26.662 0 48.352 21.893 48.352 48.796 0 26.902-21.69 48.804-48.352 48.804-.37 0-.73-.009-1.098-.018l-43.593 31.377c.028.582.046 1.163.046 1.735 0 20.204-16.283 36.636-36.294 36.636-17.566 0-32.263-12.658-35.584-29.412L4.41 164.654c15.223 54.313 64.673 94.132 123.369 94.132 70.818 0 128.221-57.938 128.221-129.393C256 57.93 198.597 0 127.779 0zM80.352 196.332l-15.749-6.568c2.787 5.867 7.621 10.775 14.033 13.47 13.857 5.83 29.836-.803 35.612-14.799a27.555 27.555 0 0 0 .046-21.035c-2.768-6.79-7.999-12.086-14.706-14.909-6.67-2.795-13.811-2.694-20.085-.304l16.275 6.79c10.222 4.3 15.056 16.145 10.794 26.46-4.253 10.314-15.998 15.195-26.22 10.895zm121.957-100.29c0-17.925-14.457-32.52-32.217-32.52-17.769 0-32.226 14.595-32.226 32.52 0 17.926 14.457 32.512 32.226 32.512 17.76 0 32.217-14.586 32.217-32.512zm-56.37-.055c0-13.488 10.84-24.42 24.2-24.42 13.368 0 24.208 10.932 24.208 24.42 0 13.488-10.84 24.421-24.209 24.421-13.359 0-24.2-10.933-24.2-24.42z&quot;                        fill&#x3D;&quot;#1A1918&quot; &#x2F;&gt;                &lt;&#x2F;svg&gt;                &lt;span style&#x3D;&quot;vertical-align: middle;&quot;&gt;Steam&lt;&#x2F;span&gt;            &lt;&#x2F;a&gt;        &lt;&#x2F;div&gt;    &lt;&#x2F;div&gt;&lt;&#x2F;div&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><details>  <summary>点击展开查看效果</summary><div style="  display: flex;  align-items: center;  background: linear-gradient(135deg, #B2C89E, #eef1de);  padding: 15px;   border-radius: 10px;   margin: auto;  width: 100%;  max-width: 600px;  max-height: 165px;  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;   color: #a3a300;   box-shadow: 0 4px 10px rgba(0,0,0,0.1);  border: 1px solid #ddd;">    <!-- Logo区域 -->    <div style="width: 120px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;">        <img style="height: 100%; width: 120px;"            src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkAQMAAABEgsN2AAAABlBMVEWhz1Hw8PBzFgw4AAAAnklEQVR4Ae3aMQqAMAwF0IIH8Ei9mkftERyd1MVOWVrBUvD98cPLHpJ0vcieKIqiKIrqUFt6UoujFitFURRFURRFURRFzaBKak+OKj/DzlosdXyhKIqiKIqiKIqiqI9U1w4b9+WQpi2boiiKoiiKoiiKosYrF3CKoiiKoiiKoihq/C9xUC2/xDGFoiiKoiiKoiiKomZQvaEoiqKoH6kbFYxkM/0L5boAAAAASUVORK5CYII=">    </div>    <!-- 右侧内容部分 -->    <div style="flex:1; display:flex; flex-direction: column; justify-content: center; margin-left: 15px;">        <div style="text-align: left; font-weight: bold; font-size: 1.4em; margin-bottom: 0;">            Ethaniel        </div>        <div style="margin-top: 0px; font-style: italic; font-size: 0.85em; text-align: left;">            "用音乐记录生活，用代码连接未来。"        </div>        <hr style="border: none; height: 1px; background-color: #a3a300; margin: 5px 0;">        <div style="text-align: left; margin-top: 2px; font-size: 0.9em; align-items: center; justify-content: center;">            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"                stroke="#a3a300" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"                style="vertical-align: middle;">                <rect x="3" y="5" width="18" height="14" rx="2" ry="2" />                <polyline points="3,5 12,13 21,5" />            </svg>            <a href="mailto:Ethaniel@100713.xyz"                style="margin-left: 5px; color: #a3a300; text-decoration: none; ">Ethaniel@100713.xyz</a>        </div>        <div style="margin-left: 0px; text-align: left; line-height: 1.6; margin-top: 2px;">            <a href="https://music.100713.xyz" style="color: #a3a300; text-decoration: none;">音乐空间</a>            <a href="https://100713.xyz" style="color: #a3a300; text-decoration: none; margin: 0 8px;">博客</a>            <a href="https://flash.100713.xyz"                style="color: #a3a300; text-decoration: none; margin: 0 8px;">Flash收藏站</a>        </div>        <div style="text-align: left; margin-top: 2px;">            <a href="https://github.com/2010HCY" target="_blank"                style="display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;">                <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" style="margin-right: 4px;">                    <path                        d="M12 0C5.372 0 0 5.372 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.82-.258.82-.577 0-.285-.011-1.041-.017-2.046-3.338.726-4.042-1.611-4.042-1.611-.546-1.387-1.333-1.757-1.333-1.757-1.089-.744.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.832 2.807 1.303 3.492.996.108-.775.418-1.305.762-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.31.468-2.381 1.236-3.222-.124-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.301 1.23.956-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.29-1.552 3.295-1.23 3.295-1.23.654 1.653.243 2.873.119 3.176.77.841 1.235 1.912 1.235 3.222 0 4.61-2.807 5.624-5.479 5.921.43.371.813 1.096.813 2.209 0 1.595-.015 2.878-.015 3.273 0 .321.219.694.825.576C20.565 21.796 24 17.298 24 12c0-6.628-5.372-12-12-12z" />                </svg>                <span style="vertical-align: middle;">GitHub</span>            </a>            <a href="https://linux.do/u/ethaniel/summary" target="_blank"                style="margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;">                <svg width="20" height="20" viewBox="0 0 120 120" fill="currentColor" style="margin-right: 4px; ">                    <clipPath id="a">                        <circle cx="60" cy="60" r="47" />                    </clipPath>                    <circle fill="#f0f0f0" cx="60" cy="60" r="50" />                    <rect fill="#1c1c1e" clip-path="url(#a)" x="10" y="10" width="100" height="30" />                    <rect fill="#f0f0f0" clip-path="url(#a)" x="10" y="40" width="100" height="40" />                    <rect fill="#ffb003" clip-path="url(#a)" x="10" y="80" width="100" height="30" />                </svg>                <span style="vertical-align: middle;">LinuxDO</span>            </a>            <a href="https://steamcommunity.com/id/2010hcy/" target="_blank"                style="margin: 0 8px; display:inline-flex; align-items:center; text-decoration: none; color: #a3a300;">                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 259"                    style="margin-right: 4px;">                    <path                        d="M127.779 0C60.42 0 5.24 52.412 0 119.014l68.724 28.674a35.812 35.812 0 0 1 20.426-6.366c.682 0 1.356.019 2.02.056l30.566-44.71v-.626c0-26.903 21.69-48.796 48.353-48.796 26.662 0 48.352 21.893 48.352 48.796 0 26.902-21.69 48.804-48.352 48.804-.37 0-.73-.009-1.098-.018l-43.593 31.377c.028.582.046 1.163.046 1.735 0 20.204-16.283 36.636-36.294 36.636-17.566 0-32.263-12.658-35.584-29.412L4.41 164.654c15.223 54.313 64.673 94.132 123.369 94.132 70.818 0 128.221-57.938 128.221-129.393C256 57.93 198.597 0 127.779 0zM80.352 196.332l-15.749-6.568c2.787 5.867 7.621 10.775 14.033 13.47 13.857 5.83 29.836-.803 35.612-14.799a27.555 27.555 0 0 0 .046-21.035c-2.768-6.79-7.999-12.086-14.706-14.909-6.67-2.795-13.811-2.694-20.085-.304l16.275 6.79c10.222 4.3 15.056 16.145 10.794 26.46-4.253 10.314-15.998 15.195-26.22 10.895zm121.957-100.29c0-17.925-14.457-32.52-32.217-32.52-17.769 0-32.226 14.595-32.226 32.52 0 17.926 14.457 32.512 32.226 32.512 17.76 0 32.217-14.586 32.217-32.512zm-56.37-.055c0-13.488 10.84-24.42 24.2-24.42 13.368 0 24.208 10.932 24.208 24.42 0 13.488-10.84 24.421-24.209 24.421-13.359 0-24.2-10.933-24.2-24.42z"                        fill="#1A1918" />                </svg>                <span style="vertical-align: middle;">Steam</span>            </a>        </div>    </div></div></details>（部分老旧浏览器可能出现错乱，因为博客CSS原因可能会有所不同）<h3 id="为了兼容性转表格布局"><a href="#为了兼容性转表格布局" class="headerlink" title="为了兼容性转表格布局"></a>为了兼容性转表格布局</h3><p>为什么我要使用传统的表格布局？原因是踏马的WebEmail渲染现代的 Flexbox 布局会鬼畜，鬼畜效果如下</p><img src="./../../images/我的个人电子邮件签名/鬼畜.png" style="zoom:80%;" /><p>为此我为了让我的好友能够在浏览器里查看我精心设计的签名，我不得不转为传统表格布局，源码：</p><details>  <summary>点击展开代码</summary><pre class="line-numbers language-none"><code class="language-none">&lt;table cellpadding&#x3D;&quot;0&quot; cellspacing&#x3D;&quot;0&quot; width&#x3D;&quot;100%&quot;    style&#x3D;&quot;max-width:600px; margin:auto; border:1px solid #ddd; border-radius:10px; box-shadow:0 4px 10px rgba(0,0,0,0.1); background:linear-gradient(135deg, #B2C89E, #eef1de); font-family:&#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; color:#a3a300;&quot;&gt;    &lt;tr&gt;        &lt;td style&#x3D;&quot;width: 120px; padding:15px; vertical-align: middle; text-align: center;&quot;&gt;            &lt;img src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkAQMAAABEgsN2AAAABlBMVEWhz1Hw8PBzFgw4AAAAnklEQVR4Ae3aMQqAMAwF0IIH8Ei9mkftERyd1MVOWVrBUvD98cPLHpJ0vcieKIqiKIrqUFt6UoujFitFURRFURRFURRFzaBKak+OKj&#x2F;DzlosdXyhKIqiKIqiKIqiqI9U1w4b9+WQpi2boiiKoiiKoiiKosYrF3CKoiiKoiiKoihq&#x2F;C9xUC2&#x2F;xDGFoiiKoiiKoiiKomZQvaEoiqKoH6kbFYxkM&#x2F;0L5boAAAAASUVORK5CYII&#x3D;&quot;                alt&#x3D;&quot;Logo&quot; style&#x3D;&quot;display:block; width:120px; height:auto;&quot;&gt;        &lt;&#x2F;td&gt;        &lt;td style&#x3D;&quot;padding:15px; vertical-align: top;&quot;&gt;            &lt;h2 style&#x3D;&quot;margin:0; font-size:1.4em; font-weight:bold;&quot;&gt;Ethaniel&lt;&#x2F;h2&gt;            &lt;p style&#x3D;&quot;margin:0px 0 3px 0; font-style:italic; font-size:0.85em;&quot;&gt;&quot;用音乐记录生活，用代码连接未来。&quot;&lt;&#x2F;p&gt;            &lt;hr style&#x3D;&quot;border:none; height:1px; background-color:#a3a300; margin:5px 0;&quot;&gt;            &lt;p style&#x3D;&quot;margin:0; font-size:0.9em; line-height:1.6;&quot;&gt;                &lt;svg xmlns&#x3D;&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 24 24&quot; fill&#x3D;&quot;none&quot;                    stroke&#x3D;&quot;#a3a300&quot; stroke-width&#x3D;&quot;2&quot; stroke-linecap&#x3D;&quot;round&quot; stroke-linejoin&#x3D;&quot;round&quot;                    style&#x3D;&quot;vertical-align: middle;&quot;&gt;                    &lt;rect x&#x3D;&quot;3&quot; y&#x3D;&quot;5&quot; width&#x3D;&quot;18&quot; height&#x3D;&quot;14&quot; rx&#x3D;&quot;2&quot; ry&#x3D;&quot;2&quot; &#x2F;&gt;                    &lt;polyline points&#x3D;&quot;3,5 12,13 21,5&quot; &#x2F;&gt;                &lt;&#x2F;svg&gt;                &lt;a href&#x3D;&quot;mailto:Ethaniel@100713.xyz&quot;                    style&#x3D;&quot;margin-left:5px; color:#a3a300; text-decoration:none;&quot;&gt;Ethaniel@100713.xyz&lt;&#x2F;a&gt;            &lt;&#x2F;p&gt;            &lt;div style&#x3D;&quot;margin-top:2px; font-size:0.9em; line-height:1.6;&quot;&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;music.100713.xyz&quot;                    style&#x3D;&quot;color:#a3a300; text-decoration:none; margin-right:8px;&quot;&gt;音乐空间&lt;&#x2F;a&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;100713.xyz&quot; style&#x3D;&quot;color:#a3a300; text-decoration:none; margin-right:8px;&quot;&gt;博客&lt;&#x2F;a&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;flash.100713.xyz&quot; style&#x3D;&quot;color:#a3a300; text-decoration:none;&quot;&gt;Flash收藏站&lt;&#x2F;a&gt;            &lt;&#x2F;div&gt;            &lt;div style&#x3D;&quot;margin-top:2px;&quot;&gt;                &lt;!-- GitHub --&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;github.com&#x2F;2010HCY&quot; target&#x3D;&quot;_blank&quot;                    style&#x3D;&quot;margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;&quot;&gt;                    &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 24 24&quot; fill&#x3D;&quot;currentColor&quot; style&#x3D;&quot;margin-right:4px;&quot;&gt;                        &lt;path                            d&#x3D;&quot;M12 0C5.372 0 0 5.372 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.82-.258.82-.577 0-.285-.011-1.041-.017-2.046-3.338.726-4.042-1.611-4.042-1.611-.546-1.387-1.333-1.757-1.333-1.757-1.089-.744.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.832 2.807 1.303 3.492.996.108-.775.418-1.305.762-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.31.468-2.381 1.236-3.222-.124-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.301 1.23.956-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.29-1.552 3.295-1.23 3.295-1.23.654 1.653.243 2.873.119 3.176.77.841 1.235 1.912 1.235 3.222 0 4.61-2.807 5.624-5.479 5.921.43.371.813 1.096.813 2.209 0 1.595-.015 2.878-.015 3.273 0 .321.219.694.825.576C20.565 21.796 24 17.298 24 12c0-6.628-5.372-12-12-12z&quot; &#x2F;&gt;                    &lt;&#x2F;svg&gt;                    &lt;span&gt;GitHub&lt;&#x2F;span&gt;                &lt;&#x2F;a&gt;                &lt;!-- LinuxDO --&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;linux.do&#x2F;u&#x2F;ethaniel&#x2F;summary&quot; target&#x3D;&quot;_blank&quot;                    style&#x3D;&quot;margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;&quot;&gt;                    &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 120 120&quot; fill&#x3D;&quot;currentColor&quot; style&#x3D;&quot;margin-right:4px;&quot;&gt;                        &lt;clipPath id&#x3D;&quot;a&quot;&gt;                            &lt;circle cx&#x3D;&quot;60&quot; cy&#x3D;&quot;60&quot; r&#x3D;&quot;47&quot; &#x2F;&gt;                        &lt;&#x2F;clipPath&gt;                        &lt;circle fill&#x3D;&quot;#f0f0f0&quot; cx&#x3D;&quot;60&quot; cy&#x3D;&quot;60&quot; r&#x3D;&quot;50&quot; &#x2F;&gt;                        &lt;rect fill&#x3D;&quot;#1c1c1e&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;10&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;30&quot; &#x2F;&gt;                        &lt;rect fill&#x3D;&quot;#f0f0f0&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;40&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;40&quot; &#x2F;&gt;                        &lt;rect fill&#x3D;&quot;#ffb003&quot; clip-path&#x3D;&quot;url(#a)&quot; x&#x3D;&quot;10&quot; y&#x3D;&quot;80&quot; width&#x3D;&quot;100&quot; height&#x3D;&quot;30&quot; &#x2F;&gt;                    &lt;&#x2F;svg&gt;                    &lt;span&gt;LinuxDO&lt;&#x2F;span&gt;                &lt;&#x2F;a&gt;                &lt;!-- Steam --&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;steamcommunity.com&#x2F;id&#x2F;2010hcy&#x2F;&quot; target&#x3D;&quot;_blank&quot;                    style&#x3D;&quot;margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;&quot;&gt;                    &lt;svg width&#x3D;&quot;20&quot; height&#x3D;&quot;20&quot; viewBox&#x3D;&quot;0 0 256 259&quot; style&#x3D;&quot;margin-right:4px;&quot;&gt;                        &lt;path                            d&#x3D;&quot;M127.779 0C60.42 0 5.24 52.412 0 119.014l68.724 28.674a35.812 35.812 0 0 1 20.426-6.366c.682 0 1.356.019 2.02.056l30.566-44.71v-.626c0-26.903 21.69-48.796 48.353-48.796 26.662 0 48.352 21.893 48.352 48.796 0 26.902-21.69 48.804-48.352 48.804-.37 0-.73-.009-1.098-.018l-43.593 31.377c.028.582.046 1.163.046 1.735 0 20.204-16.283 36.636-36.294 36.636-17.566 0-32.263-12.658-35.584-29.412L4.41 164.654c15.223 54.313 64.673 94.132 123.369 94.132 70.818 0 128.221-57.938 128.221-129.393C256 57.93 198.597 0 127.779 0zM80.352 196.332l-15.749-6.568c2.787 5.867 7.621 10.775 14.033 13.47 13.857 5.83 29.836-.803 35.612-14.799a27.555 27.555 0 0 0 .046-21.035c-2.768-6.79-7.999-12.086-14.706-14.909-6.67-2.795-13.811-2.694-20.085-.304l16.275 6.79c10.222 4.3 15.056 16.145 10.794 26.46-4.253 10.314-15.998 15.195-26.22 10.895zm121.957-100.29c0-17.925-14.457-32.52-32.217-32.52-17.769 0-32.226 14.595-32.226 32.52 0 17.926 14.457 32.512 32.226 32.512 17.76 0 32.217-14.586 32.217-32.512zm-56.37-.055c0-13.488 10.84-24.42 24.2-24.42 13.368 0 24.208 10.932 24.208 24.42 0 13.488-10.84 24.421-24.209 24.421-13.359 0-24.2-10.933-24.2-24.42z&quot;                            fill&#x3D;&quot;#1A1918&quot; &#x2F;&gt;                    &lt;&#x2F;svg&gt;                    &lt;span&gt;Steam&lt;&#x2F;span&gt;                &lt;&#x2F;a&gt;            &lt;&#x2F;div&gt;        &lt;&#x2F;td&gt;    &lt;&#x2F;tr&gt;&lt;&#x2F;table&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><p>但问题它又又又踏马来了，Gmail、QQ邮箱不支持SVG渲染！为此我不得不将其转换成Base64编码插入，但…出了点玄学问题，我直接SVG转Base64不能显示，但SVG转PNG转Base64就可以，嗯？我还得多转一遍才能用？下面是折腾好的源码：</p><details>  <summary>点击展开代码</summary><pre class="line-numbers language-none"><code class="language-none">&lt;table cellpadding&#x3D;&quot;0&quot; cellspacing&#x3D;&quot;0&quot; width&#x3D;&quot;100%&quot;    style&#x3D;&quot;max-width:600px; margin:auto; border:1px solid #ddd; border-radius:10px; box-shadow:0 4px 10px rgba(0,0,0,0.1); background:linear-gradient(135deg, #B2C89E, #eef1de); font-family:&#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; color:#a3a300;&quot;&gt;    &lt;tr&gt;        &lt;td style&#x3D;&quot;width: 120px; padding:15px; margin-right:0px; vertical-align: middle; text-align: center;&quot;&gt;            &lt;img src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkAQMAAABEgsN2AAAABlBMVEWhz1Hw8PBzFgw4AAAAnklEQVR4Ae3aMQqAMAwF0IIH8Ei9mkftERyd1MVOWVrBUvD98cPLHpJ0vcieKIqiKIrqUFt6UoujFitFURRFURRFURRFzaBKak+OKj&#x2F;DzlosdXyhKIqiKIqiKIqiqI9U1w4b9+WQpi2boiiKoiiKoiiKosYrF3CKoiiKoiiKoihq&#x2F;C9xUC2&#x2F;xDGFoiiKoiiKoiiKomZQvaEoiqKoH6kbFYxkM&#x2F;0L5boAAAAASUVORK5CYII&#x3D;&quot;                alt&#x3D;&quot;Logo&quot; style&#x3D;&quot;display:block; width:120px; height:auto;&quot;&gt;        &lt;&#x2F;td&gt;        &lt;td style&#x3D;&quot;padding:15px; margin-left: 15px; vertical-align: top;&quot;&gt;            &lt;h2 style&#x3D;&quot;margin:0; font-size:1.4em; font-weight:bold;&quot;&gt;Ethaniel&lt;&#x2F;h2&gt;            &lt;p style&#x3D;&quot;margin:0px 0 10px 0; font-style:italic; font-size:0.85em;&quot;&gt;&quot;用音乐记录生活，用代码连接未来。&quot;&lt;&#x2F;p&gt;            &lt;hr style&#x3D;&quot;border:none; height:1px; background-color:#a3a300; margin:5px 0;&quot;&gt;            &lt;p style&#x3D;&quot;margin:0; font-size:0.9em; line-height:1.6;&quot;&gt;                &lt;img src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAABfVBMVEUAAAAAAAD&#x2F;&#x2F;wCAgAC&#x2F;vwCZmQCqqgCiogCdnQCkpACqqgCfnwClpQChoQCmpgCengCqqgCiogCfnwCjowCnpwCnpwChoQCfnwCiogCgoACjowClpQCkpACmpgCiogCkpAChoQClpQClpQCkpACjowClpQCkpAChoQCkpACjowCkpACjowChoQCkpACiogCiogClpQCiogCjowCjowCkpACiogCkpACkpACjowCjowCkpACjowCiogCjowCkpACjowCiogCkpACjowCjowCkpACjowCiogCiogCjowCjowCiogCjowCiogCjowCjowCjowCjowCjowCkpACjowCkpACjowCjowCiogCkpACiogCjowCkpACjowCiogCkpACjowCiogCjowCjowCjowCjowCjowCjowCjowCjowCjowCkpACjowCiogCjowCjowCjowCjowCjowCjowCjowCjowCiogCjowCjowCjowCjowCjowCjowCjowCjowCjowDzQ23hAAAAfnRSTlMAAQECBAUJCw0ODxARExQVFRYYGRodHiAhIyQlKissLS4wNjhAQUNESUtMTk9RUlVVWFlbX2BiZWlscHd8fX6AgYGCiImOj5KTlpqcnZ6go6Snqqutrq+wsLO0u7y+vsfJzs&#x2F;R0tPV2tve3+Hi4+Tl5ujp6uzt7&#x2F;Hy9vn6&#x2F;f45g3pQAAAECUlEQVR42uzBgQAAAACAoP2pF6kCAAAAAACYnbtQblwJojB8lpmZmTfMzMzMzHw53M9+mZTpckseadpb871A6rct6YTG+4Y9yq5o6el3oqelIvsRrPjSsUGObXR8QZpu1m2TCtt1NxHd6doDUuOg9jQi+rJCqqx8QSQNpE4Dwjs7SAoNnkVIF6ZJpekLCGeClJpAKD2kVg9CqCDFKiD2mlR7DalpUm0aQoWkXCFklki5JYjkkHo5kBgn9cYhcJsywG2kVkwZoNjBQ93Z432FMsCKYPaSxNbHtzH5uEUSF5DKcxKZuYRYXJwlkedI5QPJLFxDDK4tkswHpJJFASPcx&#x2F;QurLu3SmbDFJAV&#x2F;rmeW3pMRhsPYdnj78jouCSXf7bLQ1BwREY&#x2F;vIRVL34io6M82AnB10My2n0Di17vkdHhZ9gKwft9Mtp&#x2F;D2vecV&#x2F;jHeyF4M0u82p9hSWfmXd97zVshuAl9&#x2F;ktgBV53HX4AnZD8GSHuaOUwoIy5s64+QC2Q3CfG2HVSFsNma3egf0QXFsgs2ak53Q7mS1eQxwhuDRDZp1nkIYzfWQ2exHxhOD8JJmNnkNk58bIbOo84grBuVEymzyPiM5PkdnYOcQXgjO9&#x2F;Ky3O9v7ziDOEJxuszrrb3GzvfU04g0BaizO+nvr&#x2F;C099hCU87Pe2mxHEiHRZ718ticTEn3Wi2d7QiHRZ710ticVEn3WC2d7YiHhZ718ticbEn7Wy2d7siG4v0ZmVUiplp&#x2F;tyYfgFj&#x2F;ro892FyHyWS+f7W5C5LNePtvdhMhnvXy2uwmRz3rJbHcZIp71gtnuNgSo5Wd9qNnuPATlxM96+WxXEIJibm48lc92FSHsrP&#x2F;ljXy2uw+RznrBbHcfIpj1gtnuPkQw6wWz3X2IYNYLZrv7EMGsl892BSG4wc36phYym7sOjSH8rOdnu84Qftbzs11nCD&#x2F;r+dmuMISZ9YzuM1Aawsx6RiugOwSoJ4FK6A9hZz0&#x2F;25WGsLOen+1KQ9hZz892pSHsrOdnu9IQdtbzs11pCF79TEY&#x2F;voD+EH7W87Ndewgz6&#x2F;nZrjgEt5blP21XHYIrM&#x2F;xs1x&#x2F;Cz&#x2F;qp89Afwumif3QBGRyCj9&#x2F;TH3Y+IrNDcDW&#x2F;dmigNu8y1IbY50N8iA&#x2F;xIT7Eh&#x2F;gQH+JDfIgP8SE+xIf4EB&#x2F;iQ3yID8migCIoUBT+8IoPFNAIBRrDHyfynALmocB8+ANeLlDQJzj3iYIuRDgEaf4UHDt14g1ZiXQsVR8c66OgnmgHhU08g0PPJuiE4qhHt3V+ugUnbn3q&#x2F;LW9OyACAASAENbBwGa3gAH+uC0I3I&#x2F;Tj+kV84aB4GQgARqIsgYyuYFwcSAlHYh7Z3LrlQB+ZElQmURUth1GKkNrG7MhAAAAAAAAxj0l70sLmc&#x2F;I9gAAAABJRU5ErkJggg&#x3D;&#x3D;&quot; alt&#x3D;&quot;Mail&quot; style&#x3D;&quot;width:20px; height:20px; vertical-align: middle;&quot;&gt;                &lt;a href&#x3D;&quot;mailto:Ethaniel@100713.xyz&quot;                    style&#x3D;&quot;margin-left:5px; color:#a3a300; text-decoration:none;&quot;&gt;Ethaniel@100713.xyz&lt;&#x2F;a&gt;            &lt;&#x2F;p&gt;            &lt;div style&#x3D;&quot;margin-top:2px; font-size:0.9em; line-height:1.6;&quot;&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;music.100713.xyz&quot;                    style&#x3D;&quot;color:#a3a300; text-decoration:none; margin-right:8px;&quot;&gt;音乐空间&lt;&#x2F;a&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;100713.xyz&quot; style&#x3D;&quot;color:#a3a300; text-decoration:none; margin-right:8px;&quot;&gt;博客&lt;&#x2F;a&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;flash.100713.xyz&quot; style&#x3D;&quot;color:#a3a300; text-decoration:none;&quot;&gt;Flash收藏站&lt;&#x2F;a&gt;            &lt;&#x2F;div&gt;            &lt;div style&#x3D;&quot;margin-top:2px;&quot;&gt;                &lt;!-- GitHub --&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;github.com&#x2F;2010HCY&quot; target&#x3D;&quot;_blank&quot;                    style&#x3D;&quot;margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;&quot;&gt;                    &lt;img src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAgCAYAAACcuBHKAAADK0lEQVR42rXWA5TkTBRA4Zf8tm3bts21bdu2bdu2bdu2bb69NcypxuTMZm+fr6VUBHn5jff8ehIp0BxzsAdncRmnsQMzUA+&#x2F;4iGIH36+9BwqYSlOQX04hpnI99Ib7z0CiUZefu29SG7nT7JgGTSZLmMmWILv3gIJJ9qib4+z0ACcRGM84nd1PI+x0KChd7htxTF3nh5Fe6TAjaqzilOSx1MSl3cDuYMBtYZ6HMBU7Erm9rAV03HUer&#x2F;qq69+cBPE8C6WnDgP9ejw8uvv3c3jm6iIjVBcwEFswzpsxyFchGIZCuBl3IfBUI8j+N3eJp7GUqilEMTjdeTHf3gHz+BxPIf3kQp58DzEoyrUwhJ+9yHv3lEOV6EeV5EdEoASUMtFZIa4IvIk0sKBNwfPIoieh90tSI+7zSA+x2uwu4TDCKKDuAq7z&#x2F;GRGcSPuAt2Y9AbQdQBM2D3IL4z62su1HIe&#x2F;0MClBOXoZZRZkk8B7tjWIcgW4VTsHvBDOIB2J0HAu0MLsPugZu5M+xux20IsrsiTOtmsySOw+4OPIAgeyjCjB03gzgCu3vwLoLsPdwBu8NmEFth5+J3EecOCab78RvCtdlMbB4Udr&#x2F;y9r8STGnwZYQD4lzX3OEY7O5GdXHkK7m+&#x2F;kSVCNvDASwyB5F7MAoaZyMW4QwU21CO643XeLztlTffFx&#x2F;u4Ptv8&#x2F;1q2Bv1Suv1d28zgzAy4gIUA&#x2F;E6MmEfFFexPW6w1fEcJIyXUAfjsBsaxWn8CeGH7xv3e64rL2P4y2++9xiPueOXiMciPAEJ4zmsgvrQD3faF7rf4yA0TsVX3nj&#x2F;Zh7LYjfO4DAqQKJoCU3CDnwEMVxHVOLMFJGGuABTNhV9Me69X&#x2F;E&#x2F;fhGVlhK9&#x2F;YjWadTCEonLVceROFcZSSve6wjTq2iOr8RxtqlenYRVKnpRoncZkbqI2qLSDQIgzOJ8AK1wEYrDmIKBGIV&#x2F;IFGUhYZxFtVeevO92yFekf7odpTFfqglbzIGsROF2cZugdhc94orYZxHIxFJhaGe6wAFfHccffA&#x2F;WqvoJdg3lsSb7ybl3rhL+fE4gf8gUeTGKQzH38zpnZBorgEeIoJDUN3opQAAAABJRU5ErkJggg&#x3D;&#x3D;&quot; alt&#x3D;&quot;GitHub&quot; style&#x3D;&quot;width:20px; height:20px; margin-right:4px; vertical-align: middle;&quot;&gt;                    &lt;span&gt;GitHub&lt;&#x2F;span&gt;                &lt;&#x2F;a&gt;                &lt;!-- LinuxDO --&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;linux.do&#x2F;u&#x2F;ethaniel&#x2F;summary&quot; target&#x3D;&quot;_blank&quot;                    style&#x3D;&quot;margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;&quot;&gt;                    &lt;img src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADQUlEQVR42sWXz04TURTGryhFJCaE&#x2F;yb8EdA38BFMxMRNN&#x2F;gE6tYF4tIHwAVv0AS1GopGZGc0VLbs3BIkuiCxtE4VSplOO5&#x2F;3Z7FeJmCqaWmTL9w595zvd+bM3ALmxv1b5jhJOmMVi8TiVgmrtO&#x2F;75VKpJMSaGHvkRGpieJ3EOQne7qy7rZKAVlZWNDv7UFNTN9XfP2Q1KMSaGHvkkEsNta5nXQ3QsbOeD4JAc3OPNTIyJmNMYOV3dV0sDwwMaXDwkhBrYuyRQy411OIR9XYVhXfwMwwrPZK2FxdT6u3tF8Z9fQPh+PikJiauaGxsXEBcEWOPHHKpoRYPvCqVSo&#x2F;LQMhEu7PjG6ZiZuYB4CIjxhjI8PBoXSKXGmrxwIsP3i4LHXk+dEni9PRtCg+4m9HRy5j+l6jFAy88+cBwmcZ9QxkV3VIwOXkVk4YILzzxhuGetNo4eFlSqZQYGQWMsZHCE+9UakmwYMKuHbVMJkOCVZs6O7vU0dHZUOGJNwxYMGvvQBCUkltbW5xhf21tTauraaXTjRWeeMOABbPWgOd5KhaLkhSq+Z8QFkzYJp&#x2F;Px60IBNlsVqchWDBh00Di8MK3UrMVYSVoIH14UT4luMtKGxfcApUNi1aq9Q20&#x2F;hG0&#x2F;iVs&#x2F;TGMVy+8IO9ldSrKO19EfB3agPI&#x2F;ivL2FVqpyQphwfzzu2C3nPy+s6m9zZS&#x2F;++Wddj+&#x2F;bYqst2Us+bBg1hrIVdSd&#x2F;5aRnhvphdVic4Q&#x2F;ggUTtvkqxVhkpfnCxhNpwRT15oL0+lxDhSfeMGDBhG28&#x2F;dqfZExi21+&#x2F;Kz01B9UmzjZEeOGJNwxYCDYL7r79V2BPPblACj5cP2yiU1putyZt&#x2F;wylhlo88MITbxgukwYQgVj1hQyGSfTX74iR6ZVRdRrtdcPJpYZaPPDCE2+XdaQBtCN1&#x2F;J4EoypsLEgvjfTM+NYs1PJ5VacSU&#x2F;QZE2OPHHKpoRYPvPB0Gcc2EO0uJ83b46Lix0fcFY0ESlrjlClzd66IsUcOudRQi0fU+68NuM8H5UJ1Z6WkHZ&#x2F;2Pi3JX7+n8vtrijZAjD1yyKWG2qhnXQ0gr6AzHJPII4rbcSa8faUtpAwIsSbGHjluDR5e4eR&#x2F;z38CRCwmJc9le7gAAAAASUVORK5CYII&#x3D;&quot; alt&#x3D;&quot;LinuxDO&quot; style&#x3D;&quot;width:20px; height:20px; margin-right:4px; vertical-align: middle;&quot;&gt;                    &lt;span&gt;LinuxDO&lt;&#x2F;span&gt;                &lt;&#x2F;a&gt;                &lt;!-- Steam --&gt;                &lt;a href&#x3D;&quot;https:&#x2F;&#x2F;steamcommunity.com&#x2F;id&#x2F;2010hcy&#x2F;&quot; target&#x3D;&quot;_blank&quot;                    style&#x3D;&quot;margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;&quot;&gt;                    &lt;img src&#x3D;&quot;data:image&#x2F;png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAADTUlEQVR42qXXA4zsXADF8U6389m2bdu2+Wzbtm3btm3btm3r37zT5KbD7p7ktzs+t7cOWVHywP33Wb48ji&#x2F;xFV7DA7gRbk5gJxZjAiZhq2Vk1+49lj+hBIXPIAv+wBMII17OYQMGoCs2xRpAKEbpdSosgSeRmqxFXfTEOX95SpTSu1Af5fQ4tbkL3+EOzMUZWDfffJN1&#x2F;MQJivVEuRutkEmDSmscvKttYorKrxYbS3s9GiAjgmYbRmAQpuMA7oS3RK&#x2F;iBm14F1lQRqSQ7MiCILmAbqiHtTDzBiriN7jJhSXoBCtF0&#x2F;w8WuIOBEkbFMJJpNOPf6tdbRpG42n9voPn9Nphr7gMfkCQLENuhNBCPzodB&#x2F;E33sIorMAvuEUb3FFMtvnzrKYjaIZhl5byIrJpGtvq8WMawHJMhJe&#x2F;8JitqXkMQXJZP+jgffTQdHs5gIH43JgdL0&#x2F;hC7f461TsOpv1Y2GVn4Y&#x2F;p3AN3JyHlzC+tnXsDZJzqIM1KlwbZftw8B2WGEtp5jW3+KymLtn0RXd4aYf3UBVv4l3Ux93ogQfwBcw86G7VozXqm3BPghPBKuTDPng5iPn4GH&#x2F;jE+zQQPaiAn6HmXDIOHLdjA&#x2F;wL77BgzBzUltrP8TKzbiA07gdRVEC18PMJa&#x2F;YjLeL&#x2F;Yo&#x2F;tGGMw2KMwCXEyuN4AS&#x2F;q++&#x2F;Bhj&#x2F;HVBwzd6joTg3iGAZrqs04+AuV8LSex8tqO8E6PYQj2IlpeAnNcC+83I8G6AgdGhNmsbtxuftxZhzFgRhTeUHl4&#x2F;Et7sZcfIa2+BvhALtjU7fY0dklJ15T8b4YB4VLuAcva6B9tZRBsgY1bO1K&#x2F;XEH&#x2F;kFvjMKHcMTMS9pdXsF9CBR1bfPOTtvxA25HCh5U4VLkMk7qWfAuWiM3nkGQrEZpHPGKD2ruv1Wxm6ewCQv0+te4gCb4DtkDHuPPoCymmBcCblbgHrwFN9fgU9jaqGbhkArz6P0gaa5BX4QV8l1l3olmSBdlSzyL6+EgaDqhGI56l7j+q8zTmoqb8Jo3lfp&#x2F;LWwEyRk0QzmVEl1l6oG&#x2F;fKI2uGfTcG29UhtSU5wyLuiTuoV5ApnwF55OYr2exVr0Q49491DJ3rQ9gs+Mm7aHfDdtO7AIEzAFO&#x2F;2F&#x2F;lwBKuXlrrIH4NIAAAAASUVORK5CYII&#x3D;&quot; alt&#x3D;&quot;Steam&quot; style&#x3D;&quot;width:20px; height:20px; margin-right:4px; vertical-align: middle;&quot;&gt;                    &lt;span&gt;Steam&lt;&#x2F;span&gt;                &lt;&#x2F;a&gt;            &lt;&#x2F;div&gt;        &lt;&#x2F;td&gt;    &lt;&#x2F;tr&gt;&lt;&#x2F;table&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><p>Base64编码有点长，我个人建议把图片放一个好一点的图床里，我这边为了稳定性才选择内嵌使用Base64，接下来就是最后的效果：</p><details>  <summary>点击展开查看效果</summary><table cellpadding="0" cellspacing="0" width="100%"    style="max-width:600px; margin:auto; border:1px solid #ddd; border-radius:10px; box-shadow:0 4px 10px rgba(0,0,0,0.1); background:linear-gradient(135deg, #B2C89E, #eef1de); font-family:'Helvetica Neue', Helvetica, Arial, sans-serif; color:#a3a300;">    <tr>        <td style="width: 120px; padding:15px; margin-right:0px; vertical-align: middle; text-align: center;">            <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGkAQMAAABEgsN2AAAABlBMVEWhz1Hw8PBzFgw4AAAAnklEQVR4Ae3aMQqAMAwF0IIH8Ei9mkftERyd1MVOWVrBUvD98cPLHpJ0vcieKIqiKIrqUFt6UoujFitFURRFURRFURRFzaBKak+OKj/DzlosdXyhKIqiKIqiKIqiqI9U1w4b9+WQpi2boiiKoiiKoiiKosYrF3CKoiiKoiiKoihq/C9xUC2/xDGFoiiKoiiKoiiKomZQvaEoiqKoH6kbFYxkM/0L5boAAAAASUVORK5CYII="                style="display:block; width:120px; height:auto;">        </td>        <td style="padding:15px; margin-left: 15px; vertical-align: top;">            <h2 style="margin:0; font-size:1.4em; font-weight:bold;">Ethaniel</h2>            <p style="margin:0px 0 10px 0; font-style:italic; font-size:0.85em;">"用音乐记录生活，用代码连接未来。"</p>            <hr style="border:none; height:1px; background-color:#a3a300; margin:5px 0;">            <p style="margin:0; font-size:0.9em; line-height:1.6;">                <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAABfVBMVEUAAAAAAAD//wCAgAC/vwCZmQCqqgCiogCdnQCkpACqqgCfnwClpQChoQCmpgCengCqqgCiogCfnwCjowCnpwCnpwChoQCfnwCiogCgoACjowClpQCkpACmpgCiogCkpAChoQClpQClpQCkpACjowClpQCkpAChoQCkpACjowCkpACjowChoQCkpACiogCiogClpQCiogCjowCjowCkpACiogCkpACkpACjowCjowCkpACjowCiogCjowCkpACjowCiogCkpACjowCjowCkpACjowCiogCiogCjowCjowCiogCjowCiogCjowCjowCjowCjowCjowCkpACjowCkpACjowCjowCiogCkpACiogCjowCkpACjowCiogCkpACjowCiogCjowCjowCjowCjowCjowCjowCjowCjowCjowCkpACjowCiogCjowCjowCjowCjowCjowCjowCjowCjowCiogCjowCjowCjowCjowCjowCjowCjowCjowCjowDzQ23hAAAAfnRSTlMAAQECBAUJCw0ODxARExQVFRYYGRodHiAhIyQlKissLS4wNjhAQUNESUtMTk9RUlVVWFlbX2BiZWlscHd8fX6AgYGCiImOj5KTlpqcnZ6go6Snqqutrq+wsLO0u7y+vsfJzs/R0tPV2tve3+Hi4+Tl5ujp6uzt7/Hy9vn6/f45g3pQAAAECUlEQVR42uzBgQAAAACAoP2pF6kCAAAAAACYnbtQblwJojB8lpmZmTfMzMzMzHw53M9+mZTpckseadpb871A6rct6YTG+4Y9yq5o6el3oqelIvsRrPjSsUGObXR8QZpu1m2TCtt1NxHd6doDUuOg9jQi+rJCqqx8QSQNpE4Dwjs7SAoNnkVIF6ZJpekLCGeClJpAKD2kVg9CqCDFKiD2mlR7DalpUm0aQoWkXCFklki5JYjkkHo5kBgn9cYhcJsywG2kVkwZoNjBQ93Z432FMsCKYPaSxNbHtzH5uEUSF5DKcxKZuYRYXJwlkedI5QPJLFxDDK4tkswHpJJFASPcx/QurLu3SmbDFJAV/rmeW3pMRhsPYdnj78jouCSXf7bLQ1BwREY/vIRVL34io6M82AnB10My2n0Di17vkdHhZ9gKwft9Mtp/D2vecV/jHeyF4M0u82p9hSWfmXd97zVshuAl9/ktgBV53HX4AnZD8GSHuaOUwoIy5s64+QC2Q3CfG2HVSFsNma3egf0QXFsgs2ak53Q7mS1eQxwhuDRDZp1nkIYzfWQ2exHxhOD8JJmNnkNk58bIbOo84grBuVEymzyPiM5PkdnYOcQXgjO9/Ky3O9v7ziDOEJxuszrrb3GzvfU04g0BaizO+nvr/C099hCU87Pe2mxHEiHRZ718ticTEn3Wi2d7QiHRZ710ticVEn3WC2d7YiHhZ718ticbEn7Wy2d7siG4v0ZmVUiplp/tyYfgFj/ro892FyHyWS+f7W5C5LNePtvdhMhnvXy2uwmRz3rJbHcZIp71gtnuNgSo5Wd9qNnuPATlxM96+WxXEIJibm48lc92FSHsrP/ljXy2uw+RznrBbHcfIpj1gtnuPkQw6wWz3X2IYNYLZrv7EMGsl892BSG4wc36phYym7sOjSH8rOdnu84Qftbzs11nCD/r+dmuMISZ9YzuM1Aawsx6RiugOwSoJ4FK6A9hZz0/25WGsLOen+1KQ9hZz892pSHsrOdnu9IQdtbzs11pCF79TEY/voD+EH7W87Ndewgz6/nZrjgEt5blP21XHYIrM/xs1x/Cz/qp89Afwumif3QBGRyCj9/TH3Y+IrNDcDW/dmigNu8y1IbY50N8iA/xIT7Eh/gQH+JDfIgP8SE+xIf4EB/iQ3yID8migCIoUBT+8IoPFNAIBRrDHyfynALmocB8+ANeLlDQJzj3iYIuRDgEaf4UHDt14g1ZiXQsVR8c66OgnmgHhU08g0PPJuiE4qhHt3V+ugUnbn3q/LW9OyACAASAENbBwGa3gAH+uC0I3I/Tj+kV84aB4GQgARqIsgYyuYFwcSAlHYh7Z3LrlQB+ZElQmURUth1GKkNrG7MhAAAAAAAAxj0l70sLmc/I9gAAAABJRU5ErkJggg==" style="width:20px; height:20px; vertical-align: middle;">                <a href="mailto:Ethaniel@100713.xyz"                    style="margin-left:5px; color:#a3a300; text-decoration:none;">Ethaniel@100713.xyz</a>            </p>            <div style="margin-top:2px; font-size:0.9em; line-height:1.6;">                <a href="https://music.100713.xyz"                    style="color:#a3a300; text-decoration:none; margin-right:8px;">音乐空间</a>                <a href="https://100713.xyz" style="color:#a3a300; text-decoration:none; margin-right:8px;">博客</a>                <a href="https://flash.100713.xyz" style="color:#a3a300; text-decoration:none;">Flash收藏站</a>            </div>            <div style="margin-top:2px;">                <!-- GitHub -->                <a href="https://github.com/2010HCY" target="_blank"                    style="margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;">                    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAgCAYAAACcuBHKAAADK0lEQVR42rXWA5TkTBRA4Zf8tm3bts21bdu2bdu2bdu2bb69NcypxuTMZm+fr6VUBHn5jff8ehIp0BxzsAdncRmnsQMzUA+/4iGIH36+9BwqYSlOQX04hpnI99Ib7z0CiUZefu29SG7nT7JgGTSZLmMmWILv3gIJJ9qib4+z0ACcRGM84nd1PI+x0KChd7htxTF3nh5Fe6TAjaqzilOSx1MSl3cDuYMBtYZ6HMBU7Erm9rAV03HUer/qq69+cBPE8C6WnDgP9ejw8uvv3c3jm6iIjVBcwEFswzpsxyFchGIZCuBl3IfBUI8j+N3eJp7GUqilEMTjdeTHf3gHz+BxPIf3kQp58DzEoyrUwhJ+9yHv3lEOV6EeV5EdEoASUMtFZIa4IvIk0sKBNwfPIoieh90tSI+7zSA+x2uwu4TDCKKDuAq7z/GRGcSPuAt2Y9AbQdQBM2D3IL4z62su1HIe/0MClBOXoZZRZkk8B7tjWIcgW4VTsHvBDOIB2J0HAu0MLsPugZu5M+xux20IsrsiTOtmsySOw+4OPIAgeyjCjB03gzgCu3vwLoLsPdwBu8NmEFth5+J3EecOCab78RvCtdlMbB4Udr/y9r8STGnwZYQD4lzX3OEY7O5GdXHkK7m+/kSVCNvDASwyB5F7MAoaZyMW4QwU21CO643XeLztlTffFx/u4Ptv8/1q2Bv1Suv1d28zgzAy4gIUA/E6MmEfFFexPW6w1fEcJIyXUAfjsBsaxWn8CeGH7xv3e64rL2P4y2++9xiPueOXiMciPAEJ4zmsgvrQD3faF7rf4yA0TsVX3nj/Zh7LYjfO4DAqQKJoCU3CDnwEMVxHVOLMFJGGuABTNhV9Me69X/E/fhGVlhK9/YjWadTCEonLVceROFcZSSve6wjTq2iOr8RxtqlenYRVKnpRoncZkbqI2qLSDQIgzOJ8AK1wEYrDmIKBGIV/IFGUhYZxFtVeevO92yFekf7odpTFfqglbzIGsROF2cZugdhc94orYZxHIxFJhaGe6wAFfHccffA/WqvoJdg3lsSb7ybl3rhL+fE4gf8gUeTGKQzH38zpnZBorgEeIoJDUN3opQAAAABJRU5ErkJggg==" style="width:20px; height:20px; margin-right:4px; vertical-align: middle;">                    <span>GitHub</span>                </a>                <!-- LinuxDO -->                <a href="https://linux.do/u/ethaniel/summary" target="_blank"                    style="margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;">                    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADQUlEQVR42sWXz04TURTGryhFJCaE/yb8EdA38BFMxMRNN/gE6tYF4tIHwAVv0AS1GopGZGc0VLbs3BIkuiCxtE4VSplOO5/3Z7FeJmCqaWmTL9w595zvd+bM3ALmxv1b5jhJOmMVi8TiVgmrtO/75VKpJMSaGHvkRGpieJ3EOQne7qy7rZKAVlZWNDv7UFNTN9XfP2Q1KMSaGHvkkEsNta5nXQ3QsbOeD4JAc3OPNTIyJmNMYOV3dV0sDwwMaXDwkhBrYuyRQy411OIR9XYVhXfwMwwrPZK2FxdT6u3tF8Z9fQPh+PikJiauaGxsXEBcEWOPHHKpoRYPvCqVSo/LQMhEu7PjG6ZiZuYB4CIjxhjI8PBoXSKXGmrxwIsP3i4LHXk+dEni9PRtCg+4m9HRy5j+l6jFAy88+cBwmcZ9QxkV3VIwOXkVk4YILzzxhuGetNo4eFlSqZQYGQWMsZHCE+9UakmwYMKuHbVMJkOCVZs6O7vU0dHZUOGJNwxYMGvvQBCUkltbW5xhf21tTauraaXTjRWeeMOABbPWgOd5KhaLkhSq+Z8QFkzYJp/Px60IBNlsVqchWDBh00Di8MK3UrMVYSVoIH14UT4luMtKGxfcApUNi1aq9Q20/hG0/iVs/TGMVy+8IO9ldSrKO19EfB3agPI/ivL2FVqpyQphwfzzu2C3nPy+s6m9zZS/++Wddj+/bYqst2Us+bBg1hrIVdSd/5aRnhvphdVic4Q/ggUTtvkqxVhkpfnCxhNpwRT15oL0+lxDhSfeMGDBhG28/dqfZExi21+/Kz01B9UmzjZEeOGJNwxYCDYL7r79V2BPPblACj5cP2yiU1putyZt/wylhlo88MITbxgukwYQgVj1hQyGSfTX74iR6ZVRdRrtdcPJpYZaPPDCE2+XdaQBtCN1/J4EoypsLEgvjfTM+NYs1PJ5VacSU/QZE2OPHHKpoRYPvPB0Gcc2EO0uJ83b46Lix0fcFY0ESlrjlClzd66IsUcOudRQi0fU+68NuM8H5UJ1Z6WkHZ/2Pi3JX7+n8vtrijZAjD1yyKWG2qhnXQ0gr6AzHJPII4rbcSa8faUtpAwIsSbGHjluDR5e4eR/z38CRCwmJc9le7gAAAAASUVORK5CYII=" style="width:20px; height:20px; margin-right:4px; vertical-align: middle;">                    <span>LinuxDO</span>                </a>                <!-- Steam -->                <a href="https://steamcommunity.com/id/2010hcy/" target="_blank"                    style="margin-right:8px; text-decoration:none; display:inline-flex; align-items:center; color:#a3a300;">                    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAADTUlEQVR42qXXA4zsXADF8U6389m2bdu2+Wzbtm3btm3btm3r37zT5KbD7p7ktzs+t7cOWVHywP33Wb48ji/xFV7DA7gRbk5gJxZjAiZhq2Vk1+49lj+hBIXPIAv+wBMII17OYQMGoCs2xRpAKEbpdSosgSeRmqxFXfTEOX95SpTSu1Af5fQ4tbkL3+EOzMUZWDfffJN1/MQJivVEuRutkEmDSmscvKttYorKrxYbS3s9GiAjgmYbRmAQpuMA7oS3RK/iBm14F1lQRqSQ7MiCILmAbqiHtTDzBiriN7jJhSXoBCtF0/w8WuIOBEkbFMJJpNOPf6tdbRpG42n9voPn9Nphr7gMfkCQLENuhNBCPzodB/E33sIorMAvuEUb3FFMtvnzrKYjaIZhl5byIrJpGtvq8WMawHJMhJe/8JitqXkMQXJZP+jgffTQdHs5gIH43JgdL0/hC7f461TsOpv1Y2GVn4Y/p3AN3JyHlzC+tnXsDZJzqIM1KlwbZftw8B2WGEtp5jW3+KymLtn0RXd4aYf3UBVv4l3Ux93ogQfwBcw86G7VozXqm3BPghPBKuTDPng5iPn4GH/jE+zQQPaiAn6HmXDIOHLdjA/wL77BgzBzUltrP8TKzbiA07gdRVEC18PMJa/YjLeL/Yo/tGGMw2KMwCXEyuN4AS/q++/Bhj/HVBwzd6joTg3iGAZrqs04+AuV8LSex8tqO8E6PYQj2IlpeAnNcC+83I8G6AgdGhNmsbtxuftxZhzFgRhTeUHl4/Et7sZcfIa2+BvhALtjU7fY0dklJ15T8b4YB4VLuAcva6B9tZRBsgY1bO1K/XEH/kFvjMKHcMTMS9pdXsF9CBR1bfPOTtvxA25HCh5U4VLkMk7qWfAuWiM3nkGQrEZpHPGKD2ruv1Wxm6ewCQv0+te4gCb4DtkDHuPPoCymmBcCblbgHrwFN9fgU9jaqGbhkArz6P0gaa5BX4QV8l1l3olmSBdlSzyL6+EgaDqhGI56l7j+q8zTmoqb8Jo3lfp/LWwEyRk0QzmVEl1l6oG/fKI2uGfTcG29UhtSU5wyLuiTuoV5ApnwF55OYr2exVr0Q49491DJ3rQ9gs+Mm7aHfDdtO7AIEzAFO/2F/lwBKuXlrrIH4NIAAAAASUVORK5CYII=" style="width:20px; height:20px; margin-right:4px; vertical-align: middle;">                    <span>Steam</span>                </a>            </div>        </td>    </tr></table></details><p>（部分老旧浏览器可能出现错乱，因为博客CSS原因可能会有所不同）</p><h2 id="总结一下坑点"><a href="#总结一下坑点" class="headerlink" title="总结一下坑点"></a>总结一下坑点</h2><ol><li>WebMail对现代Flexbox 布局支持不佳，需要用传统表格布局</li><li>WebMail对SVG支持不佳，需要使用正确的PNG Base64编码插入或者是URL插入</li><li><del>你需要一个愿意收你的邮件的好友</del></li></ol><p>好了，这就是我亲手设计的邮件签名。简单却又不失个性。花了不少时间折腾这个签名，感觉自己又浪费了点时间。有兴趣的人可以拿去参考一下（记得把联系方式改成你自己的！我可不想被一大堆邮件轰炸），也欢迎留言交流。下面就是最终的样子，直接复制到邮件末尾附上发送就很好看</p><img src="./../../images/我的个人电子邮件签名/最终样子.png" style="zoom:80%;" /><p>四版合照：</p><img src="./../../images/我的个人电子邮件签名/四版合照.png" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E9%82%AE%E4%BB%B6%E5%BA%95%E9%83%A8%E7%9A%84%E5%B0%8F%E5%BF%83%E6%80%9D%EF%BC%9A%E6%88%91%E7%9A%84%E4%B8%AA%E6%80%A7%E5%8C%96%E9%82%AE%E4%BB%B6%E7%AD%BE%E5%90%8D%E8%AE%BE%E8%AE%A1%E4%B9%8B%E6%97%85</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E9%82%AE%E4%BB%B6%E5%BA%95%E9%83%A8%E7%9A%84%E5%B0%8F%E5%BF%83%E6%80%9D%EF%BC%9A%E6%88%91%E7%9A%84%E4%B8%AA%E6%80%A7%E5%8C%96%E9%82%AE%E4%BB%B6%E7%AD%BE%E5%90%8D%E8%AE%BE%E8%AE%A1%E4%B9%8B%E6%97%85"/>
    <published>2025-04-19T11:52:16.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="设计我的电子邮件签名"><a href="#设计我的电子邮件签名" class="headerlink"]]>
    </summary>
    <title>邮件底部的小心思：我的个性化邮件签名设计之旅</title>
    <updated>2025-06-06T01:46:40.187Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="个性签名" scheme="https://hcyhub.com/tags/%E4%B8%AA%E6%80%A7%E7%AD%BE%E5%90%8D/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="成为逼王，从一个有深度的个性签名开始"><a href="#成为逼王，从一个有深度的个性签名开始" class="headerlink" title="成为逼王，从一个有深度的个性签名开始"></a>成为逼王，从一个有深度的个性签名开始</h2><p>在现在这个人均通网的环境下，了解一个人往往从点进他的头像开始，点进头像，在页面中央最显眼的往往是个性签名，签名，就这样成为了你在网上的与人第一面，所以，想要成为一个成功的逼王，要从互联网第一面开始装逼。</p><h3 id="中文签名：心灵的表达"><a href="#中文签名：心灵的表达" class="headerlink" title="中文签名：心灵的表达"></a>中文签名：心灵的表达</h3><p>中文蕴含着悠久的文化底蕴和哲学智慧，中文的语境往往以诗意、哲学、高深为上品，以下几条签名适合装探索、超越和追梦的人生态度的逼：</p><ul><li><strong>“行者无疆，思者无垠。”</strong><br> 表达了思想的无限延伸与探索精神，热爱思考，行遍天下。</li><li><strong>“自我超越，未来可期。”</strong><br> 不断突破自我极限，未来将在不断努力中会越来越美好。</li><li><strong>“万物皆有可能。”</strong><br> 传递给访客对世界充满无限可能的信心，表达敢于追梦，心存希望。</li><li><strong>“在无尽的探索中，成就自我。”</strong><br> 表达出通过不断探索、实践以及学习来成就更好的自己的理念，探索永无止境。</li><li><strong>“心有远方，脚踏实地。”</strong><br> 则完美地平衡了理想与现实，既有对远大抱负的向往，也有脚踏实地的坚定信念。</li></ul><hr><h3 id="英文签名：世界的共鸣"><a href="#英文签名：世界的共鸣" class="headerlink" title="英文签名：世界的共鸣"></a>英文签名：世界的共鸣</h3><p>英文签名力求简洁明快的方式，将哲理融入日常生活中向大家展现，适合展示你追求知识与创意的一面，也体现出你对过程与成长的重视：</p><ul><li><strong>“The journey is the destination.”</strong><br> 人生路上不断学习与探索的过程本身就是最美的目的地。</li><li><strong>“Not all who wander are lost.”</strong><br> 来自《魔戒》的名言，提醒人们迷茫与探索并非等同于迷失方向，而是一种人生常态。</li><li><strong>“To create is to live twice.”</strong><br> 援引加缪的智慧，传递出通过创造，人们能够实现自我超越，赋予生命更多维度的意义。</li><li><strong>“In the pursuit of knowledge, there are no limits.”</strong><br> 这种表达肯定了对知识无穷追求的无限可能，鼓励不断突破界限。</li><li><strong>“Dreams are the seeds of the future.”</strong><br> 表示每一个梦想都是未来辉煌事迹的萌芽，点燃人们对美好未来的向往。</li><li><strong>“We are all stardust.”</strong><br> 一种结合科学与哲学的表达，提醒我们每个人都与宇宙有着千丝万缕的联系，呼唤谦卑与探索。</li><li><strong>“The only way out is through.”</strong><br> 强调面对困难时，唯一的出路就是积极地迎难而上，勇敢前行。</li><li><strong>“What we think, we become.”</strong><br> 借用佛教智慧，表达思想的力量不仅决定了我们的行为，更塑造了我们的存在。</li></ul><hr><h3 id="拉丁文签名：经典的永恒"><a href="#拉丁文签名：经典的永恒" class="headerlink" title="拉丁文签名：经典的永恒"></a>拉丁文签名：经典的永恒</h3><p>拉丁文作为一种几乎失传古典语言，带给人一种独特的庄重与历史感，用拉丁文签名不仅简练有力，还蕴藏着你的跨越时空智慧，彰显文化底蕴：</p><ul><li><strong>“Per aspera ad astra.”</strong><br> “通过艰难困苦到达星辰”，展现在逆境中依然执着追求理想的决心。</li><li><strong>“Vive ut vivas.”</strong><br> “活着，为了更好地生活” ，展现你追求一种充实且富有意义的生命，不入凡流。</li><li><strong>“Ad astra per alia porci.”</strong><br> 这是一句幽默的签名（“靠猪的翅膀飞向星辰”），表达了即使看似不可能的事，也能通过别出心裁的方法实现，万物皆有可能，我已飞向星辰，你呢？</li><li><strong>“Memento mori.”</strong><br> “记住你终将逝去”，珍惜当下，在长眠前活出生命的精彩，成为人们代代相传的传说。</li><li><strong>“Ars longa, vita brevis.”</strong><br> “艺术长存，生命短暂”，道出了艺术永恒与生命的有限，令人反思如何在人生中留下真正有意义的传世作品。</li><li><strong>“Fortes fortuna adiuvat.”</strong><br> “命运青睐勇者” 短短三词中蕴含着面对困难时的不屈精神和勇敢冒险的信条，勇者受命运垂青。</li><li><strong>“Carpe diem.”</strong><br> “抓住今天”，珍惜眼前的每一刻，不留遗憾。</li><li><strong>“Cogito, ergo sum.”</strong><br> “我思故我在”，以简洁的语言揭示了思考和自我意识的力量，是哲学与存在主义的不朽名言。</li></ul><hr><p>选择签名时记住，签名不仅是一句简单的短语，它更像是一面镜子，反映着你的思考方式、生活态度与精神追求。所以，从中文的诗意深远，到英文的精炼智慧，再到拉丁文的经典永恒，每一种表达都独具特色，选择一条适合自己想要立的人设的签名，就像为你的数字身份注入了一份独特而深沉的灵魂。</p><h2 id="不走寻常路，使用独具一格定位"><a href="#不走寻常路，使用独具一格定位" class="headerlink" title="不走寻常路，使用独具一格定位"></a>不走寻常路，使用独具一格定位</h2><p>你是否还在填写传统的xx国xx市做为你的定位？这太普通了！定位也要装起来！</p><h3 id="英文定位"><a href="#英文定位" class="headerlink" title="英文定位"></a>英文定位</h3><ol><li><strong>“Earth, Solar System, Milky Way”</strong><br>“地球、太阳系、银河系” 简洁而优雅，直接标明我们所在的宇宙大致位置。</li><li><strong>“Third Rock from the Sun”</strong><br>“距太阳第三颗岩石” 用地球在太阳系中的位置表达，带点幽默感。</li><li><strong>“A Dust Speck in the Infinite Cosmos”</strong><br>“无限宇宙中的一粒尘埃” 带有哲学意味，突显宇宙的浩瀚和人类的渺小。</li><li><strong>“Home, Among the Stars”</strong><br>家，星辰之中” 富有诗意，传递一种人类与星空的联系。</li><li><strong>“Somewhere between the stars.”</strong><br>“在星际间的某个地方” 充满神秘感，表达自己身在宇宙中但不明具体踪迹。</li><li><strong>“A tiny speck in the vast cosmos.”</strong><br>“浩瀚宇宙中的一个小点” 表达宇宙的浩瀚和我们微小的存在，突出你的思想宏大。</li><li><strong>“Orbiting the Sun, thinking about code.”</strong><br>“绕太阳运行，思考代码” 用幽默的方式结合了宇宙位置表明你的程序员身份。</li><li><strong>“Here, in the Milky Way, making things work.”</strong><br>“这里，在银河系，让一切运转起来” 简洁、现代，同时传达着对技术的热爱。</li></ol><h3 id="拉丁文定位"><a href="#拉丁文定位" class="headerlink" title="拉丁文定位"></a>拉丁文定位</h3><ol><li><strong>“Terra, Solis Systema, Via Lactea”</strong><br> 地球、太阳系、银河系的拉丁语表达。</li><li><strong>“Tertia Petra a Sole”</strong><br> 太阳的第三颗岩石行星，地球的拉丁语化描述。</li><li><strong>“Punctum Caeruleum Pallidum”</strong><br> 拉丁语版的“暗淡蓝点”。</li><li><strong>“Inter Astra, Domum Hominum”</strong><br> “在星际之间，人类的家园。”</li><li><strong>“Infinitum Universum, Pars Humana”</strong><br> “无限宇宙中的人类一部分。”</li><li><strong>“Inter Astra, in Via Lactea.”</strong><br> “在群星之间，在银河系中” 的拉丁文版本。</li><li><strong>“Punctum Caeruleum, Inter Astrum.”</strong><br> “蓝点之中，星际之间”，带有深刻哲学意味。</li><li><strong>“Solis Tertius, Via Lactea.”</strong><br> “太阳的第三颗行星，银河系”，简洁且带有地理感。</li><li><strong>“Infinita Universum, Hic.”</strong><br> “在无限宇宙中，这里”，有点诗意且神秘。</li></ol><p>选择定位时要尽量选择宏大虚无缥缈的概念，例如宇宙啦行星啦，这样才能给人以一种琢磨不透，感觉深邃的感觉，并且不要将现实生活信息带入，这会给人以一种 ”刚刚觉得你很牛逼，结果一下子落入凡尘俗气起来“ 的感觉，装逼主要打的就是一个宏大叙事飘渺概念看不懂的就是最高级的，所以选择拉丁文效果最佳~</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%88%90%E4%B8%BA%E9%80%BC%E7%8E%8B%EF%BC%8C%E4%BB%8E%E4%B8%80%E4%B8%AA%E6%9C%89%E6%B7%B1%E5%BA%A6%E7%9A%84%E4%B8%AA%E6%80%A7%E7%AD%BE%E5%90%8D%E5%BC%80%E5%A7%8B</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%88%90%E4%B8%BA%E9%80%BC%E7%8E%8B%EF%BC%8C%E4%BB%8E%E4%B8%80%E4%B8%AA%E6%9C%89%E6%B7%B1%E5%BA%A6%E7%9A%84%E4%B8%AA%E6%80%A7%E7%AD%BE%E5%90%8D%E5%BC%80%E5%A7%8B"/>
    <published>2025-04-12T07:33:29.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="成为逼王，从一个有深度的个性签名开始"><a href="#成为逼王，从一个有深度的个性签名开始" class="headerlink"]]>
    </summary>
    <title>成为逼王，从一个有深度的个性签名开始</title>
    <updated>2025-04-12T07:33:38.138Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="缓存失败"><a href="#缓存失败" class="headerlink" title="缓存失败"></a>缓存失败</h2><p>我前天做了个项目，使用 CloudflareWorkers 来处理地球图像请求，访客访问Workers地址Workers返回最新图片，我当时想用 Cloudflare 的缓存来避免过多不必要重复的Workers请求刷爆我的账单，于是我我在 Worker 中设置最新图片的缓存头</p><pre class="line-numbers language-none"><code class="language-none">return new Response(imageResponse.body, &#123;    headers: &#123;        &#39;Content-Type&#39;: &#39;image&#x2F;png&#39;,        &#39;Cache-Control&#39;: &#39;public, max-age&#x3D;300, s-maxage&#x3D;600&#39;    &#125;&#125;);<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>但是，事情没有这么简单，我实际打开发现Cloudflare并没有缓存我的图片，并且我每一次刷新都结结实实的发送给了Workers处理，我在F12中发现响应头缺失<code>cf-cache-status</code>字段：</p><img src="./../../images/记一次CloudflareWorkers图片缓存失败解决/截图1.png" style="zoom:80%;" /><img src="./../../images/记一次CloudflareWorkers图片缓存失败解决/截图2.jpg" style="zoom:80%;" /><h2 id="修改"><a href="#修改" class="headerlink" title="修改"></a>修改</h2><p>我尝试过设置Cloudflare Cache Rules、将访问改成访问earth.png，但Cloudflare就是不缓存图片，就是没有<code>cf-cache-status</code>字段，就是不缓存，我无奈的只能搜索、发帖求助、骚扰AI，但都无功而返，直到GPT说漏了嘴，提到了 <strong>Cache API</strong> 。</p><p>我搜了下，这似乎是Cloudflare官方提供的缓存API <a href="https://developers.cloudflare.com/workers/runtime-apis/cache/">官方文档</a> 我研究了下把文档复制给了GPT，但GPT输出的代码全特么是报错，扯皮了半小时，没办法，只能人工亲自修改：</p><pre class="line-numbers language-none"><code class="language-none"> export default &#123;    async fetch(request) &#123;        const url &#x3D; new URL(request.url);        const cache &#x3D; caches.default;                 ......        const cacheKey &#x3D; new Request(imageUrl); &#x2F;&#x2F; 使用图像 URL 作为缓存键let response &#x3D; await cache.match(cacheKey); &#x2F;&#x2F; 尝试从缓存中获取图像                ......        if (!response) &#123;            const imageResponse &#x3D; await fetch(imageUrl); &#x2F;&#x2F; 获取图像            if (!imageResponse.ok) &#123;                throw new Error(&#96;Failed to fetch image: $&#123;imageResponse.status&#125;&#96;);            &#125;            &#x2F;&#x2F; 创建新的响应并缓存            response &#x3D; new Response(imageResponse.body, &#123;                headers: &#123;                    &#39;Content-Type&#39;: &#39;image&#x2F;png&#39;,                    &#39;Cache-Control&#39;: &#39;public, s-maxage&#x3D;600&#39;, &#x2F;&#x2F; Cloudflare缓存10分钟                    &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;, &#x2F;&#x2F; 允许任何位置请求                &#125;            &#125;);            &#x2F;&#x2F; 将响应存入缓存            await cache.put(cacheKey, response.clone());        ......<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>一番修正后，F12查看终于是命中了缓存</p><img src="./../../images/记一次CloudflareWorkers图片缓存失败解决/命中缓存.png" style="zoom:80%;" /><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Cloudflare好像是更新了Workers更新规则，现在不再主动缓存Workers，现在需要在Workers里手动使用Cache API缓存你想要缓存的内容，关键点如下：</p><ul><li>缓存键（Cache Key）必须使用有效的 URL 格式，缓存键就像你存放缓存的货架编号，需要使用有效URL</li><li>缓存键可以瞎设置，但必须符合URL格式规则</li><li>URL不需要实际存在、可用，URL就像你的缓存Key，这个Key的格式只需要包含“**https:&#x2F;&#x2F;**”，后面的字符可以随便填</li><li>只要你的Workers是在同一个数据中心的，那么这个缓存可以共用</li></ul><p>这是我阅读文档后写了一段Workers代码示例：</p><pre class="line-numbers language-none"><code class="language-none">export default &#123;  async fetch(request, env, ctx) &#123;    const cache &#x3D; caches.default;    const cacheKey &#x3D; new URL(request.url); &#x2F;&#x2F; 创建缓存键    &#x2F;&#x2F; 尝试从缓存中获取响应    let response &#x3D; await cache.match(cacheKey);    if (!response) &#123;      &#x2F;&#x2F; 没缓存，则创建新的响应      response &#x3D; new Response(&#39;Fuck World!&#39;, &#123;        headers: &#123; &#39;Cache-Control&#39;: &#39;max-age&#x3D;3600&#39; &#125; &#x2F;&#x2F; 使用传入的头部      &#125;);      &#x2F;&#x2F; 将响应存入缓存      await cache.put(cacheKey, response.clone());    &#125;    return response; &#x2F;&#x2F; 返回响应  &#125;,&#125;;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>经我观察，GPT的回答似乎完全是凭空捏造的，我怀疑是AI的知识库中缺乏相关信息、标注，不过如果把示例代码、文档打包发给他回好很多</p><p>下面是我折腾好的地球实时图像，10分钟更新一次</p><p><img src="https://earth.hcyhub.com/"></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E8%AE%B0%E4%B8%80%E6%AC%A1CloudflareWorkers%E5%9B%BE%E7%89%87%E7%BC%93%E5%AD%98%E5%A4%B1%E8%B4%A5%E8%A7%A3%E5%86%B3</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E8%AE%B0%E4%B8%80%E6%AC%A1CloudflareWorkers%E5%9B%BE%E7%89%87%E7%BC%93%E5%AD%98%E5%A4%B1%E8%B4%A5%E8%A7%A3%E5%86%B3"/>
    <published>2025-04-09T12:10:33.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="缓存失败"><a href="#缓存失败" class="headerlink" title="缓存失败"></a>缓存失败</h2><p>我前天做了个项目，使用 CloudflareWorkers 来处理地球图像请求，访客访问Workers地址Workers返回最新图片，我当时想用 Cloudflare 的缓存来避免过多不必要重复的Workers请求刷爆我的账单，于是我我在 Worker 中设置最新图片的缓存头</p>
<pre]]>
    </summary>
    <title>记一次CloudflareWorkers图片缓存失败解决</title>
    <updated>2025-12-01T11:21:45.376Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="广告屏蔽" scheme="https://hcyhub.com/tags/%E5%B9%BF%E5%91%8A%E5%B1%8F%E8%94%BD/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="BiliBili首页广告屏蔽规则"><a href="#BiliBili首页广告屏蔽规则" class="headerlink" title="BiliBili首页广告屏蔽规则"></a>BiliBili首页广告屏蔽规则</h2><h3 id="首页"><a href="#首页" class="headerlink" title="首页"></a>首页</h3><h4 id="番剧、纪录片、直播、推广"><a href="#番剧、纪录片、直播、推广" class="headerlink" title="番剧、纪录片、直播、推广"></a>番剧、纪录片、直播、推广</h4><p>如图，哔哩哔哩网页端首页右侧会有很烦人的番剧、纪录片、直播、推广，还无法关闭<br><img src="./../../images/BiliBili首页广告屏蔽规则/推广.png" style="zoom:80%;" /><br>这时可以用AdGuard的过滤规则一键屏蔽</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com##.floor-single-card<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>直接按Div名过滤避免结构变动更新。</p><h4 id="横幅"><a href="#横幅" class="headerlink" title="横幅"></a>横幅</h4><p>如果你启用了广告屏蔽类插件，B站还会给你在首页加一个横幅，为了保障您的浏览体验～<br><img src="./../../images/BiliBili首页广告屏蔽规则/横幅.png" style="zoom:80%;" /><br>屏蔽规则：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com##.adblock-tips<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>直接按Div名过滤避免结构变动更新</p><h4 id="首页左侧"><a href="#首页左侧" class="headerlink" title="首页左侧"></a>首页左侧</h4><img src="./../../images/BiliBili首页广告屏蔽规则/首页左侧.png" style="zoom:50%;" /><p>这个看个人习惯，我是不怎么习惯过滤后的样子，且该板块也不全是广告（但阅读价值都不大）</p><p>过滤规则：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com##.recommended-swipe<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h3 id="播放页"><a href="#播放页" class="headerlink" title="播放页"></a>播放页</h3><h4 id="右侧广告卡片"><a href="#右侧广告卡片" class="headerlink" title="右侧广告卡片"></a>右侧广告卡片</h4><img src="./../../images/BiliBili首页广告屏蔽规则/播放页右侧广告卡片.png" style="zoom:50%;" /><p>过滤规则：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com##.video-card-ad-small<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h2 id="最终效果"><a href="#最终效果" class="headerlink" title="最终效果"></a>最终效果</h2><p>最终效果：<br><img src="./../../images/BiliBili首页广告屏蔽规则/效果1.png" style="zoom:80%;" /><br><img src="./../../images/BiliBili首页广告屏蔽规则/效果2.png" style="zoom:80%;" /></p><h2 id="如何导入规则？"><a href="#如何导入规则？" class="headerlink" title="如何导入规则？"></a>如何导入规则？</h2><p>安装<a href="https://adguard.com/">AdGuard</a></p><p>点击浏览器扩展图标→右上角设置</p><img src="./../../images/BiliBili首页广告屏蔽规则/扩展设置.png" style="zoom:80%;" /><p>打开扩展配置页面，点击用户规则，粘贴过滤规则进去即可</p><p>过滤规则（2026-03-04）：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com##.floor-single-cardbilibili.com##.adblock-tips<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>直播和软广卡片今年都没有发现，可能被删了，也可能我没刷到</p><img src="./../../images/BiliBili首页广告屏蔽规则/添加规则.png" style="zoom:80%;" /><p>2025.04.09  更新：添加软广屏蔽规则</p><p>2026.03.04  更新：更新了直播、右侧番剧卡片的过滤规则</p><p>2026.03.05  更新：添加首页左侧、播放页右侧广告过滤规则，软广、直播归类失效</p><h2 id="已失效、历史过滤规则"><a href="#已失效、历史过滤规则" class="headerlink" title="已失效、历史过滤规则"></a>已失效、历史过滤规则</h2><h3 id="软广"><a href="#软广" class="headerlink" title="软广"></a>软广</h3><p>如图所示，视频右下角有个小火箭的就是必火推广，至于买推广的视频…不是卖药就是卖课的</p><img src="./../../images/BiliBili首页广告屏蔽规则/软广.png" style="zoom:80%;" /><p>屏蔽规则：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com###i_cecream &gt; div.bili-feed4:last-child &gt; main.bili-feed4-layout:nth-child(3) &gt; div.feed2:last-child &gt; div.recommended-container_floor-aside &gt; div.container.is-version8:first-child &gt; div.feed-card:nth-child<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>2026.3.4更新：很久没有见到过它了，不清楚是否是被删了</p><h3 id="直播"><a href="#直播" class="headerlink" title="直播"></a>直播</h3><p>如图，首页视频卡片里总是会给你塞一个直播<br><img src="./../../images/BiliBili首页广告屏蔽规则/直播.png" style="zoom:80%;" /><br>内容弱智不说还很影响体验，屏蔽规则：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com###i_cecream &gt; div.bili-feed4:last-child &gt; main.bili-feed4-layout:nth-child(3) &gt; div.feed2:last-child &gt; div.recommended-container_floor-aside &gt; div.container.is-version8:first-child &gt; div.bili-live-card.is-rcmd.enable-no-interest<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>2026.3.4更新：不知道为什么B站首页很久没有推这个直播了</p><p>过滤规则（2025-04-08）：</p><pre class="line-numbers language-none"><code class="language-none">bilibili.com###i_cecream &gt; div.bili-feed4:last-child &gt; main.bili-feed4-layout:nth-child(3) &gt; div.feed2:last-child &gt; div.recommended-container_floor-aside &gt; div.container.is-version8:first-child &gt; div.floor-single-cardbilibili.com###i_cecream &gt; div.adblock-tipsbilibili.com###i_cecream &gt; div.bili-feed4:last-child &gt; main.bili-feed4-layout:nth-child(3) &gt; div.feed2:last-child &gt; div.recommended-container_floor-aside &gt; div.container.is-version8:first-child &gt; div.bili-live-card.is-rcmd.enable-no-interestbilibili.com###i_cecream &gt; div.bili-feed4:last-child &gt; main.bili-feed4-layout:nth-child(3) &gt; div.feed2:last-child &gt; div.recommended-container_floor-aside &gt; div.container.is-version8:first-child &gt; div.feed-card:nth-child<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/BiliBili%E9%A6%96%E9%A1%B5%E5%B9%BF%E5%91%8A%E5%B1%8F%E8%94%BD%E8%A7%84%E5%88%99</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/BiliBili%E9%A6%96%E9%A1%B5%E5%B9%BF%E5%91%8A%E5%B1%8F%E8%94%BD%E8%A7%84%E5%88%99"/>
    <published>2025-04-08T02:41:46.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="BiliBili首页广告屏蔽规则"><a href="#BiliBili首页广告屏蔽规则" class="headerlink" title="BiliBili首页广告屏蔽规则"></a>BiliBili首页广告屏蔽规则</h2><h3 id="首页"><a href="#首页" class="headerlink" title="首页"></a>首页</h3><h4 id="番剧、纪录片、直播、推广"><a]]>
    </summary>
    <title>BiliBili首页广告屏蔽规则</title>
    <updated>2026-03-06T12:30:15.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <category term="4399" scheme="https://hcyhub.com/tags/4399/"/>
    <category term="游戏" scheme="https://hcyhub.com/tags/%E6%B8%B8%E6%88%8F/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>众所周知，4399为了防止下载其SWF Flash游戏禁用了F12、Shift+Ctrl+I快捷键打开开发者工具，如果手动打开开发者工具会暂停加载</p><p>如图：<br><img src="./../../images/3分钟破解4399防沉迷/开发者工具被禁1.png" style="zoom:80%;" /><br><img src="./../../images/3分钟破解4399防沉迷/开发者工具被禁2.png" style="zoom:80%;" /></p><p>但关键就在于，实现此功能的是一个名字叫Antiindulgence.js的JS文件，打开此文件可以看到，防沉迷、防F12功能全是由此JS文件实现的，这…</p><img src="./../../images/3分钟破解4399防沉迷/JS详情.png" style="zoom:80%;" />所以，破解4399防沉迷、防下载只需要在前端屏蔽掉`https://www.4399.com/antijs/Antiindulgence.js`这个JS文件就好了...<p>屏蔽后你不用登录即可畅玩4399游戏</p><p>屏蔽方法：在<a href="https://adguard.com/zh_cn/welcome.html">AdGuard</a>广告屏蔽插件里添加屏蔽<code>https://www.4399.com/antijs/Antiindulgence.js</code><br>加载的规则即可</p><img src="./../../images/3分钟破解4399防沉迷/屏蔽规则.png" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/4399%E9%98%B2%E6%B2%89%E8%BF%B7%E3%80%81%E7%A6%81%E7%94%A8F12%E7%A0%B4%E8%A7%A3</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/4399%E9%98%B2%E6%B2%89%E8%BF%B7%E3%80%81%E7%A6%81%E7%94%A8F12%E7%A0%B4%E8%A7%A3"/>
    <published>2025-04-06T06:00:32.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>众所周知，4399为了防止下载其SWF Flash游戏禁用了F12、Shift+Ctrl+I快捷键打开开发者工具，如果手动打开开发者工具会暂停加载</p>
<p>如图：<br><img src="./../../images/3分钟破解4399防沉迷/开发者工具被禁1.png" style="zoom:80%;" /><br><img src="./../../images/3分钟破解4399防沉迷/开发者工具被禁2.png"]]>
    </summary>
    <title>3分钟破解4399防沉迷（顺便防止4399禁用浏览器开发者工具）</title>
    <updated>2025-04-06T06:00:37.451Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>众所周知我有一个<a href="https://music.hcyhub.com/">原声音轨播放网站</a>，原本我图省事将音乐和网页文件放置在一起的，但时间长了就慢慢有问题出现了：服务器空间不够了 <del>其实是贵</del>  ，我的服务器只有可怜的3G磁盘，安装一些七七八八的服务后就基本没空间了，而原声音轨又很占空间，这使得我无法继续添加新的音乐了。</p><p>于是我开始寻找能够储存文件并分发的云端服务，Backblaze在各个方面都很符合我的要求，免费计划有10GB的空间可以耍，最重要的是，它Backblaze是Cloudflare带宽联盟的成员，走大善人Cloudflare代理流量免费！</p><h2 id="开始白嫖"><a href="#开始白嫖" class="headerlink" title="开始白嫖"></a>开始白嫖</h2><h3 id="第一步，上传文件"><a href="#第一步，上传文件" class="headerlink" title="第一步，上传文件"></a>第一步，上传文件</h3><h4 id="创建桶和密钥"><a href="#创建桶和密钥" class="headerlink" title="创建桶和密钥"></a>创建桶和密钥</h4><p>我已经注册过了Backblaze，所以只需要创建个私有桶就行了（公共桶要有付款记录或者支付一刀验证），新用户注册记得去创建一下主密钥，并将key ID和key记好放到安全的地方</p><p>这里我创建好了桶</p><img src="./../../images/原声音轨迁移至BackblazeB2/创建桶.png" style="zoom:80%;" /><p>接下来就是创建一个密钥，我不推荐使用主密钥，很不安全，我这里创建了个仅能访问音乐桶的只读密钥</p><img src="./../../images/原声音轨迁移至BackblazeB2/创建密钥.png" style="zoom:80%;" /><p>桶创建好了，密钥也创建好了，接下来开始上传文件，虽然Backblaze官方提供了个浏览器上传接口，但那玩意上传贼慢，还不支持多线程，上传一两个小文件还好，一要批量上传那简直是噩梦，所以我选择了命令行上传</p><p>要现安装一下Backblaze B2 CLI，Backblaze B2 CLI是官方推出的命令行工具，这里建议现安装Python，然后使用pip一键安装。</p><p>打开命令提示窗口（Win+R，输入cmd），输入</p><pre class="line-numbers language-none"><code class="language-none">pip install b2<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>然后等，安装完成后输入</p><pre class="line-numbers language-none"><code class="language-none">b2 authorize-account<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>接着它会提示你输入Application Key ID，这里我们输入主密钥的ID，回车输入主密钥的Key，注意输入Key时是不会显示的，输入好后回车就好了，如果出现下图的一大串内容就说明你成功授权了Backblaze B2 CLI</p><img src="./../../images/原声音轨迁移至BackblazeB2/命令行授权.png" style="zoom:80%;" /><p>接着开始上传，输入</p><pre class="line-numbers language-none"><code class="language-none">b2 sync &quot;C:\&lt;本地路径&gt;&quot; &quot;b2:&#x2F;&#x2F;&lt;存储桶名&gt;&#x2F;&lt;文件夹&gt;&quot;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>自己将命令中的路径替换成你要上传的路径，存储桶中如果不存在你所指定的文件夹会自动创建，然后等待上传完成吧，控制台里每打印一个文件名就说明上传好了一个文件名，如果控制台打印的文件名乱码也不用慌，上传的文件名是不会错的</p><img src="./../../images/原声音轨迁移至BackblazeB2/上传.png" style="zoom:80%;" /><p>上传完成！</p><h3 id="创建CloudflareWorkers访问私有桶里的东西"><a href="#创建CloudflareWorkers访问私有桶里的东西" class="headerlink" title="创建CloudflareWorkers访问私有桶里的东西"></a>创建CloudflareWorkers访问私有桶里的东西</h3><p>创建或登录Cloudflare账号，然后创建Workers，名字随意不影响的，接着编辑代码，将以下代码粘贴进去</p><img src="./../../images/PageMeter/编辑代码、部署.png" style="zoom:80%;" /><p>⬇⬇⬇⬇⬇</p><details>  <summary>点击展开代码</summary><pre class="line-numbers language-none"><code class="language-none">var __defProp &#x3D; Object.defineProperty;var __name &#x3D; (target, value) &#x3D;&gt; __defProp(target, &quot;name&quot;, &#123; value, configurable: true &#125;);var encoder &#x3D; new TextEncoder();var HOST_SERVICES &#x3D; &#123;  appstream2: &quot;appstream&quot;,  cloudhsmv2: &quot;cloudhsm&quot;,  email: &quot;ses&quot;,  marketplace: &quot;aws-marketplace&quot;,  mobile: &quot;AWSMobileHubService&quot;,  pinpoint: &quot;mobiletargeting&quot;,  queue: &quot;sqs&quot;,  &quot;git-codecommit&quot;: &quot;codecommit&quot;,  &quot;mturk-requester-sandbox&quot;: &quot;mturk-requester&quot;,  &quot;personalize-runtime&quot;: &quot;personalize&quot;&#125;;var UNSIGNABLE_HEADERS &#x3D; &#x2F;* @__PURE__ *&#x2F; new Set([  &quot;authorization&quot;,  &quot;content-type&quot;,  &quot;content-length&quot;,  &quot;user-agent&quot;,  &quot;presigned-expires&quot;,  &quot;expect&quot;,  &quot;x-amzn-trace-id&quot;,  &quot;range&quot;,  &quot;connection&quot;]);var AwsClient &#x3D; class &#123;  static &#123;    __name(this, &quot;AwsClient&quot;);  &#125;  constructor(&#123; accessKeyId, secretAccessKey, sessionToken, service, region, cache, retries, initRetryMs &#125;) &#123;    if (accessKeyId &#x3D;&#x3D; null) throw new TypeError(&quot;accessKeyId is a required option&quot;);    if (secretAccessKey &#x3D;&#x3D; null) throw new TypeError(&quot;secretAccessKey is a required option&quot;);    this.accessKeyId &#x3D; accessKeyId;    this.secretAccessKey &#x3D; secretAccessKey;    this.sessionToken &#x3D; sessionToken;    this.service &#x3D; service;    this.region &#x3D; region;    this.cache &#x3D; cache || &#x2F;* @__PURE__ *&#x2F; new Map();    this.retries &#x3D; retries !&#x3D; null ? retries : 10;    this.initRetryMs &#x3D; initRetryMs || 50;  &#125;  async sign(input, init) &#123;    if (input instanceof Request) &#123;      const &#123; method, url, headers, body &#125; &#x3D; input;      init &#x3D; Object.assign(&#123; method, url, headers &#125;, init);      if (init.body &#x3D;&#x3D; null &amp;&amp; headers.has(&quot;Content-Type&quot;)) &#123;        init.body &#x3D; body !&#x3D; null &amp;&amp; headers.has(&quot;X-Amz-Content-Sha256&quot;) ? body : await input.clone().arrayBuffer();      &#125;      input &#x3D; url;    &#125;    const signer &#x3D; new AwsV4Signer(Object.assign(&#123; url: input.toString() &#125;, init, this, init &amp;&amp; init.aws));    const signed &#x3D; Object.assign(&#123;&#125;, init, await signer.sign());    delete signed.aws;    try &#123;      return new Request(signed.url.toString(), signed);    &#125; catch (e) &#123;      if (e instanceof TypeError) &#123;        return new Request(signed.url.toString(), Object.assign(&#123; duplex: &quot;half&quot; &#125;, signed));      &#125;      throw e;    &#125;  &#125;  async fetch(input, init) &#123;    for (let i &#x3D; 0; i &lt;&#x3D; this.retries; i++) &#123;      const fetched &#x3D; fetch(await this.sign(input, init));      if (i &#x3D;&#x3D;&#x3D; this.retries) &#123;        return fetched;      &#125;      const res &#x3D; await fetched;      if (res.status &lt; 500 &amp;&amp; res.status !&#x3D;&#x3D; 429) &#123;        return res;      &#125;      await new Promise((resolve) &#x3D;&gt; setTimeout(resolve, Math.random() * this.initRetryMs * Math.pow(2, i)));    &#125;    throw new Error(&quot;An unknown error occurred, ensure retries is not negative&quot;);  &#125;&#125;;var AwsV4Signer &#x3D; class &#123;  static &#123;    __name(this, &quot;AwsV4Signer&quot;);  &#125;  constructor(&#123; method, url, headers, body, accessKeyId, secretAccessKey, sessionToken, service, region, cache, datetime, signQuery, appendSessionToken, allHeaders, singleEncode &#125;) &#123;    if (url &#x3D;&#x3D; null) throw new TypeError(&quot;url is a required option&quot;);    if (accessKeyId &#x3D;&#x3D; null) throw new TypeError(&quot;accessKeyId is a required option&quot;);    if (secretAccessKey &#x3D;&#x3D; null) throw new TypeError(&quot;secretAccessKey is a required option&quot;);    this.method &#x3D; method || (body ? &quot;POST&quot; : &quot;GET&quot;);    this.url &#x3D; new URL(url);    this.headers &#x3D; new Headers(headers || &#123;&#125;);    this.body &#x3D; body;    this.accessKeyId &#x3D; accessKeyId;    this.secretAccessKey &#x3D; secretAccessKey;    this.sessionToken &#x3D; sessionToken;    let guessedService, guessedRegion;    if (!service || !region) &#123;      [guessedService, guessedRegion] &#x3D; guessServiceRegion(this.url, this.headers);    &#125;    this.service &#x3D; service || guessedService || &quot;&quot;;    this.region &#x3D; region || guessedRegion || &quot;us-east-1&quot;;    this.cache &#x3D; cache || &#x2F;* @__PURE__ *&#x2F; new Map();    this.datetime &#x3D; datetime || (&#x2F;* @__PURE__ *&#x2F; new Date()).toISOString().replace(&#x2F;[:-]|\.\d&#123;3&#125;&#x2F;g, &quot;&quot;);    this.signQuery &#x3D; signQuery;    this.appendSessionToken &#x3D; appendSessionToken || this.service &#x3D;&#x3D;&#x3D; &quot;iotdevicegateway&quot;;    this.headers.delete(&quot;Host&quot;);    if (this.service &#x3D;&#x3D;&#x3D; &quot;s3&quot; &amp;&amp; !this.signQuery &amp;&amp; !this.headers.has(&quot;X-Amz-Content-Sha256&quot;)) &#123;      this.headers.set(&quot;X-Amz-Content-Sha256&quot;, &quot;UNSIGNED-PAYLOAD&quot;);    &#125;    const params &#x3D; this.signQuery ? this.url.searchParams : this.headers;    params.set(&quot;X-Amz-Date&quot;, this.datetime);    if (this.sessionToken &amp;&amp; !this.appendSessionToken) &#123;      params.set(&quot;X-Amz-Security-Token&quot;, this.sessionToken);    &#125;    this.signableHeaders &#x3D; [&quot;host&quot;, ...this.headers.keys()].filter((header) &#x3D;&gt; allHeaders || !UNSIGNABLE_HEADERS.has(header)).sort();    this.signedHeaders &#x3D; this.signableHeaders.join(&quot;;&quot;);    this.canonicalHeaders &#x3D; this.signableHeaders.map((header) &#x3D;&gt; header + &quot;:&quot; + (header &#x3D;&#x3D;&#x3D; &quot;host&quot; ? this.url.host : (this.headers.get(header) || &quot;&quot;).replace(&#x2F;\s+&#x2F;g, &quot; &quot;))).join(&quot;\n&quot;);    this.credentialString &#x3D; [this.datetime.slice(0, 8), this.region, this.service, &quot;aws4_request&quot;].join(&quot;&#x2F;&quot;);    if (this.signQuery) &#123;      if (this.service &#x3D;&#x3D;&#x3D; &quot;s3&quot; &amp;&amp; !params.has(&quot;X-Amz-Expires&quot;)) &#123;        params.set(&quot;X-Amz-Expires&quot;, &quot;86400&quot;);      &#125;      params.set(&quot;X-Amz-Algorithm&quot;, &quot;AWS4-HMAC-SHA256&quot;);      params.set(&quot;X-Amz-Credential&quot;, this.accessKeyId + &quot;&#x2F;&quot; + this.credentialString);      params.set(&quot;X-Amz-SignedHeaders&quot;, this.signedHeaders);    &#125;    if (this.service &#x3D;&#x3D;&#x3D; &quot;s3&quot;) &#123;      try &#123;        this.encodedPath &#x3D; decodeURIComponent(this.url.pathname.replace(&#x2F;\+&#x2F;g, &quot; &quot;));      &#125; catch (e) &#123;        this.encodedPath &#x3D; this.url.pathname;      &#125;    &#125; else &#123;      this.encodedPath &#x3D; this.url.pathname.replace(&#x2F;\&#x2F;+&#x2F;g, &quot;&#x2F;&quot;);    &#125;    if (!singleEncode) &#123;      this.encodedPath &#x3D; encodeURIComponent(this.encodedPath).replace(&#x2F;%2F&#x2F;g, &quot;&#x2F;&quot;);    &#125;    this.encodedPath &#x3D; encodeRfc3986(this.encodedPath);    const seenKeys &#x3D; &#x2F;* @__PURE__ *&#x2F; new Set();    this.encodedSearch &#x3D; [...this.url.searchParams].filter(([k]) &#x3D;&gt; &#123;      if (!k) return false;      if (this.service &#x3D;&#x3D;&#x3D; &quot;s3&quot;) &#123;        if (seenKeys.has(k)) return false;        seenKeys.add(k);      &#125;      return true;    &#125;).map((pair) &#x3D;&gt; pair.map((p) &#x3D;&gt; encodeRfc3986(encodeURIComponent(p)))).sort(([k1, v1], [k2, v2]) &#x3D;&gt; k1 &lt; k2 ? -1 : k1 &gt; k2 ? 1 : v1 &lt; v2 ? -1 : v1 &gt; v2 ? 1 : 0).map((pair) &#x3D;&gt; pair.join(&quot;&#x3D;&quot;)).join(&quot;&amp;&quot;);  &#125;  async sign() &#123;    if (this.signQuery) &#123;      this.url.searchParams.set(&quot;X-Amz-Signature&quot;, await this.signature());      if (this.sessionToken &amp;&amp; this.appendSessionToken) &#123;        this.url.searchParams.set(&quot;X-Amz-Security-Token&quot;, this.sessionToken);      &#125;    &#125; else &#123;      this.headers.set(&quot;Authorization&quot;, await this.authHeader());    &#125;    return &#123;      method: this.method,      url: this.url,      headers: this.headers,      body: this.body    &#125;;  &#125;  async authHeader() &#123;    return [      &quot;AWS4-HMAC-SHA256 Credential&#x3D;&quot; + this.accessKeyId + &quot;&#x2F;&quot; + this.credentialString,      &quot;SignedHeaders&#x3D;&quot; + this.signedHeaders,      &quot;Signature&#x3D;&quot; + await this.signature()    ].join(&quot;, &quot;);  &#125;  async signature() &#123;    const date &#x3D; this.datetime.slice(0, 8);    const cacheKey &#x3D; [this.secretAccessKey, date, this.region, this.service].join();    let kCredentials &#x3D; this.cache.get(cacheKey);    if (!kCredentials) &#123;      const kDate &#x3D; await hmac(&quot;AWS4&quot; + this.secretAccessKey, date);      const kRegion &#x3D; await hmac(kDate, this.region);      const kService &#x3D; await hmac(kRegion, this.service);      kCredentials &#x3D; await hmac(kService, &quot;aws4_request&quot;);      this.cache.set(cacheKey, kCredentials);    &#125;    return buf2hex(await hmac(kCredentials, await this.stringToSign()));  &#125;  async stringToSign() &#123;    return [      &quot;AWS4-HMAC-SHA256&quot;,      this.datetime,      this.credentialString,      buf2hex(await hash(await this.canonicalString()))    ].join(&quot;\n&quot;);  &#125;  async canonicalString() &#123;    return [      this.method.toUpperCase(),      this.encodedPath,      this.encodedSearch,      this.canonicalHeaders + &quot;\n&quot;,      this.signedHeaders,      await this.hexBodyHash()    ].join(&quot;\n&quot;);  &#125;  async hexBodyHash() &#123;    let hashHeader &#x3D; this.headers.get(&quot;X-Amz-Content-Sha256&quot;) || (this.service &#x3D;&#x3D;&#x3D; &quot;s3&quot; &amp;&amp; this.signQuery ? &quot;UNSIGNED-PAYLOAD&quot; : null);    if (hashHeader &#x3D;&#x3D; null) &#123;      if (this.body &amp;&amp; typeof this.body !&#x3D;&#x3D; &quot;string&quot; &amp;&amp; !(&quot;byteLength&quot; in this.body)) &#123;        throw new Error(&quot;body must be a string, ArrayBuffer or ArrayBufferView, unless you include the X-Amz-Content-Sha256 header&quot;);      &#125;      hashHeader &#x3D; buf2hex(await hash(this.body || &quot;&quot;));    &#125;    return hashHeader;  &#125;&#125;;async function hmac(key, string) &#123;  const cryptoKey &#x3D; await crypto.subtle.importKey(    &quot;raw&quot;,    typeof key &#x3D;&#x3D;&#x3D; &quot;string&quot; ? encoder.encode(key) : key,    &#123; name: &quot;HMAC&quot;, hash: &#123; name: &quot;SHA-256&quot; &#125; &#125;,    false,    [&quot;sign&quot;]  );  return crypto.subtle.sign(&quot;HMAC&quot;, cryptoKey, encoder.encode(string));&#125;__name(hmac, &quot;hmac&quot;);async function hash(content) &#123;  return crypto.subtle.digest(&quot;SHA-256&quot;, typeof content &#x3D;&#x3D;&#x3D; &quot;string&quot; ? encoder.encode(content) : content);&#125;__name(hash, &quot;hash&quot;);var HEX_CHARS &#x3D; [&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;];function buf2hex(arrayBuffer) &#123;  const buffer &#x3D; new Uint8Array(arrayBuffer);  let out &#x3D; &quot;&quot;;  for (let idx &#x3D; 0; idx &lt; buffer.length; idx++) &#123;    const n &#x3D; buffer[idx];    out +&#x3D; HEX_CHARS[n &gt;&gt;&gt; 4 &amp; 15];    out +&#x3D; HEX_CHARS[n &amp; 15];  &#125;  return out;&#125;__name(buf2hex, &quot;buf2hex&quot;);function encodeRfc3986(urlEncodedStr) &#123;  return urlEncodedStr.replace(&#x2F;[!&#39;()*]&#x2F;g, (c) &#x3D;&gt; &quot;%&quot; + c.charCodeAt(0).toString(16).toUpperCase());&#125;__name(encodeRfc3986, &quot;encodeRfc3986&quot;);function guessServiceRegion(url, headers) &#123;  const &#123; hostname, pathname &#125; &#x3D; url;  if (hostname.endsWith(&quot;.on.aws&quot;)) &#123;    const match2 &#x3D; hostname.match(&#x2F;^[^.]&#123;1,63&#125;\.lambda-url\.([^.]&#123;1,63&#125;)\.on\.aws$&#x2F;);    return match2 !&#x3D; null ? [&quot;lambda&quot;, match2[1] || &quot;&quot;] : [&quot;&quot;, &quot;&quot;];  &#125;  if (hostname.endsWith(&quot;.r2.cloudflarestorage.com&quot;)) &#123;    return [&quot;s3&quot;, &quot;auto&quot;];  &#125;  if (hostname.endsWith(&quot;.backblazeb2.com&quot;)) &#123;    const match2 &#x3D; hostname.match(&#x2F;^(?:[^.]&#123;1,63&#125;\.)?s3\.([^.]&#123;1,63&#125;)\.backblazeb2\.com$&#x2F;);    return match2 !&#x3D; null ? [&quot;s3&quot;, match2[1] || &quot;&quot;] : [&quot;&quot;, &quot;&quot;];  &#125;  const match &#x3D; hostname.replace(&quot;dualstack.&quot;, &quot;&quot;).match(&#x2F;([^.]&#123;1,63&#125;)\.(?:([^.]&#123;0,63&#125;)\.)?amazonaws\.com(?:\.cn)?$&#x2F;);  let service &#x3D; match &amp;&amp; match[1] || &quot;&quot;;  let region &#x3D; match &amp;&amp; match[2];  if (region &#x3D;&#x3D;&#x3D; &quot;us-gov&quot;) &#123;    region &#x3D; &quot;us-gov-west-1&quot;;  &#125; else if (region &#x3D;&#x3D;&#x3D; &quot;s3&quot; || region &#x3D;&#x3D;&#x3D; &quot;s3-accelerate&quot;) &#123;    region &#x3D; &quot;us-east-1&quot;;    service &#x3D; &quot;s3&quot;;  &#125; else if (service &#x3D;&#x3D;&#x3D; &quot;iot&quot;) &#123;    if (hostname.startsWith(&quot;iot.&quot;)) &#123;      service &#x3D; &quot;execute-api&quot;;    &#125; else if (hostname.startsWith(&quot;data.jobs.iot.&quot;)) &#123;      service &#x3D; &quot;iot-jobs-data&quot;;    &#125; else &#123;      service &#x3D; pathname &#x3D;&#x3D;&#x3D; &quot;&#x2F;mqtt&quot; ? &quot;iotdevicegateway&quot; : &quot;iotdata&quot;;    &#125;  &#125; else if (service &#x3D;&#x3D;&#x3D; &quot;autoscaling&quot;) &#123;    const targetPrefix &#x3D; (headers.get(&quot;X-Amz-Target&quot;) || &quot;&quot;).split(&quot;.&quot;)[0];    if (targetPrefix &#x3D;&#x3D;&#x3D; &quot;AnyScaleFrontendService&quot;) &#123;      service &#x3D; &quot;application-autoscaling&quot;;    &#125; else if (targetPrefix &#x3D;&#x3D;&#x3D; &quot;AnyScaleScalingPlannerFrontendService&quot;) &#123;      service &#x3D; &quot;autoscaling-plans&quot;;    &#125;  &#125; else if (region &#x3D;&#x3D; null &amp;&amp; service.startsWith(&quot;s3-&quot;)) &#123;    region &#x3D; service.slice(3).replace(&#x2F;^fips-|^external-1&#x2F;, &quot;&quot;);    service &#x3D; &quot;s3&quot;;  &#125; else if (service.endsWith(&quot;-fips&quot;)) &#123;    service &#x3D; service.slice(0, -5);  &#125; else if (region &amp;&amp; &#x2F;-\d$&#x2F;.test(service) &amp;&amp; !&#x2F;-\d$&#x2F;.test(region)) &#123;    [service, region] &#x3D; [region, service];  &#125;  return [HOST_SERVICES[service] || service, region || &quot;&quot;];&#125;__name(guessServiceRegion, &quot;guessServiceRegion&quot;);&#x2F;&#x2F; index.jsvar UNSIGNABLE_HEADERS2 &#x3D; [  &quot;x-forwarded-proto&quot;,  &quot;x-real-ip&quot;,  &quot;accept-encoding&quot;,  &quot;if-match&quot;,  &quot;if-modified-since&quot;,  &quot;if-none-match&quot;,  &quot;if-range&quot;,  &quot;if-unmodified-since&quot;];var HTTPS_PROTOCOL &#x3D; &quot;https:&quot;;var HTTPS_PORT &#x3D; &quot;443&quot;;function filterHeaders(headers, env) &#123;  return new Headers(    Array.from(headers.entries()).filter((pair) &#x3D;&gt; !(UNSIGNABLE_HEADERS2.includes(pair[0]) || pair[0].startsWith(&quot;cf-&quot;) || &quot;ALLOWED_HEADERS&quot; in env &amp;&amp; !env[&quot;ALLOWED_HEADERS&quot;].includes(pair[0])))  );&#125;__name(filterHeaders, &quot;filterHeaders&quot;);function createHeadResponse(response) &#123;  return new Response(null, &#123;    headers: response.headers,    status: response.status,    statusText: response.statusText  &#125;);&#125;__name(createHeadResponse, &quot;createHeadResponse&quot;);var index_default &#x3D; &#123;  async fetch(request, env) &#123;    if (![&quot;GET&quot;, &quot;HEAD&quot;].includes(request.method)) &#123;      return new Response(null, &#123;        status: 405,        statusText: &quot;Method Not Allowed&quot;      &#125;);    &#125;    const url &#x3D; new URL(request.url);    url.protocol &#x3D; HTTPS_PROTOCOL;    url.port &#x3D; HTTPS_PORT;    let path &#x3D; url.pathname.replace(&#x2F;^\&#x2F;&#x2F;, &quot;&quot;).replace(&#x2F;\&#x2F;$&#x2F;, &quot;&quot;);    const isRootRequest &#x3D; path &#x3D;&#x3D;&#x3D; &quot;&quot;;    if (isRootRequest || url.pathname.startsWith(&quot;&#x2F;api&#x2F;&quot;)) &#123;      const objectPath &#x3D; isRootRequest ? &quot;&quot; : url.pathname.replace(&#x2F;^\&#x2F;api\&#x2F;&#x2F;, &quot;&quot;);      url.pathname &#x3D; objectPath;      url.hostname &#x3D; &#96;$&#123;env[&quot;BUCKET_NAME&quot;]&#125;.$&#123;env[&quot;B2_ENDPOINT&quot;]&#125;&#96;;      const headers &#x3D; filterHeaders(request.headers, env);      const client &#x3D; new AwsClient(&#123;        &quot;accessKeyId&quot;: env[&quot;B2_APPLICATION_KEY_ID&quot;],        &quot;secretAccessKey&quot;: env[&quot;B2_APPLICATION_KEY&quot;],        &quot;service&quot;: &quot;s3&quot;      &#125;);      const signedRequest &#x3D; await client.sign(url.toString(), &#123;        method: request.method,        headers      &#125;);      const response &#x3D; await fetch(signedRequest);      if (request.method &#x3D;&#x3D;&#x3D; &quot;HEAD&quot;) &#123;        return createHeadResponse(response);      &#125;      return response;    &#125;    return new Response(&quot;Not Found&quot;, &#123; status: 404 &#125;);  &#125;&#125;;export &#123;  index_default as default&#125;;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></details><p>然后点击部署，部署完成后在设置-变量与机密里设置变量名，依次填入刚刚创建的只读密钥Key、存储桶名称，存储桶访问Endpoint是一个域名，在你的桶信息里</p><img src="./../../images/原声音轨迁移至BackblazeB2/访问Endpoint.png" style="zoom:80%;" /><table><thead><tr><th>纯文本</th><th>ALLOW_LIST_BUCKET</th><th>true</th></tr></thead><tbody><tr><td>纯文本</td><td>B2_APPLICATION_KEY</td><td>你的Key</td></tr><tr><td>纯文本</td><td>B2_APPLICATION_KEY_ID</td><td>你的KeyID</td></tr><tr><td>纯文本</td><td>B2_ENDPOINT</td><td>你的访问ENDPOINT</td></tr><tr><td>纯文本</td><td>BUCKET_NAME</td><td>存储桶名称</td></tr></tbody></table><img src="./../../images/原声音轨迁移至BackblazeB2/配置变量.png" style="zoom:80%;" /><p>全部添加好后你可以打开Workers自带的域名后面加上&#x2F;api&#x2F;，例如：<br>cloudflare-b2.abab.workers.dev&#x2F;api&#x2F;<br>如果出现了如下内容就说明成功了！</p><img src="./../../images/原声音轨迁移至BackblazeB2/部署成功.png" style="zoom:80%;" /><h3 id="添加CDN缓存"><a href="#添加CDN缓存" class="headerlink" title="添加CDN缓存"></a>添加CDN缓存</h3><p>鉴于CloudflareWorkers每天只有（其实很多）10万次免费请求，而且每次都重新请求时效性不高，所以我们可以人CloudflareCDN缓存下来，打开Backblaze，找到你刚刚创建的桶，点击桶设定，在桶信息里添加如下内容：</p><pre class="line-numbers language-none"><code class="language-none">&#123;&quot;cache-control&quot;:&quot;public, max-age&#x3D;15552000&quot;&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>这个意思是让Cloudflare缓存内容，max-age标识缓存时间，我设置成了半年（因为我的音乐基本不会变动）你可以视情况修改，我建议经常更新的内容设置成24小时或72小时（max-age的单位是秒）</p><img src="./../../images/原声音轨迁移至BackblazeB2/CDN.png" style="zoom:80%;" /><p>怎么知道Cloudflare是否缓存了你的内容？很简单，上传张图片到桶的根目录，然后打开图片 https:&#x2F;&#x2F;你的Workers域名.workers.dev&#x2F;api&#x2F;图片名.jpg ，多刷新两次，然后按F12→网络→点击图片请求，如果cf-cache-status这一栏显示HIT就说明缓存成功了</p><h2 id="完成！"><a href="#完成！" class="headerlink" title="完成！"></a>完成！</h2><p>如果你一步步做并完成了没有报错的话，那么恭喜你有了一个任意文件床，你可以通过命令行上传任意文件，然后分发给大家下载、播放，鉴于CloudflareWorkers域名大概率被墙，你还可以设置自定义域</p><img src="./../../images/PageMeter/自定义域.png" style="zoom:80%;" /><p>搭配上Cloudflare的CDN，使用起来非常Nice，我的原声音轨播放网站已经完全迁至BackblazeB2储存，并且因为储存空间不再受到限制，我还添加了死亡细胞的原版、8bit版的原声音轨！</p><p>去我的原声音轨播放界面看看？<a href="https://music.hcyhub.com/">点击前往</a></p><p>对了，关于Backblaze和Cloudflare是流量联盟成员，Backblaze的流量走Cloudflare免费，这一点没有错，值得注意的是Backblaze的计费方式，Backblaze走Cloudflare的流量免费，这个不是不计费，而是先记在当日账单上，月底再扣除（会扣得很干净滴，不会收钱），所以如果你的流量限额设置得很低的话会导致当日账单满了而拒绝连接，所以最好把限额设置得高一点，Key要保管好啊。</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E5%8E%9F%E5%A3%B0%E9%9F%B3%E8%BD%A8%E8%BF%81%E7%A7%BB%E8%87%B3BackblazeB2</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E5%8E%9F%E5%A3%B0%E9%9F%B3%E8%BD%A8%E8%BF%81%E7%A7%BB%E8%87%B3BackblazeB2"/>
    <published>2025-04-04T13:52:09.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>众所周知我有一个<a href="https://music.hcyhub.com/">原声音轨播放网站</a>，原本我图省事将音乐和网页文件放置在一起的，但时间长了就慢慢有问题出现了：服务器空间不够了 <del>其实是贵</del>]]>
    </summary>
    <title>从存储到分发：使用Backblaze B2私有桶和Cloudflare Workers公开分发原声音轨</title>
    <updated>2025-12-01T11:23:23.316Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>kongregate是一个Flash游戏网站，提供大量的游戏（没有中文，*），而我刚好维护着一个Flash收藏站，这不得抓取里面的游戏下了汉化？于是我就这么“刚”上了kongregate，抓取，开始！</p><h2 id="抓取过程"><a href="#抓取过程" class="headerlink" title="抓取过程"></a>抓取过程</h2><h3 id="1-挑选受害者"><a href="#1-挑选受害者" class="headerlink" title="1.挑选受害者"></a>1.挑选受害者</h3><p><a href="https://flash.hcyhub.com/%E8%BF%B7%E4%BD%A0%E5%A1%94%E9%98%B2/">迷你塔防</a>，就这款塔防小游戏吧，第一步完成</p><h3 id="2-查看网络请求"><a href="#2-查看网络请求" class="headerlink" title="2.查看网络请求"></a>2.查看网络请求</h3><p>按F12打开浏览器的开发者工具，找到上方的<strong>“网络”</strong></p><p><img src="/../images/%E4%BF%9D%E5%AD%98kongregate%E4%B8%8A%E7%9A%84Flash%E6%B8%B8%E6%88%8F%E4%BB%A5%E4%BE%9B%E7%A6%BB%E7%BA%BF%E6%B8%B8%E7%8E%A9/%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7%EF%BC%8C%E7%BD%91%E7%BB%9C.png"></p><p>现在什么都没有对吧，按F5刷新一下页面你会发现加载了一大堆的网络请求，而我们要的SWF就在里面</p><h3 id="3-过滤数据"><a href="#3-过滤数据" class="headerlink" title="3.过滤数据"></a>3.过滤数据</h3><p>kongregate是通过GET请求获取地址的，返回的SWF地址格式如下所示：</p><pre class="line-numbers language-none"><code class="language-none">http:&#x2F;&#x2F;chat.kongregate.com&#x2F;gamez&#x2F;&lt;数字&gt;&#x2F;&lt;数字&gt;&#x2F;live&#x2F;&lt;游戏名&gt;.swf?kongregate_game_version&#x3D;&lt;数字&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>其中chat.kongregate.com域名可能是其他的域名，数字是<strong>随机</strong>的。</p><p>我们可以在刚刚加载的一堆请求中按Ctrl+F搜索 <code>chat.kongregate.com</code> ，<code>.swf</code> 如果你看到如下内容就说明你找到它了：</p><p><img src="/../images/%E4%BF%9D%E5%AD%98kongregate%E4%B8%8A%E7%9A%84Flash%E6%B8%B8%E6%88%8F%E4%BB%A5%E4%BE%9B%E7%A6%BB%E7%BA%BF%E6%B8%B8%E7%8E%A9/%E8%AF%B7%E6%B1%82%E8%BF%87%E6%BB%A4.png"></p><p>点击它，然后你就可以在右侧的</p><p><img src="/../images/%E4%BF%9D%E5%AD%98kongregate%E4%B8%8A%E7%9A%84Flash%E6%B8%B8%E6%88%8F%E4%BB%A5%E4%BE%9B%E7%A6%BB%E7%BA%BF%E6%B8%B8%E7%8E%A9/SWF%E5%9C%B0%E5%9D%80.png"></p><p>把这段地址复制出来：</p><pre class="line-numbers language-none"><code class="language-none">&#x2F;&#x2F;chat.kongregate.com&#x2F;gamez&#x2F;0007&#x2F;1458&#x2F;live&#x2F;miniTowerDefence.swf?kongregate_game_version&#x3D;1385373388<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>在浏览器中输入这段地址，如果浏览器开始了下载（如果你装了<strong>Ruffle</strong>插件那么你会看到游戏界面），恭喜你，你成功拿到了你要的SWF游戏。</p><h3 id="4-绕开、去除URL锁"><a href="#4-绕开、去除URL锁" class="headerlink" title="4.绕开、去除URL锁"></a>4.绕开、去除URL锁</h3><p>kongregate的游戏都有<strong>URL锁</strong>，顾名思义就是锁定该Flash游戏<strong>只能</strong>在<code>kongregate.com</code>这个域名中打开，无法放到其它网站上使用，这时候就需要用<a href="https://github.com/jindrapetrik/jpexs-decompiler">JPEXS Free Flash Decompiler</a>这款开源免费的Flash反编译软件进行反编译了，使用JPEXS打开刚刚下载的miniTowerDefence.swf，打开游戏的主文件，搜索 <code>URLLock</code> ：</p><p><img src="/../images/%E4%BF%9D%E5%AD%98kongregate%E4%B8%8A%E7%9A%84Flash%E6%B8%B8%E6%88%8F%E4%BB%A5%E4%BE%9B%E7%A6%BB%E7%BA%BF%E6%B8%B8%E7%8E%A9/%E5%8F%8D%E7%BC%96%E8%AF%91.png"></p><p>哎~这个URL锁的开关就这么明晃晃的摆在这儿，把true设置成false，再用Flash播放器打开，完事。（我想过一万种加密方式，但我就是没想到它很贴心的给我配了个开关🤣🤣🤣）</p><p>当然，一些简单的锁我们可以直接去除，但复杂的锁怎么办呢？</p><p>解决办法：</p><ul><li>找大佬帮解</li><li><del>V我50</del></li><li>欺骗SWF，通过在本地模拟网站让SWF以为它在kongregate.com上</li></ul><h4 id="模拟网站"><a href="#模拟网站" class="headerlink" title="模拟网站"></a>模拟网站</h4><p>安装nodejs，然后找个文件夹创建server.js文件并复制文末代码，并在server.js的目录下创建一个名为<strong>kongregate.com的文件夹</strong>，把刚刚下载的SWF文件<strong>移到kongregate.com</strong>里。</p><p>运行<code>node server.js</code>，浏览器打开<a href="http://localhost:3000/kongregate.com/%EF%BC%8C%E4%BD%A0%E5%BA%94%E8%AF%A5%E8%83%BD%E5%A4%9F%E7%9C%8B%E8%A7%81%E6%B8%B8%E6%88%8F%E7%95%8C%E9%9D%A2%E4%BA%86%EF%BC%88%E5%A6%82%E6%9E%9C%E4%BD%A0%E5%AE%89%E8%A3%85%E4%BA%86**Ruffle**%E6%8F%92%E4%BB%B6%E7%9A%84%E8%AF%9D%EF%BC%89">http://localhost:3000/kongregate.com/，你应该能够看见游戏界面了（如果你安装了**Ruffle**插件的话）</a></p><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">const</span> http <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'http'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> server <span class="token operator">=</span> http<span class="token punctuation">.</span><span class="token function">createServer</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    <span class="token keyword">const</span> filePath <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> req<span class="token punctuation">.</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token keyword">const</span> ext <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">extname</span><span class="token punctuation">(</span>filePath<span class="token punctuation">)</span><span class="token punctuation">;</span>    fs<span class="token punctuation">.</span><span class="token function">access</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> fs<span class="token punctuation">.</span>constants<span class="token punctuation">.</span><span class="token constant">F_OK</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>        <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>            res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token string-property property">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/plain'</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token string">'404 Not Found'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token keyword">return</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>        <span class="token keyword">const</span> mimeTypes <span class="token operator">=</span> <span class="token punctuation">&#123;</span>            <span class="token string-property property">'.swf'</span><span class="token operator">:</span> <span class="token string">'application/x-shockwave-flash'</span><span class="token punctuation">,</span>            <span class="token string-property property">'.html'</span><span class="token operator">:</span> <span class="token string">'text/html'</span><span class="token punctuation">,</span>            <span class="token string-property property">'.txt'</span><span class="token operator">:</span> <span class="token string">'text/plain'</span>        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>        <span class="token keyword">const</span> contentType <span class="token operator">=</span> mimeTypes<span class="token punctuation">[</span>ext<span class="token punctuation">]</span> <span class="token operator">||</span> <span class="token string">'application/octet-stream'</span><span class="token punctuation">;</span>        res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token string-property property">'Content-Type'</span><span class="token operator">:</span> contentType <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        fs<span class="token punctuation">.</span><span class="token function">createReadStream</span><span class="token punctuation">(</span>filePath<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>server<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Server running at http://localhost:3000/'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>好了，可以愉快的玩耍了。</p><p>我的Flash收藏站：<a href="https://flash.hcyhub.com/">https://flash.hcyhub.com</a></p><p><del>你还在等什么？去玩啊！</del></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%BF%9D%E5%AD%98kongregate%E4%B8%8A%E7%9A%84Flash%E6%B8%B8%E6%88%8F%E4%BB%A5%E4%BE%9B%E7%A6%BB%E7%BA%BF%E6%B8%B8%E7%8E%A9</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%BF%9D%E5%AD%98kongregate%E4%B8%8A%E7%9A%84Flash%E6%B8%B8%E6%88%8F%E4%BB%A5%E4%BE%9B%E7%A6%BB%E7%BA%BF%E6%B8%B8%E7%8E%A9"/>
    <published>2025-03-29T15:24:39.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>kongregate是一个Flash游戏网站，提供大量的游戏（没有中文，*），而我刚好维护着一个Flash收藏站，这不得抓取里面的游戏下了汉化？于是我就这么“刚”上了kongregate，抓取，开始！</p>
<h2 id="抓取过程"><a href="#抓取过程" class="headerlink"]]>
    </summary>
    <title>保存kongregate上的Flash游戏以供离线游玩</title>
    <updated>2025-12-01T11:21:33.606Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <category term="PageMeter" scheme="https://hcyhub.com/tags/PageMeter/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="PageMeter"><a href="#PageMeter" class="headerlink" title="PageMeter"></a>PageMeter</h1><p>一个使用CloudflareWorkers做后端，D1做数据库的网站访问次数记录器，类似不算子</p><p>查看在线演示：<a href="https://page.hcyhub.com/%E7%A4%BA%E4%BE%8B">PageMeter计数器示例</a></p><p>为什么要做这个项目？因为不算子实在是太不稳定了，基本不可能加载出数据，统计功能也是可有可无。但如果使用大大善人Cloudflare搭建，不仅能够稳定，数据也完全掌握在自己的手中，我的博客现在使用的就是PageMeter。</p><p>下面开始部署教程：</p><h2 id="1-后端部署："><a href="#1-后端部署：" class="headerlink" title="1.后端部署："></a>1.后端部署：</h2><ol><li><p>注册或登录Cloudflare（废话）</p></li><li><p>创建一个D1数据库，名称随意，但要记住后面要用，这里我的名称叫PageMeter</p><img src="/images/PageMeter/创建数据库.png" style="zoom:80%;" /></li><li><p>进入数据库详情，找到控制台，在控制台中依次输入以下命令初始化数据库：</p><pre class="line-numbers language-none"><code class="language-none">CREATE TABLE post (  url TEXT PRIMARY KEY,  visit_count INTEGER DEFAULT 0,  visitor_count INTEGER DEFAULT 0);<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><pre class="line-numbers language-none"><code class="language-none">CREATE TABLE site (  domain TEXT PRIMARY KEY,  visit_count INTEGER DEFAULT 0,  visitor_count INTEGER DEFAULT 0);<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><img src="/images/PageMeter/初始化数据库.png" style="zoom:80%;" /><p>然后打开表，如果你看到了如下信息就说明成功了</p><table><thead><tr><th align="left">名称</th><th align="left">列</th></tr></thead><tbody><tr><td align="left"><a href="https://dash.cloudflare.com/57e18b4fb317b217ebf8b0f74415ab9e/workers/d1/databases/d86fca60-255b-49cc-b467-ea2d5c94b998/tables/post">post</a></td><td align="left">3</td></tr><tr><td align="left"><a href="https://dash.cloudflare.com/57e18b4fb317b217ebf8b0f74415ab9e/workers/d1/databases/d86fca60-255b-49cc-b467-ea2d5c94b998/tables/site">site</a></td><td align="left">3</td></tr></tbody></table><img src="/images/PageMeter/初始化完毕.png" style="zoom:80%;" /></li><li><p>打开Workers和Pages，创建一个Workers，选HelloWorld</p><img src="/images/PageMeter/创建Workers.png" style="zoom:80%;" /><img src="/images/PageMeter/模板选择.png" style="zoom:80%;" /></li><li><p>创建好后点击编辑代码，把原来的代码统统删掉，然后把 <a href="/src/index.js">这里的代码</a> 复制粘贴进去，然后点击右上角部署</p><img src="/images/PageMeter/编辑代码.png" style="zoom:80%;" /><img src="/images/PageMeter/编辑代码、部署.png" style="zoom:80%;" /></li><li><p>由于CloudflareWorkers自带的域名在中国大陆被墙，基本不可能使用，所以我们还要添加自定义域，转到设置→域和路由→自定义域，输入一个域名，需要托管在Cloudflare上</p><img src="/images/PageMeter/自定义域.png" style="zoom:80%;" /></li><li><p>完成！你可以输入你的自定义域，出现“部署成功”的字样就说明你部署好了后端</p></li></ol><h2 id="2-前端应用"><a href="#2-前端应用" class="headerlink" title="2.前端应用"></a>2.前端应用</h2><ol><li><p>先下载<a href="https://github.com/2010HCY/PageMeter/releases/download/1.0.1/blog-count.js">blog-count.js</a>文件</p></li><li><p>打开下载好的blog-count.js，把里面第六行中的</p><pre class="line-numbers language-none"><code class="language-none">const baseUrl &#x3D; &#96;https:&#x2F;&#x2F;&lt;你的域名&gt;&#x2F;visitor-count?target&#x3D;$&#123;encodeURIComponent(target)&#125;&#96;;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>&lt;你的域名&gt;换成你前面后端部署的域名</p></li><li><p>打开你要插入访问量统计显示的页面，引入JS文件<code>&lt;script async src=&quot;/blog-count.js&quot;&gt;&lt;/script&gt;</code>注意你要把src&#x3D;””字段替换成你实际存放blog-count.js的路径</p></li><li><p>然后在你希望显示访问量的地方安装标签：</p><pre class="line-numbers language-none"><code class="language-none">本站总阅读量&lt;span id&#x3D;&quot;PageMeter_site_pv&quot;&gt;&lt;&#x2F;span&gt;次<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></li></ol><p>完成！JS脚本会自动替换<code>&lt;span id=&quot;PageMeter_site_pv&quot;&gt;&lt;/span&gt;</code>字段将其替换成实际访问数据，PageMeter支持的标签有以下四种：</p><p>统计站点pv</p><pre class="line-numbers language-none"><code class="language-none">本站总阅读量&lt;span id&#x3D;&quot;PageMeter_site_pv&quot;&gt;&lt;&#x2F;span&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>统计站点uv</p><pre class="line-numbers language-none"><code class="language-none">本站访客数&lt;span id&#x3D;&quot;PageMeter_site_uv&quot;&gt;&lt;&#x2F;span&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>统计页面pv</p><pre class="line-numbers language-none"><code class="language-none">本文总阅读量&lt;span id&#x3D;&quot;PageMeter_page_pv&quot;&gt;&lt;&#x2F;span&gt;<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>统计页面uv</p><pre><code>本文总访客数&lt;span id=&quot;PageMeter_page_uv&quot;&gt;&lt;/span&gt;</code></pre><blockquote><p>uv是访客数，pv是阅读数</p></blockquote>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E8%87%AA%E5%BB%BA%E4%B8%8D%E7%AE%97%E5%AD%90-%E6%88%91%E5%BC%80%E5%8F%91%E7%9A%84PageMeter</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E8%87%AA%E5%BB%BA%E4%B8%8D%E7%AE%97%E5%AD%90-%E6%88%91%E5%BC%80%E5%8F%91%E7%9A%84PageMeter"/>
    <published>2025-03-26T09:40:06.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="PageMeter"><a href="#PageMeter" class="headerlink" title="PageMeter"></a>PageMeter</h1><p>一个使用CloudflareWorkers做后端，D1做数据库的网站访问次数记录器，类似不算子</p>
<p>查看在线演示：<a]]>
    </summary>
    <title>自建不算子-我开发的PageMeter</title>
    <updated>2025-12-01T11:23:36.659Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <category term="工具" scheme="https://hcyhub.com/tags/%E5%B7%A5%E5%85%B7/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Status监控页面"><a href="#Status监控页面" class="headerlink" title="Status监控页面"></a>Status监控页面</h1><p>话不多说，先上效果图（页面经过缩放）</p><img src="../../images/效果图.png" style="zoom:80%;" /><p>支持功能：</p><ol><li>使用Cron定时器每隔半小时自动请求目标站点，获取运行状态</li><li>手动运行监测，通过访问&#x2F;api&#x2F;refresh?key&#x3D;&lt;你的密钥&gt; 来手动运行一次站点监测</li></ol><p>使用KV储存数据，KV只要不频繁的写入，一天10万次读取额度和Workers一样，够够的。</p><p><a href="https://deploy.workers.cloudflare.com/?url=https://github.com/2010HCY/status-monitor"><img src="https://deploy.workers.cloudflare.com/button" alt="Deploy to Cloudflare Workers"></a></p><p>部署很简单，点击上方的一键部署，部署好后去Workers设置里修改KEY变量，修改成你想要设置的值</p><p>我的云端页面也都接入了此监控页面，你可以打开<a href="https://status.100713.xyz/%E6%9F%A5%E7%9C%8B">https://status.100713.xyz/查看</a></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%BD%BF%E7%94%A8Cloudflare%E6%90%AD%E5%BB%BAStatus%E7%9B%91%E6%8E%A7%E9%A1%B5%E9%9D%A2</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E4%BD%BF%E7%94%A8Cloudflare%E6%90%AD%E5%BB%BAStatus%E7%9B%91%E6%8E%A7%E9%A1%B5%E9%9D%A2"/>
    <published>2025-03-26T09:40:06.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="Status监控页面"><a href="#Status监控页面" class="headerlink" title="Status监控页面"></a>Status监控页面</h1><p>话不多说，先上效果图（页面经过缩放）</p>
<img src="../../images/效果图.png" style="zoom:80%;"]]>
    </summary>
    <title>使用Cloudflare搭建Status监控页面</title>
    <updated>2025-06-06T01:47:16.443Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="干货文章" scheme="https://hcyhub.com/tags/%E5%B9%B2%E8%B4%A7%E6%96%87%E7%AB%A0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="PCB常见标识大全"><a href="#PCB常见标识大全" class="headerlink" title="PCB常见标识大全"></a>PCB常见标识大全</h2><h2 id="常见信号标识"><a href="#常见信号标识" class="headerlink" title="常见信号标识"></a>常见信号标识</h2><table><thead><tr><th><strong>标识符</strong></th><th>说明</th><th>类型</th></tr></thead><tbody><tr><td><strong>VCC（Voltage at Common Collector）</strong></td><td>表示电源的正极，通常为电压源连接至电路中的正电压。</td><td><strong>电源（Power）信号标识</strong></td></tr><tr><td><strong>VDD（Voltage at Drain）</strong></td><td>表示用于集成电路的电源电压，通常是CMOS电路的供电电源。</td><td><strong>电源（Power）信号标识</strong></td></tr><tr><td><strong>GND（Ground）</strong></td><td>表示电路的接地或零电位，所有电流的返回路径。通常与负电源电压相对应。</td><td><strong>电源（Power）信号标识</strong></td></tr><tr><td><strong>VSS（Voltage at Source）</strong></td><td>与GND相似，通常指代CMOS电路的接地端。</td><td><strong>电源（Power）信号标识</strong></td></tr><tr><td><strong>CLK（Clock）</strong></td><td>表示时钟信号，用于时序控制。通常是周期性方波，用于同步数据传输。</td><td><strong>信号线（Signal Line）标识</strong></td></tr><tr><td><strong>DATA</strong></td><td>表示数据线，用于在电路中传输信息。数据线可能是单向或双向的。</td><td><strong>信号线（Signal Line）标识</strong></td></tr><tr><td><strong>RST（Reset）</strong></td><td>表示复位信号，通常用于重新启动设备或重置电路状态。</td><td><strong>信号线（Signal Line）标识</strong></td></tr><tr><td><strong>CS（Chip Select）</strong></td><td>芯片选择信号，通常用于选择某个特定的集成电路或外设。</td><td><strong>信号线（Signal Line）标识</strong></td></tr><tr><td><strong>TX（Transmit）</strong></td><td>表示传输信号，通常是串行数据通信中的发送端信号。</td><td><strong>数字信号标识</strong></td></tr><tr><td><strong>RX（Receive）</strong></td><td>表示接收信号，通常是串行数据通信中的接收端信号。</td><td><strong>数字信号标识</strong></td></tr><tr><td><strong>SCL（Serial Clock Line）</strong></td><td>用于I2C通信协议的时钟信号。</td><td><strong>数字信号标识</strong></td></tr><tr><td><strong>SDA（Serial Data Line）</strong></td><td>用于I2C通信协议的数据线。</td><td><strong>数字信号标识</strong></td></tr><tr><td><strong>ANALOG（Analog）</strong></td><td>表示模拟信号线，用于传输连续变化的电压信号。</td><td><strong>模拟信号标识</strong></td></tr><tr><td><strong>VREF（Reference Voltage）</strong></td><td>参考电压信号，常用于设置电路的基准电压。</td><td><strong>模拟信号标识</strong></td></tr><tr><td><strong>TEMP（Temperature）</strong></td><td>温度传感器的信号线，通常是模拟信号，用于获取温度数据。</td><td><strong>模拟信号标识</strong></td></tr><tr><td><strong>IRQ（Interrupt Request）</strong></td><td>表示中断请求信号，用于表示需要处理的优先事件。</td><td><strong>中断（Interrupt）信号标识</strong></td></tr><tr><td><strong>INT（Interrupt）</strong></td><td>与IRQ类似，但有时可以用作中断信号的通用标识。</td><td><strong>中断（Interrupt）信号标识</strong></td></tr><tr><td><strong>LEVEL（Level Shifter）</strong></td><td>电平转换信号，用于在不同电压级别的电路间传输信号。</td><td><strong>电平转换信号标识</strong></td></tr><tr><td><strong>AD（Address）</strong></td><td>表示地址信号，通常用于指定存储器或外设的地址。</td><td><strong>总线信号标识</strong></td></tr><tr><td><strong>RD（Read）</strong></td><td>表示读取信号，用于从存储器或外设读取数据。</td><td><strong>总线信号标识</strong></td></tr><tr><td><strong>WR（Write）</strong></td><td>表示写入信号，用于将数据写入存储器或外设。</td><td><strong>总线信号标识</strong></td></tr><tr><td><strong>TDI（Test Data In）</strong></td><td>用于JTAG测试接口，表示测试数据输入信号。</td><td><strong>调试和测试信号标识</strong></td></tr><tr><td><strong>TDO（Test Data Out）</strong></td><td>用于JTAG测试接口，表示测试数据输出信号。</td><td><strong>调试和测试信号标识</strong></td></tr><tr><td><strong>TMS（Test Mode Select）</strong></td><td>用于JTAG接口，表示选择测试模式信号。</td><td><strong>调试和测试信号标识</strong></td></tr><tr><td><strong>SENSE（Current Sense）</strong></td><td>表示电流感应信号，用于监测电流流动。</td><td><strong>电流信号标识</strong></td></tr><tr><td><strong>OVP（Over Voltage Protection）</strong></td><td>过压保护信号，用于监测电压是否超过安全限度。</td><td><strong>保护信号标识</strong></td></tr><tr><td><strong>OCP（Over Current Protection）</strong></td><td>过流保护信号，用于监测电流是否超过安全限度。</td><td><strong>保护信号标识</strong></td></tr></tbody></table><h3 id="常见元器件标识"><a href="#常见元器件标识" class="headerlink" title="常见元器件标识"></a>常见元器件标识</h3><p>这个分类是PCB上的元器件标识，例如电容是C，二极管是D，通常在PCB的丝印上一个字母后还会跟着一个数字，例如C100，这说明这是这块PCB上第100个电容</p><table><thead><tr><th><strong>标识符号</strong></th><th><strong>含义</strong></th></tr></thead><tbody><tr><td><strong>A</strong></td><td>可分离组件或子组件（如印刷电路组件）：用于表示电路中的可分离的部分或子组件。</td></tr><tr><td><strong>AT</strong></td><td>衰减器或隔离器（Attenuator or Isolator）：用于降低信号强度或隔离电路中的不同部分。</td></tr><tr><td><strong>B</strong></td><td>电池（Battery）：用于提供电源，储存化学能转化为电能。</td></tr><tr><td><strong>BR</strong></td><td>桥式整流器（Bridge Rectifier）：将交流电（AC）转换为直流电（DC）。</td></tr><tr><td><strong>BT</strong></td><td>电池（Battery）：提供电源，储存化学能转化为电能。</td></tr><tr><td><strong>C</strong></td><td>电容器（Capacitor）：储存电能并平滑电流，通常用于滤波。</td></tr><tr><td><strong>CN</strong></td><td>电容网络（Capacitor Network）：多个电容器组成的网络，用于特定应用。</td></tr><tr><td><strong>D, CR</strong></td><td>二极管（所有类型，包括LED）、晶闸管（Diode, Thyristor）：控制电流流向，常用于整流、保护电路。</td></tr><tr><td><strong>DL</strong></td><td>延迟线（Delay Line）：延迟信号的传播，用于时钟电路等。</td></tr><tr><td><strong>DS</strong></td><td>显示器、通用光源、灯、信号灯（Display, General Light Source, Lamp, Signal Light）：显示或指示状态，常用于显示界面或状态指示。</td></tr><tr><td><strong>F</strong></td><td>保险丝（Fuse）：用于保护电路免受过载或短路的损害。</td></tr><tr><td><strong>FB</strong></td><td>铁素体磁珠（Ferrite Bead）：用于滤波，抑制高频噪声。</td></tr><tr><td><strong>FD</strong></td><td>基准（Reference）：提供稳定的参考信号，常用于精确控制和比较。</td></tr><tr><td><strong>FL</strong></td><td>过滤器（Filter）：去除电路中的不需要的频率或信号。</td></tr><tr><td><strong>G</strong></td><td>发生器或振荡器（Generator or Oscillator）：产生特定频率的信号。</td></tr><tr><td><strong>GN</strong></td><td>广义网络（General Network）：表示电路中的广泛网络或多功能组件。</td></tr><tr><td><strong>H</strong></td><td>加热元件（Heater）：用于加热应用的电阻元件。</td></tr><tr><td><strong>H</strong></td><td>硬件，如螺钉、螺母、垫圈（Hardware, e.g., screws, nuts, washers）：用于连接和固定电路中的其他元件。</td></tr><tr><td><strong>HY</strong></td><td>循环器或定向耦合器（Circulator or Directional Coupler）：控制信号流动的方向。</td></tr><tr><td><strong>IR</strong></td><td>红外二极管（Infrared Diode）：用于红外信号的发射和接收。</td></tr><tr><td><strong>J</strong></td><td>插孔（连接器对中最小的可移动连接器）（Jack, smallest movable connector）：提供电路连接的插口。</td></tr><tr><td><strong>JP</strong></td><td>跳线（链路）（Jumper, Link）：连接电路中不同部分的跳线，用于开关或配置电路。</td></tr><tr><td><strong>K</strong></td><td>继电器或接触器（Relay or Contactor）：控制电路中的开关操作。</td></tr><tr><td><strong>L</strong></td><td>电感器或线圈或铁氧体磁珠（Inductor, Coil, Ferrite Bead）：储存磁能并滤除高频噪声。</td></tr><tr><td><strong>LS</strong></td><td>扬声器或蜂鸣器（Loudspeaker or Buzzer）：用于声音输出或警告信号。</td></tr><tr><td><strong>M</strong></td><td>电机（Motor）：将电能转化为机械能。</td></tr><tr><td><strong>MK</strong></td><td>麦克风（Microphone）：用于接收声音信号并转化为电信号。</td></tr><tr><td><strong>MP</strong></td><td>中压机械部件（包括螺钉和紧固件）（Medium Pressure Mechanical Part）：用于紧固和连接电路的机械组件。</td></tr><tr><td><strong>OP</strong></td><td>光隔离器（Opto-Isolator）：通过光信号传输电信号，隔离电路。</td></tr><tr><td><strong>P</strong></td><td>插头（连接器对中最可移动的连接器）（Plug, most movable connector）：用于电路连接的插头。</td></tr><tr><td><strong>PS</strong></td><td>电源（Power Supply）：提供稳定的电能以驱动电路。</td></tr><tr><td><strong>Q</strong></td><td>晶体管（所有类型）（Transistor, all types）：放大信号或用于开关控制。</td></tr><tr><td><strong>R</strong></td><td>电阻器（Resistor）：限制电流或分压。</td></tr><tr><td><strong>RN</strong></td><td>电阻网络（Resistor Network）：多个电阻器组成的网络，用于特定电路应用。</td></tr><tr><td><strong>RT</strong></td><td>热敏电阻（Thermistor）：根据温度变化调整电阻值。</td></tr><tr><td><strong>RV</strong></td><td>变阻器，可变电阻器（Variable Resistor）：用于调整电阻值，调节电流或电压。</td></tr><tr><td><strong>S</strong></td><td>开关（所有类型，包括按钮）（Switch, all types）：用于控制电路的开关。</td></tr><tr><td><strong>T</strong></td><td>变压器（Transformer）：用于电压的升高或降低。</td></tr><tr><td><strong>TC</strong></td><td>热电偶（Thermocouple）：用于温度测量和温度控制。</td></tr><tr><td><strong>TP</strong></td><td>测试点（Test Point）：用于电路的调试和测试。</td></tr><tr><td><strong>TUN</strong></td><td>调谐器（Tuner）：用于调整接收信号的频率。</td></tr><tr><td><strong>U</strong></td><td>集成电路（IC）（Integrated Circuit）：将多个电子元件集成到一个封装中。</td></tr><tr><td><strong>V</strong></td><td>真空管（Vacuum Tube）：用于音频放大和一些电子设备中。</td></tr><tr><td><strong>VR</strong></td><td>电压调节器（参考电压）、可变电阻器（Voltage Regulator, Variable Resistor）：用于调节电压或电流。</td></tr><tr><td><strong>X</strong></td><td>另一个项目的插座连接器，不是P或J（Socket for Another Item）：用于电路中的插座连接器。</td></tr><tr><td><strong>XTAL</strong></td><td>晶体（Crystal）：用于提供稳定的频率参考信号。</td></tr><tr><td><strong>Y</strong></td><td>晶体或振荡器（Crystal or Oscillator）：用于生成精确的频率信号，常见于时钟电路。</td></tr></tbody></table><h3 id="常见标准认证标识"><a href="#常见标准认证标识" class="headerlink" title="常见标准认证标识"></a>常见标准认证标识</h3><p>这是电器设备通常会经过的认证，它们会以丝印的方式出现在PCB上，可以分为：<strong>国际化</strong>、<strong>最严格</strong>、<strong>最宽松</strong>、<strong>地区国家标准</strong>、<strong>其他</strong>这五个分类，常见的3C认证属于地区国家认证。</p><p>这些认证中，<strong>ISO 9001</strong> 和 <strong>CE</strong> 是最常见且国际化的认证，而 <strong>UL</strong> 和 <strong>TÜV</strong> 代表了最严格的产品认证，确保高安全性和高可靠性。</p><h4 id="国际化认证（Global-Certifications）"><a href="#国际化认证（Global-Certifications）" class="headerlink" title="国际化认证（Global Certifications）"></a><strong>国际化认证（Global Certifications）</strong></h4><p>这个分类是国际化的认证标准，在全球范围内得到广泛认可和遵守，使用最为广泛通常适用于面向全球市场的产品。</p><table><thead><tr><th><strong>ISO 9001</strong></th><th>质量管理体系认证，广泛应用于各类工业产品的生产，确保产品符合质量管理标准。</th></tr></thead><tbody><tr><td><strong>ISO 14001</strong></td><td>环境管理体系认证，确保生产过程中符合环保要求。</td></tr><tr><td><strong>UL</strong></td><td>美国保险商试验所认证，涵盖产品安全、电气设备等。</td></tr><tr><td><strong>CE</strong></td><td>欧洲市场产品认证，确保产品符合欧洲的安全、健康和环保要求。</td></tr><tr><td><strong>ROHS</strong></td><td>欧盟关于有害物质限制的指令，确保电子产品中不含有害物质。</td></tr><tr><td><strong>WEEE</strong></td><td>废弃电子电气设备指令，旨在规范电子产品的回收与废弃处理。</td></tr><tr><td><strong>IEC 61000</strong></td><td>国际电工委员会的电磁兼容性标准，规定了电子产品对电磁干扰的容忍度。</td></tr><tr><td><strong>REACH</strong></td><td>欧盟化学品注册、评估、授权和限制法规，确保产品不含有害化学物质。</td></tr></tbody></table><h4 id="严格认证（Stringent-Certifications）"><a href="#严格认证（Stringent-Certifications）" class="headerlink" title="严格认证（Stringent Certifications）"></a><strong>严格认证（Stringent Certifications）</strong></h4><p>这些认证通常用于对安全、质量和环境要求极高的行业，如汽车、医疗、航空等。认证标准要求非常严格，需要经过非常详细的测试和验证。</p><table><thead><tr><th><strong>ISO&#x2F;TS 16949</strong></th><th>适用于汽车行业的质量管理体系认证，涉及PCB生产中严格的质量控制。</th></tr></thead><tbody><tr><td><strong>UL 94</strong></td><td>塑料材料的可燃性测试，广泛应用于电子产品中，特别是PCB的材料和组件。</td></tr><tr><td><strong>TÜV</strong></td><td>技术监督协会认证，德国标准，非常严格的产品安全认证，适用于电子产品。</td></tr><tr><td><strong>EAC</strong></td><td>欧亚经济联盟认证，要求符合该地区的多项安全标准。</td></tr><tr><td><strong>ISO 13485</strong></td><td>医疗器械质量管理体系认证，要求更高的生产和质量控制标准。</td></tr><tr><td><strong>ISO 27001</strong></td><td>信息安全管理认证，确保生产过程中数据安全，适用于高敏感度设备的PCB生产。</td></tr></tbody></table><h4 id="宽松认证（Lenient-Certifications）"><a href="#宽松认证（Lenient-Certifications）" class="headerlink" title="宽松认证（Lenient Certifications）"></a>宽松认证（Lenient Certifications）</h4><p>这些认证相对较为宽松，主要面向低风险、低复杂度或局部市场的东东，认证要求不如其他认证那样复杂，主要侧重于最基本的安全标准。</p><table><thead><tr><th><strong>PSE</strong></th><th>日本电气用品安全法认证，虽然较为宽松，但适用于大多数电子产品。</th></tr></thead><tbody><tr><td><strong>SAA</strong></td><td>澳大利亚和新西兰标准认证，要求产品满足一定的电气安全标准，适用于PCB。</td></tr><tr><td><strong>BSI</strong></td><td>英国标准协会认证，适用于广泛的产品，较为宽松。</td></tr><tr><td><strong>KCS</strong></td><td>韩国认证标准，涵盖了多个领域，包括PCB的基本安全标准。</td></tr></tbody></table><h4 id="地区、国家认证（National-Certifications）"><a href="#地区、国家认证（National-Certifications）" class="headerlink" title="地区、国家认证（National Certifications）"></a><strong>地区、国家认证（National Certifications）</strong></h4><p>这些认证是国家或地区政府颁发的法律强制或行业标准，地域性强，你通过了其中一个不一定就能在其他地区销售</p><table><thead><tr><th><strong>3C（中国强制性认证）</strong></th><th>中国的强制性产品认证，涉及到电子产品的质量与安全要求，必须获得认证才能上市。</th></tr></thead><tbody><tr><td><strong>CQC</strong></td><td>中国质量认证中心，确保产品符合中国大陆的质量标准。</td></tr><tr><td><strong>KC（韩国认证）</strong></td><td>用于确保产品符合韩国的安全标准。</td></tr><tr><td><strong>BIS（印度标准局）</strong></td><td>确保产品符合印度的质量要求。</td></tr><tr><td><strong>GOST</strong></td><td>俄罗斯的国家标准，涉及到PCB及电子产品的认证。</td></tr><tr><td><strong>PSE（日本）</strong></td><td>确保电气产品符合日本的电气安全标准。</td></tr></tbody></table><h4 id="其他常见认证（Common-Certifications）"><a href="#其他常见认证（Common-Certifications）" class="headerlink" title="其他常见认证（Common Certifications）"></a>其他常见认证（Common Certifications）</h4><p>这几个认证具有较高的可接受性和应用频率，嗯…不知道划分到哪个分类</p><table><thead><tr><th><strong>TÜV Rheinland</strong></th><th>德国的安全认证机构，针对电子产品的安全性、可靠性进行认证。</th></tr></thead><tbody><tr><td><strong>NRTL</strong></td><td>美国的国家认可测试实验室认证，保证产品符合美国安全标准。</td></tr><tr><td><strong>C-Tick</strong></td><td>澳大利亚和新西兰的电子产品电磁兼容性认证。</td></tr></tbody></table><h3 id="常见图形符号标识"><a href="#常见图形符号标识" class="headerlink" title="常见图形符号标识"></a>常见图形符号标识</h3><table><thead><tr><th><img src="/images/PCB%E5%B8%B8%E8%A7%81%E6%A0%87%E8%AF%86%E5%A4%A7%E5%85%A8/WEEE%E6%A0%87%E8%AF%86.jpg" alt="WEEE标识"><br />这是<strong>电池回收标识</strong>，通常为一个带有箭头的垃圾桶图标，表示产品含有可回收的电池，需按照当地规定进行回收处理，不可以丢垃圾桶里</th><th><img src="/images/PCB常见标识大全/中国环保标志.png" alt="中国环境保护标识" style="zoom:38%;" /><br />中国环境标志认证（十环认证)是表明该产品不仅质量合格，而且在生产、使用和处理处置过程中符合特定的环境保护要求</th><th><img src="/images/PCB常见标识大全/RoHS标识.jpg" alt="RoSH标识" style="zoom:80%;" /><br />中国ROHS有二种标示,如果是一个e样的绿色箭头且没有标数字的，说明此产品为环保产品，是永远有效的，如果该标识是红色圆里有个10说明此产品回收有效期是10年，10年后会污染环境</th></tr></thead><tbody><tr><td><img src="/images/PCB常见标识大全/IP67防水标识.jpg" alt="IP67防水标识" style="zoom:90%;" /><br />该标识表示产品防尘且可承受短时间的浸水</td><td><img src="/images/PCB常见标识大全/IP68防水标识.jpg" alt="IP68防水标识" style="zoom:80%;" /><br />该标识表示产品防尘且可在规定条件下长时间浸水。</td><td><img src="/images/PCB常见标识大全/无铅标识.png" alt="无铅标识" style="zoom:80%;" /><br />无铅标识表示产品符合无铅要求，符合RoHS等环保标准。</td></tr><tr><td><img src="/images/PCB常见标识大全/静电敏感元件.jpg" alt="静电敏感元件" style="zoom:80%;" /><br />防静电标识用于指示产品对静电敏感，需要采取防静电措施，通常配有“防静电”或“ESD敏感”字样</td><td></td><td></td></tr></tbody></table>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/PCB%E5%B8%B8%E8%A7%81%E6%A0%87%E8%AF%86%E5%A4%A7%E5%85%A8</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/PCB%E5%B8%B8%E8%A7%81%E6%A0%87%E8%AF%86%E5%A4%A7%E5%85%A8"/>
    <published>2025-02-15T15:55:54.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="PCB常见标识大全"><a href="#PCB常见标识大全" class="headerlink" title="PCB常见标识大全"></a>PCB常见标识大全</h2><h2 id="常见信号标识"><a href="#常见信号标识" class="headerlink"]]>
    </summary>
    <title>PCB常见标识大全（全网最全）</title>
    <updated>2025-12-01T11:26:53.510Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="新的一年，祝大家："><a href="#新的一年，祝大家：" class="headerlink" title="新的一年，祝大家："></a>新的一年，祝大家：</h2><p>电势 磁势 引力势 事事得势<br>重力 弹力 摩擦力 处处给力<br>匀速 加速 超音速 致富加速<br>动能 势能 机械能 万事皆能<br>质心 重心 几何心 天天顺心<br>强电 弱电 交流电 秒秒来电<br>重子 轻子 中微子 龙门贵子<br>虚像 实像 等大像 人人福像<br>积分 差分 偏微分 门门满分<br>动量 冲量 作用量 前途无量<br>恒星 行星 脉冲星 满天福星<br>阴极 阳极 南北极 登峰造极<br>电场 磁场 规范场 宏大气场<br>自转 公转 螺旋转 行行玩转<br>平面 曲面 抛物面 有里有面<br>散度 旋度 自由度 大方有度<br>牛顿 莱顿 哈密顿 大吃一顿<br>三维 四维 十一维 精准思维<br>气流 湍流 交直流 一代风流<br>气态 液态 双稳态 万方仪态<br>固体 导体 半导体 处处得体<br><img id="Emoji"  src="/images/狗头.png"></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%96%B0%E6%98%A5%E7%A5%9D%E7%A6%8F</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%96%B0%E6%98%A5%E7%A5%9D%E7%A6%8F"/>
    <published>2025-02-02T14:29:13.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="新的一年，祝大家："><a href="#新的一年，祝大家：" class="headerlink" title="新的一年，祝大家："></a>新的一年，祝大家：</h2><p>电势 磁势 引力势 事事得势<br>重力 弹力 摩擦力 处处给力<br>匀速 加速 超音速 致富加速<br>动能 势能 机械能 万事皆能<br>质心 重心 几何心 天天顺心<br>强电 弱电 交流电 秒秒来电<br>重子 轻子 中微子 龙门贵子<br>虚像]]>
    </summary>
    <title>新的一年，祝大家：</title>
    <updated>2025-02-02T08:29:37.096Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="如下所示："><a href="#如下所示：" class="headerlink" title="如下所示："></a>如下所示：</h2><div id="zan" class="clearfix">    <div class="heart" onclick="goodplus(url, flag)"></div>    <br>    <div id="zan_text"></div></div>哦，文章末尾也有点赞的，但一个页面两次出现冲突了，导致只有第一个能正常显示点赞数]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%82%B9%E8%B5%9E%E5%8A%9F%E8%83%BD%E6%B5%8B%E8%AF%95</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%82%B9%E8%B5%9E%E5%8A%9F%E8%83%BD%E6%B5%8B%E8%AF%95"/>
    <published>2025-01-14T14:44:56.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="如下所示："><a href="#如下所示：" class="headerlink" title="如下所示："></a>如下所示：</h2><div id="zan" class="clearfix">
    <div class="heart" onclick="goodplus(url, flag)"></div>
    <br>
    <div]]>
    </summary>
    <title>点赞功能测试</title>
    <updated>2025-01-23T10:57:34.878Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="嘉立创开源工程" scheme="https://hcyhub.com/categories/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/"/>
    <category term="嘉立创" scheme="https://hcyhub.com/tags/%E5%98%89%E7%AB%8B%E5%88%9B/"/>
    <category term="硬件开源" scheme="https://hcyhub.com/tags/%E7%A1%AC%E4%BB%B6%E5%BC%80%E6%BA%90/"/>
    <category term="3D打印" scheme="https://hcyhub.com/tags/3D%E6%89%93%E5%8D%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="3D打印可装水小葫芦"><a href="#3D打印可装水小葫芦" class="headerlink" title="3D打印可装水小葫芦"></a>3D打印可装水小葫芦</h2><blockquote><p>复刻成本0元，嘉立创每月有免费一次3D打印</p></blockquote><p>这是我设计的小葫芦，今天终于到货了，经过3小时的精磨以及扣内部填充物，终于完成。细腻的外表摸起来温润如玉，在阳光的照射下隐隐有丝绿色，优良的材质通光性极佳，盘了半天根本舍不得放下（我磨废了五张砂纸）</p><p><strong>3D打印STL图纸下载：</strong><a href="/images/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/3D%E6%89%93%E5%8D%B0%E5%8F%AF%E8%A3%85%E6%B0%B4%E5%B0%8F%E8%91%AB%E8%8A%A6/%E5%8F%AF%E8%A3%85%E6%B0%B4%E8%91%AB%E8%8A%A6%E7%B4%A0%E7%93%B6%E4%BF%AE%E5%A4%8D%E7%89%88.stl">可装水葫芦素瓶修复版.stl</a></p><blockquote><p>推荐个3D打模型小工具：<a href="https://page.hcyhub.com/3D%E6%A8%A1%E5%9E%8B%E7%AE%80%E5%8C%96%E5%B7%A5%E5%85%B7">3D模型简化器</a></p></blockquote><p>下面是实物图:</p><img src="/images/嘉立创开源工程/3D打印可装水小葫芦/1.webp" style="zoom:70%;" /><img src="/images/嘉立创开源工程/3D打印可装水小葫芦/2.webp" style="zoom:70%;" /><img src="/images/嘉立创开源工程/3D打印可装水小葫芦/3.webp" style="zoom:70%;" /><img src="/images/嘉立创开源工程/3D打印可装水小葫芦/4.webp" style="zoom:70%;" /><p>前往打印</p><p><a href="https://www.jlc-3dp.cn/freePrint?freeShareId=404994436251680769">每月一次免费3D打印</a></p>]]>
    </content>
    <id>https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/3D%E6%89%93%E5%8D%B0%E5%8F%AF%E8%A3%85%E6%B0%B4%E5%B0%8F%E8%91%AB%E8%8A%A6</id>
    <link href="https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/3D%E6%89%93%E5%8D%B0%E5%8F%AF%E8%A3%85%E6%B0%B4%E5%B0%8F%E8%91%AB%E8%8A%A6"/>
    <published>2025-01-02T15:53:32.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="3D打印可装水小葫芦"><a href="#3D打印可装水小葫芦" class="headerlink"]]>
    </summary>
    <title>3D打印可装水小葫芦</title>
    <updated>2025-12-01T11:29:59.872Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="嘉立创开源工程" scheme="https://hcyhub.com/categories/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/"/>
    <category term="嘉立创" scheme="https://hcyhub.com/tags/%E5%98%89%E7%AB%8B%E5%88%9B/"/>
    <category term="PCB" scheme="https://hcyhub.com/tags/PCB/"/>
    <category term="硬件开源" scheme="https://hcyhub.com/tags/%E7%A1%AC%E4%BB%B6%E5%BC%80%E6%BA%90/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="厦门地铁图PCB版震撼发布！"><a href="#厦门地铁图PCB版震撼发布！" class="headerlink" title="厦门地铁图PCB版震撼发布！"></a>厦门地铁图PCB版震撼发布！</h2><blockquote><p>复刻成本0元，可免费打样</p></blockquote><p>有了它，在厦门乘坐地铁将不再需要看地铁图，只需在他人震惊的目光中掏出这小小的一张板子，你，将成为地铁上<strong>最靓</strong>的仔！</p><p>开源链接：<a href="https://oshwhub.com/ethaniel/xia-men-di-tie-tu-he-ji-kai-yuan-ban">https://oshwhub.com/ethaniel/xia-men-di-tie-tu-he-ji-kai-yuan-ban</a></p><p>此工程一共有四个版本，分别是：</p><ol><li>标准版的1.0和专业版的1.0，区别在于专业版的用了布尔运算合并了填充区域；</li><li>1.1版本则是将字符位置移动到了地图上的陆地地区，微调客编区，并将顶上的厦门地铁图及其英文纵向放置；</li><li>喷锡版则是将海洋区域放置开窗区喷锡，让锡模拟波光粼粼的大海</li></ol><p>以下是四个版本的实物图，我建议1.0、1.1版本用沉金工艺做比较好看，喷锡版你也可以用沉金，但我不建议，因为那样太浪费资源了（要是能地铁路线用沉金，海洋部分用喷锡就好了）</p><p>注：一定要记得设置<strong>自定义客编位置</strong>！！！</p><p>下面是实物图</p><img src="/images/嘉立创开源工程/厦门地铁图合集开源版/1.webp" style="zoom:67%;" /><img src="/images/嘉立创开源工程/厦门地铁图合集开源版/2.webp" style="zoom:67%;" /><img src="/images/嘉立创开源工程/厦门地铁图合集开源版/3.webp" style="zoom:67%;" /><img src="/images/嘉立创开源工程/厦门地铁图合集开源版/4.webp" style="zoom:67%;" /><p>PCB设计图</p><img src="/images/嘉立创开源工程/厦门地铁图合集开源版/PCB.webp" alt="PCB" style="zoom:67%;" />]]>
    </content>
    <id>https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E5%8E%A6%E9%97%A8%E5%9C%B0%E9%93%81%E5%9B%BE%E5%90%88%E9%9B%86%E5%BC%80%E6%BA%90%E7%89%88</id>
    <link href="https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E5%8E%A6%E9%97%A8%E5%9C%B0%E9%93%81%E5%9B%BE%E5%90%88%E9%9B%86%E5%BC%80%E6%BA%90%E7%89%88"/>
    <published>2025-01-02T06:39:35.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="厦门地铁图PCB版震撼发布！"><a href="#厦门地铁图PCB版震撼发布！" class="headerlink"]]>
    </summary>
    <title>厦门地铁图合集开源版</title>
    <updated>2025-01-23T05:40:42.617Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="陶瓷发展史" scheme="https://hcyhub.com/tags/%E9%99%B6%E7%93%B7%E5%8F%91%E5%B1%95%E5%8F%B2/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="陶瓷的故事"><a href="#陶瓷的故事" class="headerlink" title="陶瓷的故事"></a>陶瓷的故事</h2><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p><strong>中国最早用于做容器陶器</strong>可以追溯至两万年前旧石器时代，在经历了历代匠人、数千年的技术革新，发展出举世闻名的唐三彩、白瓷、青瓷、青花瓷等种类繁多瓷器，以至于有人说中国的英文名“<strong>China</strong>”来自于“瓷器”（这个说法其实并不对，目前较为可信的是来源于“晋”这个字的读音），由此也可看出中国与陶瓷之间的密切关系。</p><blockquote><p>顺便一提，<del>小</del>日本的以漆器闻名，世人称中国为瓷器大国，<del>小</del>日本为漆器<del>小</del>大国，中国英文名的小写“china”意思是瓷器，<del>小</del>日本的英文名小写“japan”意思是漆器，但漆器最早起源于中国距今约7000年前的浙江余姚河姆渡原始社会，但并未发展起来，传入<del>小</del>日本被发扬光大被世人熟知了而已。</p></blockquote><p>中国瓷器不仅在古代宫廷中被大量使用，从东南沿海里发现的南宋古沉船中（南海Ⅰ号），发现大量青釉瓷，可以看出在当时陶瓷器已被作为主要贸易品之一，并出口至亚洲、伊斯兰文化圈、以及欧洲各国，对中国的象征意义可与丝绸齐名，瓷器还为当时的欧洲人提供了一个了解中国文化和审美价值的窗口。时至今日，瓷器还作为中国的国礼频频出现。</p><img src="/images/中国-陶瓷的故事/国礼瓷.jpg" alt="国礼瓷" style="zoom:67%;" /><blockquote><p>瓷器和陶瓷都是啥？<strong>用陶土烧制的器皿叫陶器，用瓷土烧制的器皿叫瓷器，陶瓷则是陶器和瓷器的总称</strong>。</p><p> 陶与瓷的区别：陶器烧成温度低于瓷器，最低甚至达到850℃以下，最高可达1150℃左右。 瓷器烧成温度则比较高，大都在1250℃以上，甚至有的达到1380℃左右，</p><p>且陶器表面粗糙，易吸水，而瓷器一般都有上釉，表面光滑不吸水</p></blockquote><h3 id="陶瓷的发展史"><a href="#陶瓷的发展史" class="headerlink" title="陶瓷的发展史"></a>陶瓷的发展史</h3><h4 id="旧石器时代"><a href="#旧石器时代" class="headerlink" title="旧石器时代"></a><strong>旧石器时代</strong></h4><p>目前考古发现的最古老陶制容器是位于中国江西仙人洞、吊桶环遗址中的陶罐碎片，可以追溯到前20,000年至前19,000年，而在该遗址3B1层出土的条纹陶罐，至少有13000年的历史，这是人类最早烧制的陶器，陶器种类有釜和深腹钵两种，很可能与采集经济有关。早期的陶器像小孩捏的泥坯烧干烧硬了一样不甚美观，长时间受潮的话表面还会一层层的脱落，制作粗糙，器形不均，毕竟早期制作水平属实不佳。</p><h4 id="新石器时代"><a href="#新石器时代" class="headerlink" title="新石器时代"></a><strong>新石器时代</strong></h4><p>在这个时代，人们开始从事农业和畜牧，石器的制作从打制变磨制， 将种子种植食用，把野生动物驯服以供食用，人们不再只依赖大自然提供食物，因此其食物来源变得稳定，同时农业与畜牧的经营也使人类由逐水草而居变为定居下来，节省下更多的时间和精力。</p><p>新石器时代早期的陶器宛如半成品，好想把泥坯烧干烧硬了一样，长时间受潮的话表面还会一层层的脱落，制作粗糙，器形不均，后期制作工艺慢慢上去了，出现了各式各样的彩绘陶器。例如：</p><img src="/images/中国-陶瓷的故事/龟形壶.jpg" alt="龟形壶" style="zoom:50%;" /><img src="/images/中国-陶瓷的故事/船形网纹壶.jpg" alt="船形网纹壶" style="zoom:50%;" /><img src="/images/中国-陶瓷的故事/人头形器口彩陶瓶.png" alt="人头形器口彩陶瓶" style="zoom:50%;" /><p>在这时期陶器民用的较多，多半是自产自销，自娱自乐的东西。</p><h4 id="殷周时期陶瓷"><a href="#殷周时期陶瓷" class="headerlink" title="殷周时期陶瓷"></a><strong>殷周时期陶瓷</strong></h4><p>殷商时代在是陶瓷史的一个历史节点，在这个时代，人工施釉的原始瓷器的出现，从这时起，光洁美丽的瓷器正式踏上历史的舞台。</p><p>在此之前由于温度不够只能烧制陶器，随着时代的变迁，人们制造出了窑炉，在高温燃烧的窑炉中，将燃料木材的灰与土胎中的硅酸结合，会在陶器表面产生玻璃状的薄膜，这被称为“自然釉”。与朝鲜半岛和日本的陶器不同的是，朝鲜半岛和日本首先经历了窑内木灰的自然釉阶段才进入施釉陶时代，但中国各地绝大多数都没有经过自然釉阶段，而是直接出现了人工施釉并长时间高火烧成的原始瓷器。</p><blockquote><p>细心的人应该发现了，我在上面的叙述中没有用<strong>“瓷器”</strong>来称呼殷商时期<strong>人工施釉的原始陶器</strong>，而是加上了“原始”二字，这是因为：</p><ol><li>殷代的原始瓷器是由粘土烧制的，制作工序简单，烧制温度低；</li><li>而后来出现的瓷器则是由高岭土、长石和石英等材料制成，硬度更高，烧制温度更高更光洁。</li></ol><p>通俗来说就是殷代的原始瓷器是刷了釉的陶器</p></blockquote><h4 id="春秋战国时期陶瓷"><a href="#春秋战国时期陶瓷" class="headerlink" title="春秋战国时期陶瓷"></a><strong>春秋战国时期陶瓷</strong></h4><p>春秋战国时期的江浙一带出土了大量的原始瓷器，但同时期的华北地区却几乎没有发现同类陶器。浙江德清县发现了40多处烧制春秋时期原始瓷器的窑炉遗址，皇坟堆出土了27件原始瓷器，却没有发现任何青铜器。由此可以看出，当时华北地区主要关注青铜器生产，而华南地区主要生产原始瓷器。</p><blockquote><p>注：从南朝起到唐代，江浙一带就是生产越州窑青瓷的主要地区，因此而研究认为，春秋战国时期的原始瓷器就是后代青瓷的起源</p></blockquote><p>战国时代的陶器除了原始瓷器外，还出现了华北地区的加彩灰陶。灰陶是在高温的还原气氛下烧成的，其历史可以追溯至新石器时代，但在灰陶的器表面用红、白、黑等颜料绘画或刻入纹样的加彩灰陶则出现在春秋时代。</p><blockquote><p>春秋战国的加彩灰陶与新石器时代彩绘陶器不同的是，新石器时代彩绘陶器烧成前就画上图案，加彩灰陶是在烧成后才进行着色和绘图的。</p></blockquote><h4 id="秦汉时期陶瓷"><a href="#秦汉时期陶瓷" class="headerlink" title="秦汉时期陶瓷"></a><strong>秦汉时期陶瓷</strong></h4><h5 id="秦"><a href="#秦" class="headerlink" title="秦"></a>秦</h5><p>虽然秦朝历时仅十五年 <del>我都比秦朝还大</del>，但仍在中国陶瓷史上留下了浓墨重彩的一笔，即举世闻名的秦皇兵马俑。<del>(应该不会有人不知道兵马俑是陶器吧……)</del></p><p>坐落于西安郊外骊山脚下的秦始皇陵以东发现的三个兵马俑坑中挖掘出了陶制战车百余乘、陶马约600匹、兵俑约8,000座，所有兵马向东排列整齐，气势恢宏。从工艺上分析兵马俑，兵马俑属于加彩灰陶。兵俑身高在1.75~1.86米之间，陶马高约1.6米左右。尽管出土后因为氧化导致兵马俑表面均呈灰色，但制作当时均以多种色彩绘制（刚刚出土的时候就是彩色的）。兵马俑从衣着、武器、容貌和表情上都因人而异，用色丰富多彩，体现了当时高水平的陶瓷烧制技术，相较于春秋战国时期有着极大的进步。</p><img src="/images/中国-陶瓷的故事/兵马俑——征服世界的军队.webp" alt="兵马俑——征服世界的军队" style="zoom:67%;" /><h5 id="汉"><a href="#汉" class="headerlink" title="汉"></a>汉</h5><p>进入汉代后，中国陶瓷史上诞生了真正意义的瓷器——青瓷(我最喜欢的一种瓷器)。此外，原始瓷器、加彩灰陶等陶器也在继续发展。从殷周直至春秋战国，中国主要以发展青铜器为主，陶瓷的生产技术并没有取得显著的进步。但到了汉代之后，由于出现了青瓷这一划时代的技术革新，陶瓷的发展史也翻开了崭新的一页。</p><blockquote><p>我们现在所说的瓷器终于出现了，瓷器出现后原始瓷器并没有就此消声觅迹，原始瓷器在汉代仍有生产，但公元前3世纪左右曾出现过原始瓷器消失的真空期。此外，一部分研究认为，汉代原始瓷器在技术上与战国时代相比出现了倒退。</p></blockquote><h4 id="三国南北朝时期陶瓷"><a href="#三国南北朝时期陶瓷" class="headerlink" title="三国南北朝时期陶瓷"></a><strong>三国南北朝时期陶瓷</strong></h4><p>汉代发明的的<strong>青瓷</strong>在三国南北朝时期得到了进一步的发展和革新。以浙江为中心的地带出土的<strong>青瓷</strong>中可以发现从三国时代直至西晋、东晋时期的物品。这类青瓷被称为“古越瓷”以便与越瓷相区分（<strong>越瓷</strong>是<strong>晚唐</strong>到<strong>北宋</strong>时期的越州窑青瓷)。</p><p>从这一时期发掘出的青瓷主要以墓穴中的<strong>随葬品</strong>为主，尚不清楚青瓷作为日用品的主要用途(或许青瓷在这时期是专门用于陪葬的？)。在种类方面，一般以壶、盘居多，也有一种特殊的“魂瓶”（堆塑罐）。魂瓶就是即在容器上绘有动物或者楼阁人物等图案的陶壶，是这一时期特有的瓷器。</p><img src="/images/中国-陶瓷的故事/堆塑罐.jpg" alt="堆塑罐" style="zoom:50%;" /><p>上述用于随葬品的瓷器从<strong>吴国</strong>到<strong>西晋</strong>非常发达，从<strong>东晋</strong>以后此类随葬品开始减少，而生活实用品则逐渐增加。在短命的东魏灭亡后，北齐开始出现了白瓷，但在西魏及其后的北周都没有发现有大规模的制陶活动。白瓷是在精炼的白色胎土上刷透明釉用高火烧成的瓷器，为了掩盖胎色较暗的缺点，北方陶工学习南方制瓷经验，在瓷胎上抹白色土修饰。</p><h4 id="隋唐时期陶瓷"><a href="#隋唐时期陶瓷" class="headerlink" title="隋唐时期陶瓷"></a><strong>隋唐时期陶瓷</strong></h4><p>隋唐两个朝代继续生产发展前朝的青瓷、白瓷等。到了8世纪末，陶瓷器已经进入了普通民众的日常生活。同时，陶瓷器也开始成为出口海外的商品之一。从东南亚和西亚等地的考古中，发现了大量唐代青瓷和白瓷，由此可见唐朝的陶瓷器已经在国际上具有相当高的知名度和商用价值。</p><p>唐代陶瓷器的代表作之一就是色彩华丽的三彩陶器（又称“唐三彩”），这种陶器有各种形式，人物、马匹、罐子等，用小火烧成，主要还是用于随葬品，并不是日常生活中广泛使用的陶器。(其实唐三彩就是专门用于随葬的瓷器，家里摆个唐三彩&#x3D;家里摆个兵马俑)</p><img src="/images/中国-陶瓷的故事/唐三彩.jpg" alt="唐三彩" style="zoom:50%;" /><h5 id="青瓷"><a href="#青瓷" class="headerlink" title="青瓷"></a>青瓷</h5><p>唐代著名的瓷窑之一：越州窑简称称越窑，代表了中国当时青瓷生产的最高水平，主要分布在浙江省慈溪、上虞、余姚、镇海、黄岩、绍兴、湖州等地，晚唐、五代时期最上品的越窑千峰翠色青瓷专门作为贡品,平民不得用，因此称为“<strong>秘色</strong>”。五代时期闽国国王<strong>王审知</strong>曾派<strong>徐寅</strong>贡秘色瓷,<strong>徐寅</strong>作诗《<strong>贡余秘色瓷器</strong>》：</p><p>捩翠融青瑞色新，陶成先得贡吾君；</p><p>巧剜明月染春水，轻旋薄冰盛绿云；</p><p>古镜破苔当席上，嫩荷涵露别江𣸣；</p><p>中山竹叶醅初发，多病那堪中十分?</p><p>由此可见当时制作青瓷的工艺高超。 <del>啊啊啊，好想要啊</del></p><img src="/images/中国-陶瓷的故事/越窑千峰翠色青瓷.jpg" alt="越窑千峰翠色青瓷" style="zoom:67%;" /><blockquote><p>唐代七大瓷窑</p><p>唐代陆羽的《茶经》一书中，就品质优良的茶器用瓷，列举了唐代七大瓷窑：越州、鼎州、婺州、岳州、寿州、洪州、邢州。</p></blockquote><h5 id="白瓷"><a href="#白瓷" class="headerlink" title="白瓷"></a>白瓷</h5><p>唐代的中国形成了“<strong>南青北白</strong>”的陶瓷行业格局，南方各地多以青瓷为主，而北方则主要生产白瓷。</p><p>生产白瓷的窑址除了源自北朝时代的邢州窑（今河北省邢台市临城县、内丘县）外，还有河北省保定市曲阳县定窑和河南省巩义县的巩县窑。其中的定窑在北宋时代发展成为白瓷最重要的生产地。</p><p>唐代的另一个重要瓷窑是长沙窑（又称瓦渣坪窑）。位于湖南省长沙市望城区铜官镇。该瓷窑被认为是《茶经》中提及的岳州窑的延续，以大量生产出口海外的白瓷而著称。</p><p>长沙窑瓷胎呈灰白色，也有青灰、灰黄和酱色，火候在1200度左右。其最为经典的作品为在灰白色胎土上添加白土修饰后施加灰釉的黄釉陶。尽管釉质本身与青瓷相似，但由于在氧化焰下烧成，釉显得略微发黄。种类方面，虽有多种器形，但以茶壶居多。</p><p>在工艺方面，长沙窑的特点是<strong>釉下彩</strong>。后世的五彩（色绘）是在挂透明釉高火烧成的瓷器釉面上绘画并二次烧制的，而釉下彩是在无釉的胎瓷上直接进行彩绘，然后再挂透明釉进行烧制。釉下彩包括使用钴做颜料的青花瓷；使用铁的黑花以及使用铜的釉里红等。长沙窑中的色釉种类丰富，是早期釉下彩瓷器中的杰出代表。此外，长沙窑瓷器大量出口到海外，目前在日本、东南亚和西亚等地都发现了其作品。</p><h4 id="宋辽金时期陶瓷"><a href="#宋辽金时期陶瓷" class="headerlink" title="宋辽金时期陶瓷"></a><strong>宋辽金时期陶瓷</strong></h4><p>宋朝是中国陶瓷史上的黄金时代，产生了大量的青、白瓷的珍品。青瓷的产地与前代相同，主要集中在南方的越州窑和北方的耀州窑等地。越州窑原集中在浙江省北部，从北宋中期开始逐渐向浙南迁移，被后世称为龙泉窑。</p><h5 id="汝瓷"><a href="#汝瓷" class="headerlink" title="汝瓷"></a>汝瓷</h5><p>此外，宋朝创办了汝窑，汝窑所烧制的汝瓷特别之处在其釉色，釉色以天青为主要颜色，包含天蓝、粉青、月白等色，有“雨过天青云破处，这般颜色作将来”的美誉。流传到现在的汝瓷大多都有裂痕，这是因为烧制时瓷胎和釉膨胀范围不同导致的，这本是瑕疵，但在文人墨客眼中却成了艺术的象征，王宫贵族也很是喜爱，而无纹无瑕疵的极为罕见，目前传世的仅有北宋汝窑青瓷无纹水仙盆是无纹的，现收藏于台北故宫博物院。</p><img src="/images/中国-陶瓷的故事/北宋汝窑青瓷无纹水仙盆.jpg" alt="北宋汝窑青瓷无纹水仙盆" style="zoom:50%;" /><p>但是因为汝窑存在时间极为短暂（成立后仅20年北宋就变南宋了，而汝窑也毁于宋金战火中），所以汝瓷极为罕见，更有人将汝窑称为瓷魁，列为北方青瓷之首、五大名窑之冠。</p><h5 id="白瓷-1"><a href="#白瓷-1" class="headerlink" title="白瓷"></a>白瓷</h5><p>在白瓷方面，以北方的定窑和南方的景德镇窑最为著名。</p><p>定窑主要生产在氧化焰下烧制的乳白色的白瓷。</p><p>景德镇起始于五代，在元代以后成为中国陶瓷的核心。但在宋代，景德镇窑的主要产品是“青中有白，白中显青”的青白瓷（又称“<strong>影青瓷</strong>”）。</p><p>此外，在河南省一带，盛产在陶质胎土上添加白化妆土的仿白瓷，这一系列被称为磁州窑。磁州窑的产品使用了剔刻、刻填、铁绘等装饰技法，出产了大量浓郁生活气息的白瓷，在金代的磁州窑出现了中国陶瓷史上最初的五彩瓷（即色绘）。南宋时期，福建省的建窑、江西省的吉州窑等出产了黑釉的茶碗（又称“天目”，是漆器的一种）。这类茶具流传至日本后被视为珍宝，对日本茶道文化也产生了深远的影响。</p><img src="/images/中国-陶瓷的故事/“孟”字碗.png" alt="“孟”字碗" style="zoom:50%;" /><h4 id="元代陶瓷"><a href="#元代陶瓷" class="headerlink" title="元代陶瓷"></a><strong>元代陶瓷</strong></h4><p>在蒙古人统治的元代，中国陶瓷并未停滞不前，反而出现了重大发展。由于当时对元代陶瓷的书面记载不多，而且留存于世的瓷器也极其罕见，很长一段时间以来，世人对元代陶瓷并不熟悉。因此，很多元代的瓷器往往被后人当作宋代或者之后的明代的作品。但是，进入20世纪以后，欧美学者对元代陶瓷的样式研究有了突破，逐渐开始了解这一时期的陶瓷历史：</p><h5 id="青花瓷"><a href="#青花瓷" class="headerlink" title="青花瓷"></a>青花瓷</h5><p>元代陶瓷史上最值得一提的便是著名的青花瓷，即在白瓷胚上以青蓝色做图案的瓷器。青花属于釉下彩的一种，首先将成形的瓷胚素烧后，使用含有氧化钴的颜料在器面上绘制图案。绘制完成后施加透明釉，并在还原气氛中高火烧制，从而使颜料呈青色。元代使用的氧化钴颜料主要进口自西亚地区，在当时被称为“回青”或“回回青”（意为“伊斯兰世界的青色”）。前文有提到釉下彩这种技法早在唐代的长沙窑就已出现，但在宋朝并未成为中国陶瓷的主流。而釉下彩瓷主要是从元代的景德镇窑才开始兴起的。</p><p>在元代，景德镇的青花瓷也独领风骚，宋代以前颇为流行的白瓷和青瓷逐渐衰落。但是传统青瓷产地之一的浙江龙泉窑的青瓷却依然活跃在国内外市场上，大量出口海外。</p><img src="/images/中国-陶瓷的故事/青花牡丹琛宝菱花口盘.jpg" alt="青花牡丹琛宝菱花口盘" style="zoom:80%;" /><h4 id="明代陶瓷"><a href="#明代陶瓷" class="headerlink" title="明代陶瓷"></a><strong>明代陶瓷</strong></h4><p>明代陶瓷的代表是设置御器厂（官窑），专为宫廷供应瓷器的景德镇窑。景德镇窑早在五代时期就已出现，并在宋代就大量生产青白瓷。但到了明清两代，景德镇才真正成为中国陶瓷业的中心。这主要由于景德镇具备了陶瓷原料的陶土、烧窑必须的木材、优质的水源和便利的水运条件。</p><h5 id="青花瓷-1"><a href="#青花瓷-1" class="headerlink" title="青花瓷"></a>青花瓷</h5><p>朱元璋在建国次年的洪武2年（1369年）颁布圣旨，规定宫廷内的祭祀器具一律使用瓷器。出身贫农的朱元璋倡导节约，反对在宫廷祭器中使用昂贵的金银，而改用瓷器。在宋代的大江南北<strong>成百上千瓷窑</strong>百家争鸣的局面经由元过度之后，到明代变成了由<strong>景德镇</strong>各瓷窑一统天下的局面。明代的青花瓷装饰手法从元朝的刻、划、印、塑等转为彩绘。 绘画纹饰的内容更加丰富多彩，植物、动物、文字、山水、人物、花鸟、鱼及虫等皆可入画。 明代早期以<strong>写意画</strong>为主，画风自由、奔放、洒脱；明后期以<strong>写实</strong>为主，画面抒情达意，简约轻快，极具漫画趣味。</p><img src="/images/中国-陶瓷的故事/明成化青花水草莲花纹碗.png" alt="明成化青花水草莲花纹碗" style="zoom:50%;" /><h5 id="斗彩"><a href="#斗彩" class="headerlink" title="斗彩"></a>斗彩</h5><p>明代瓷器的另一主要成就，就是斗彩（逗彩）的成功烧制。斗彩创烧于名宣德（1426-1435年）年间，<strong>成化年间</strong>的作品最受推崇。而斗彩这个名称，明代的文献里未见记载，最早使用“斗彩”这一名称并给予解释的，见于清雍正年间的《南窑笔记》：“成、正、嘉、万俱有斗彩、五彩、填彩三种，先于坯上用青料画花鸟半体，复入彩料，凑其全体，名曰斗彩”。斗彩的装饰方式是青花与釉上彩的结合，青花是勾勒图案的“线稿”，在用青花勾好图案的轮廓线后，釉上彩按青花规定的范围填入，或者先用青花画好图案的一部分，釉上彩再<strong>着色</strong>画色彩的部分，甚至有的作品几乎由青花表现，而釉上彩只是稍加加点缀色彩。</p><img src="/images/中国-陶瓷的故事/明成化斗彩三秋杯.jpg" alt="明成化斗彩三秋杯" style="zoom:80%;" /><blockquote><p>红楼梦四十一回中，妙玉招待贾母的“成窑小盖钟”指的就是成化官窑斗彩。</p><p>为了体现妙玉的性格，作者又写道，洁癖又傲娇的她嫌弃贾母喝了口茶又给刘姥姥尝，不想再用，本来想直接不要了让仆人丢掉，宝玉看出来她的心思，避免浪费，劝说妙玉与其将杯子扔了，不如直接送给刘姥姥，而这点人情使得日后贾府抄家败落之际，刘姥姥仗义探监，勇救巧姐。一个成窑茶杯，便令几人性格跃然纸上。可见成窑之贵重与妙玉之清高奢侈。</p></blockquote><h4 id="清代瓷器"><a href="#清代瓷器" class="headerlink" title="清代瓷器"></a><strong>清代瓷器</strong></h4><p>清代的陶瓷生产的重要代表仍为<strong>景德镇</strong>窑。明万历帝死后一度被废止的景德镇官窑在康熙20年前后再度复兴。此后的康雍乾三朝是清代陶瓷最繁荣的时期。清代流行<strong>粉彩</strong>或<strong>珐琅彩</strong>等，在瓷器器面上烧制的图案繁华细腻，几乎是在陶瓷上绘画没有差别。除了传统的青花瓷之外，也开发出了多种色釉。因此，清代瓷器在烧制技术和绘图工艺上均达到了史无前例的高度，彰显了古代瓷器工匠的最高水平。但进入19世纪以后，随着国内局势动荡和国力衰退，陶瓷的品质也难以维持，逐渐走向衰弱</p><h5 id="粉彩"><a href="#粉彩" class="headerlink" title="粉彩"></a>粉彩</h5><p>康熙末年，中国陶瓷史点亮了粉彩这一新技法。制作粉彩首先将石英粉与铅粉混合，并在此基础上添加各种颜料用以绘制图案。雍正时期的粉彩最有代表性，用色调柔和淡雅，比例精细工整，所以也称为软彩；采用白粉扑底成立体状再加色彩，并染成浓淡明暗层次，清新透彻，温润平实，深具工笔花鸟之意味及浓厚的装饰性。</p><img src="/images/中国-陶瓷的故事/粉彩团蝶纹碗.jpg" alt="粉彩团蝶纹碗" style="zoom:50%;" /><h5 id="珐琅彩"><a href="#珐琅彩" class="headerlink" title="珐琅彩"></a><strong>珐琅彩</strong></h5><p>珐琅彩，是清康熙晚期在皇帝的授意下，将画珐琅技法移植到瓷胎上的一种釉上彩瓷新品种，学名“瓷胎画珐琅”，俗称“古月轩”。珐琅彩瓷祇生产过400件，由于全程在皇帝控制之下，所以追溯其制造者较为容易（感兴趣的可以去<a href="https://100713.xyz/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%8F%90%E7%90%85%E5%BD%A9%E6%94%B6%E8%97%8F%E6%98%8E%E7%BB%86">收藏名录</a>看看）。珐琅彩与粉彩使用的技法类似，两者的区别在于</p><ul><li><p>粉彩整个工艺流程都在景德镇完成；</p></li><li><p>而珐琅彩是在景德镇制作的瓷胎上有内务府造办处的官营工场绘彩。</p></li></ul><p>由于珐琅彩制作过程中也有<strong>宫廷画家</strong>的参与，因此达到了相当高的艺术水平。珐琅彩瓷器使用进口的材料，例如含有微量黄金的金红。初期的珐琅彩是在瓷胎上直接绘制，这主要是由于当时技术水平还无法再透明釉上绘图。随着技术的进步，雍正年间的作品出现了在透明釉上绘制图案的作品。珐琅彩的作品主要是碗、皿等小品物，而景德镇窑的粉彩中包括大型瓷瓶。景德镇粉彩中往往同时使用旧有的五彩颜料和粉彩颜料，但珐琅彩上几乎没有这种做法。康熙五彩往往被称作“硬彩”或“古彩”，而粉彩被称作“软彩”或“洋彩”，因珐琅彩制作从不考虑制作成本，因而在历代瓷器中，珐琅彩瓷器<strong>造价最贵</strong>，<strong>艺术水平也最高</strong>，被誉为“<strong>官窑中的官窑</strong>”。</p><img src="/images/中国-陶瓷的故事/粉红地珐琅彩开光花卉碗.jpg" alt="粉红地珐琅彩开光花卉碗" style="zoom:80%;" /><h3 id="结尾"><a href="#结尾" class="headerlink" title="结尾"></a>结尾</h3><blockquote><p>近现代：被列强牵着鼻子走</p></blockquote><p>自康乾盛世之后中国的陶瓷器就开始走下坡路，而且再也没有回过头来。</p><p>到了近现代，特别是鸦片战争以后，随着日本瓷器的崛起和欧洲瓷器的不断发展，中国的制瓷业渐渐进一步的走向了衰落 。20世纪上半叶，中国的制瓷业堪称衰败，时局动荡，很多名窑受牵连停产，制作工艺失传。</p><p>新中国成立以后，在政府的主导下，传统的制瓷业开始复苏。以瓷都景德镇为代表的新中国制瓷业才开始苏醒和进一步发展，一些名窑中断了一段时期后，也获得了新生。</p><p>各种省级、国家级重点项目再度上马，中国的瓷业又欲再度出现百花争艳的局面。</p><p>这样的局面对于我们来说，或许是梦回大唐；再临大宋；或是又见康乾盛世……</p><p>在历史的长河中，中国陶瓷的工艺也在悠久的国际贸易中逐渐转播到全球各地，对世界陶瓷生产技术的发展产生了深远的影响。</p><p>参考资料</p><p><em>《手铲下的文明·江西重大考古发现》《中国陶瓷》《陶瓷史话》《中国文物精华大辞典・陶瓷卷》《简明陶瓷词典》《越窑、秘色瓷》《龙泉窑青瓷》《明朝那些事儿》《红楼梦》《中国古陶瓷研究》《古代瓷器制作术》《汝窑的发现》《中国陶瓷通史》</em></p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E4%B8%AD%E5%9B%BD-%E9%99%B6%E7%93%B7%E7%9A%84%E6%95%85%E4%BA%8B</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E4%B8%AD%E5%9B%BD-%E9%99%B6%E7%93%B7%E7%9A%84%E6%95%85%E4%BA%8B"/>
    <published>2024-12-21T14:29:13.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="陶瓷的故事"><a href="#陶瓷的故事" class="headerlink" title="陶瓷的故事"></a>陶瓷的故事</h2><h3 id="引言"><a href="#引言" class="headerlink"]]>
    </summary>
    <title>中国-陶瓷的故事</title>
    <updated>2025-10-07T06:37:52.439Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="制作参与人员"><a href="#制作参与人员" class="headerlink" title="制作参与人员"></a>制作参与人员</h2><p>由于珐琅彩瓷祇生产过400件，并且全程在皇帝控制之下，所以参与人员都可以考证。整理如下</p><ul><li>烧炼珐琅料的人员：主管是怡亲王；经办人为郎中海望、员外郎沈喻和唐英；宋七格负责全部炼制工作；邓八格具体操作；胡大有吹釉；太监吴书也是主要的技术人员。</li><li>画珐琅的画家：宋三吉、张琦、邝丽南、贺金昆、谭荣、林朝楷、郎士宁</li></ul><h2 id="品种"><a href="#品种" class="headerlink" title="品种"></a>品种</h2><p>珐琅彩瓷一直收藏于故宫端凝殿左右屋内，全部造册登录。</p><h3 id="康熙"><a href="#康熙" class="headerlink" title="康熙"></a>康熙</h3><p>分为10种，共计16件。另有宜兴胎画珐琅13种、18件，玻璃胎1种、1件。</p><ol><li>瓷胎画珐琅五彩西番花黄地大碗，康熙年制。（2件）</li><li>瓷胎画珐琅五彩西番花红地茶碗，康熙御制。（2件）</li><li>瓷胎画珐琅西番花红地盒，康熙御制。（1件）</li><li>瓷胎画珐琅菱盘，康熙御制款。（1件）</li><li>瓷胎画珐琅四季花蓝地磬口碗，康熙御制，堆料款，有盖。（1件）</li><li>瓷胎画珐琅宫碗，康熙御制，有盖。（1件）</li><li>瓷胎画珐琅菊花白地小瓶，无款，有盖。（1件）</li><li>瓷胎画珐琅黄菊花白地茶碗，康熙御制，有盖。（4件）</li><li>瓷胎画珐琅西番莲黄地盅，康熙御制，有盖。（2件）</li><li>瓷胎画珐琅花卉碗，康熙御制，有盖。（1件）</li></ol><h3 id="雍正"><a href="#雍正" class="headerlink" title="雍正"></a>雍正</h3><ol><li>瓷胎画珐琅眉寿长春白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅五伦图白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅芝仙祝寿白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅节节双喜白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅白梅花红地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅绿竹长春白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅眉寿白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅石榴花白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅茶梅花白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅锦堂春富贵白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅青绿山水白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅虎丘山水景白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅时时报喜白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅墨牡丹白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅玉堂祝寿白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅五色菊花白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅青山水白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅九莲献瑞白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅花卉绿地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅榴开百子白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅寿山福海白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅诸子百家白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅祝寿白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅五色牡丹白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅墨山水白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅五色牡丹白地大宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅墨山水白地宫碗，雍正年制。（2件）</li><li>瓷胎画珐琅久安长治白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅五彩眉寿白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅杏林春燕白地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅五彩西番花黄地大碗，雍正年制。（2件）</li><li>瓷胎画珐琅五彩西番花黄地大碗，雍正年制。（1件）</li><li>瓷胎画珐琅绿竹猗猗白地盅，雍正年制。（1件）</li><li>瓷胎画珐琅节节双喜白地茶壶，雍正年制。（2件）</li><li>瓷胎画红地花卉茶盅，雍正御制。（2件）</li><li>瓷胎画珐琅节节长春白地盅，雍正年制。（2件）</li><li>瓷胎画珐琅青山白地六寸盘，雍正御制。（2件）</li><li>瓷胎画珐琅时时报喜白地茶盅，雍正年制。（1件）</li><li>瓷胎画珐琅四季花红地盅，雍正御制。（2件）</li><li>瓷胎画珐琅黄地绿竹酒盅，雍正年制。（2件）</li><li>瓷胎画珐琅墨梅花白地四寸碟，雍正年制。（2件）</li><li>瓷胎画珐琅桕树八哥白地盅，雍正年制。（2件）</li><li>瓷胎画珐琅洛阳萱草白地四寸碟，雍正年制。（2件）</li><li>瓷胎画珐琅绿竹六寸盘，大清雍正年制。（2件）</li><li>瓷胎画珐琅花卉茶盅，雍正年制。（1件）</li><li>瓷胎画珐琅青山水白地茶壶，雍正年制。（1件）</li><li>瓷胎画珐琅黄地花卉六寸盘，大清雍正年制。（2件）</li><li>瓷胎画珐琅玉堂富贵白地六寸碟，雍正年制。（2件）</li><li>瓷胎画珐琅黄地梅竹六寸碟，大清雍正年制。（2件）</li><li>瓷胎画珐琅白梅花红地四寸碟，雍正年制。（2件）</li></ol>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%8F%90%E7%90%85%E5%BD%A9%E6%94%B6%E8%97%8F%E6%98%8E%E7%BB%86</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%8F%90%E7%90%85%E5%BD%A9%E6%94%B6%E8%97%8F%E6%98%8E%E7%BB%86"/>
    <published>2024-12-21T09:59:59.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="制作参与人员"><a href="#制作参与人员" class="headerlink"]]>
    </summary>
    <title>珐琅彩收藏明细</title>
    <updated>2025-10-07T06:36:00.845Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="3D打印" scheme="https://hcyhub.com/tags/3D%E6%89%93%E5%8D%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="3D打印的小印章"><a href="#3D打印的小印章" class="headerlink" title="3D打印的小印章"></a>3D打印的小印章</h2><p>这是使用3D打印的小印章，长64mm宽20mm高30mm，和印制面是分开打印的。</p><img src="/images/Z-library的小印章/logo.zlibrary.svg" style="zoom:67%;" /><p>上面这是Z-library的logo，可以看到Y字上面有书页，但因为打印机打不出那么细的条纹，所以实物Y字少了那书页部分。</p><p>有两版，1号是小尺寸版，logo与边缘没有空隙，2号则比一号长了两毫米，有与边缘的空隙。</p><h3 id="打印文件下载"><a href="#打印文件下载" class="headerlink" title="打印文件下载"></a>打印文件下载</h3><blockquote><p><strong>一号打印文件下载：</strong></p></blockquote><p><a href="/images/Z-library的小印章/1号.Z-library印章握把.stl" download="1号.Z-library印章握把.stl" class="download-button">握把</a></p><p><a href="/images/Z-library的小印章/1号.Z-library印制面（边缘无空）" download="1号.Z-library印制面（边缘无空）" class="download-button">印制面</a></p><blockquote><p><strong>二号打印文件下载</strong></p></blockquote><p><a href="/images/Z-library的小印章/2号.Z-library印章握把.stl" download="2号.Z-library印章握把.stl" class="download-button">握把</a></p><p><a href="/images/Z-library的小印章/2号.Z-library印制面（边缘有空）.stl" download="2号.Z-library印制面（边缘有空）.stl" class="download-button">印制面</a></p><h3 id="实物效果图"><a href="#实物效果图" class="headerlink" title="实物效果图"></a>实物效果图</h3><p>效果图：</p><img src="/images/Z-library的小印章/1.webp" style="zoom:10%;" /><img src="/images/Z-library的小印章/2.webp" style="zoom:10%;" /><img src="/images/Z-library的小印章/3.webp" style="zoom:10%;" /><img src="/images/Z-library的小印章/7.webp" style="zoom:10%;" /><img src="/images/Z-library的小印章/6.webp" style="zoom:10%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%81%9A%E4%B8%AAZ-library%E7%9A%84%E5%B0%8F%E5%8D%B0%E7%AB%A0%E7%8E%A9%E7%8E%A9%E5%90%A7</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E5%81%9A%E4%B8%AAZ-library%E7%9A%84%E5%B0%8F%E5%8D%B0%E7%AB%A0%E7%8E%A9%E7%8E%A9%E5%90%A7"/>
    <published>2024-12-19T07:46:45.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="3D打印的小印章"><a href="#3D打印的小印章" class="headerlink" title="3D打印的小印章"></a>3D打印的小印章</h2><p>这是使用3D打印的小印章，长64mm宽20mm高30mm，和印制面是分开打印的。</p>
<img src="/images/Z-library的小印章/logo.zlibrary.svg" style="zoom:67%;"]]>
    </summary>
    <title>做个Z-library的小印章玩玩吧</title>
    <updated>2025-06-06T01:48:26.938Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="狐狸-在历史的长河中逐渐污名化"><a href="#狐狸-在历史的长河中逐渐污名化" class="headerlink" title="狐狸-在历史的长河中逐渐污名化"></a>狐狸-在历史的长河中逐渐污名化</h2><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>近来互联网上开始流传一个热梗：狐主任。</p><img src="/images/人们对狐狸的印象/狐主任.jpg" style="zoom:80%;" /><p>狐主任其实就是藏狐，藏狐靠着一张国字脸火遍全国，那一张写满对世俗的不屑的方脸在搭配那“淡定”的眼神，引得人们自发将其做成表情包。藏狐靠着一张方脸让人们对狐狸的形象有所改观，而在此之前，狐狸的形象一直都不好，人们对狐狸的看法都是狡猾，阴险，比如著名的《狐狸列那的故事》就刻画了一只狡猾至极，死不悔改的狐狸，由此可见狐狸的形象属实不佳，但在以前狐狸可是祥瑞的象征，甚至与王位关联，只不过在历史的长河里慢慢污名化了</p><h3 id="狐狸形象的演变"><a href="#狐狸形象的演变" class="headerlink" title="狐狸形象的演变"></a>狐狸形象的演变</h3><p>在中国古代<strong>夏</strong>至<strong>汉魏</strong>时期，那时候狐狸在人民心中的形象是吉祥的、护佑人的正面形象。</p><h4 id="1-夏朝"><a href="#1-夏朝" class="headerlink" title="1.夏朝"></a>1.夏朝</h4><p>在《山海经》《淮南子》《吴越春秋》等古籍中，狐狸被描述为神兽、大禹之妻。比如《吴越春秋》中：<code>大禹向天祝告求妻时，一只九条巨尾的白狐，优雅缓行出现在他的面前。大禹见状，心下了然：我族尚白，我身着白衣，白狐之色与之相应；九为至尊之数，白狐九尾，昭示我族王者气象， “绥绥白狐，九尾痝痝。···成家成室，我造彼昌。”于是，大禹遵从上天的安排，娶涂山女娇为妻。</code><del>嗯…咋感觉涂山女娇就是那只白狐呢…</del></p><h4 id="2-秦汉时期"><a href="#2-秦汉时期" class="headerlink" title="2.秦汉时期"></a>2.秦汉时期</h4><p>《<strong>史记</strong>》中记载，陈胜和吴广为煽动戍卒反秦，在驻地旁的丛祠中以狐鸣，呼曰：“大楚兴，陈胜王！”，引得戍卒惶恐不已，使得后来戍卒愿意与陈胜吴广一同起义。</p><p>汉代石刻画像及砖画中，常有九尾狐与白兔、蟾蜍、三足乌之属列于西王母座旁，以示祯祥。</p><h4 id="3-南北朝"><a href="#3-南北朝" class="headerlink" title="3.南北朝"></a>3.南北朝</h4><p>李暹在注《千字文》“周伐殷汤”一句时，率先提出妲己为九尾狐。与此同时，动物通过长时间修炼化身为妖也就是”物老成精“的观点逐渐被人们所接受，这个观点的出现对狐狸的瑞兽形象产生了极大的冲击，因为之前只有特殊的动物才会化成人形，而现在所有动物都有了这个能力，这也让狐狸的形象走上了下坡路。</p><h4 id="4-唐宋时期"><a href="#4-唐宋时期" class="headerlink" title="4.唐宋时期"></a>4.唐宋时期</h4><blockquote><p>到了唐宋时期，狐狸的形象开始发生变化。人们开始相信狐狸可以修炼成精，幻化成人形。再加上一些文学作品的渲染，狐狸的形象逐渐变得复杂起来，既有善良美丽的狐仙，也有迷惑人心的妖狐。</p></blockquote><h5 id="唐朝"><a href="#唐朝" class="headerlink" title="唐朝"></a>唐朝</h5><p><strong>唐期初期，狐灵信仰在民间流传，设庙参拜狐仙的现象屡见不鲜。</strong>张鷟的《朝野佥载》记载到：初唐以来，百姓流行信仰狐仙，甚至流传出了“无狐魅，不成村”的谚语；</p><p>但与此同时，在文人圈子里，或许受到前面所提的“物老成精”观念的影响，汉代以后，狐仙开始跌落神坛，妖性渐显，形象也开始负面化。众多狐仙中尤为出名的九尾狐，首当其冲成为口诛笔伐的对象。唐代白居易在《古冢狐》中，写下“女为狐媚害即深，日长月增溺人心。何况褒妲之色善蛊惑，能丧人家覆人国“等诗句。</p><h5 id="宋朝"><a href="#宋朝" class="headerlink" title="宋朝"></a>宋朝</h5><p>吕希哲的《吕氏杂记》记载，宋代邠地（今陕西省彬县）出现狐王庙，能施福降祸，深得百姓敬畏。但妲己也开始频繁以狐妖的形象出现在各种平话小说之中，这也对后来明代小说《封神演义》产生了一定影响。</p><h4 id="5-元、明朝"><a href="#5-元、明朝" class="headerlink" title="5.元、明朝"></a>5.元、明朝</h4><p>伴随着元代话本《武王伐纣书》和明代长篇章回小说《封神演义》的问世，进一步坐实了妲己是千年九尾金狐的化身。故事中妲己把商纣迷惑得神魂颠倒，丧失真性，原本外有忠臣良将、内有贤后淑妃的大好江山被推上改君易代的悬崖。《封神演义》的风行让狐妖的魅惑形象深入人心，狐媚祸国的观念被推向极致，让狐仙形象几乎在大众认知中被完全黑化，<strong>一句“狐狸精”，是将女子咒为娼妓的最恶毒的诅咒。</strong></p><p>除了《封神演义》之外，《西游记》中的形象也是此类狐妖传说的代表，牛魔王的小妾玉面狐狸令牛魔王和铁扇公主关系恶化，应对了前面白居易所说的“覆家”之言。随着封建社会的日益衰落，人们对鬼神之说更加迷信，狐狸的形象也变得更加妖魔化。很多流传广泛小说、戏曲中也都越来越频繁出现了狐狸精迷惑害人的故事。</p><h4 id="6-清朝"><a href="#6-清朝" class="headerlink" title="6.清朝"></a>6.清朝</h4><p>狐狸的污名一直延续到清代，《狐狸缘》、《九尾狐》小说中的狐妖，不是被收服割掉尾巴，就是被拿来比拟坏透的娼妓。</p><p>但在漫天贬斥中，有些人们的观念发生了变化，部分小说作者已经厌倦了用刻板印象描绘故事中的狐狸形象，他们开始尝试赋予小说中的人物更丰富人性，创作《聊斋志异》的蒲松龄便是其中代表，《聊斋志异》的出现，里面《<strong>王成</strong>》、《<strong>狐女</strong>》等几个勾勒出狐灵亦正亦邪的形象，给人们狐狸<strong>有仙有妖有善恶</strong>的观念。</p><p>在蒲松龄笔下，狐妖人性化的一面成为了描述的重点，这也意味着当时文人阶级自我意识的觉醒，这让他们能够用更加多元化的方式来构建笔下的人物。</p><p>但无奈《聊斋志异》中短篇故事的影响力远不及《封神演义》和《西游记》等著作，因此民间对于狐妖的看法并没有发生扭转。</p><h4 id="7-现代"><a href="#7-现代" class="headerlink" title="7.现代"></a>7.现代</h4><p>及至今日，东北地区“狐黄白柳灰”（狐、黄鼠狼、刺猬、蛇、鼠）五仙信仰中还有狐仙的一席之地。</p><p>尽管提到对狐狸的印象，大家首先想到的词肯定还是狡猾，不少小说也经常描述狐狸怎样用阴谋诡计害人，但现在小说里不再只有负面印象了，更多的描述了狐狸的家庭生存遇到的困难，狐狸妈妈的母爱，一家狐的团结互助，《再被狐狸骗一次》、《猎狐》等故事描写了狐狸家庭的亲情，在新兴的文艺作品中，狐狸的形象愈发丰满，相信在新的时代文化背景下，狐狸的形象一定会有的新的内涵，不再是污名。</p><h3 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h3><p>在我写这篇文章时，我查阅了大量资料（浏览器挂着36个还未关闭的页面，全是维基、电子书），从狐狸的形象演变中，我仿佛看到每个时代人们的内心诉求和当时社会中的流行文化，而狐狸作为一个有着悠久历史的意象，也从瑞兽变成了害人的妖怪，人们对于狐狸的形象过于片面，在全面了解狐狸后，你会发现其实狐狸也是地球的一份子，它们外貌各异，有的圆滚滚毛茸茸，有的凭借着自身奇特的长相获得人们的喜爱，而且狐狸会猎捕仓鼠做为食物，对农业可是大有助益呢。</p><h3 id="相关资料"><a href="#相关资料" class="headerlink" title="相关资料"></a>相关资料</h3><table>  <tr>    <td colspan="3">      <img src="/images/人们对狐狸的印象/中国历史.png" style="zoom:100%;" /><br />    </td>  </tr>  <tr>    <th><b>夏</b> 前21世纪 | 前17世纪</th>    <th><b>商</b> 前17世纪 | 前11世纪</th>    <th><b>秦</b> 前221年 | 前207年</th>  </tr>  <tr>    <td><b>汉</b> 前202年 ︱ 220年</td>    <td><b>南 北 朝</b> 420年 ︱ 589年</td>    <td><b>唐</b> 618年 | 907年</td>  </tr>  <tr>    <td><b>宋</b> 960年 ︱ 1279年</td>    <td><b>南宋</b> 1127年 | 1279年</td>    <td><b>元</b> 1260年/1271年 | 1368年</td>  </tr>  <tr>    <td><b>明</b> 1368年 | 1644年</td>    <td><b>清</b> 1636年/1644年 | 1912年</td>    <td></td>  </tr></table><p>参考书籍文章：</p><p><em>《山海经》《淮南子》《吴越春秋》《史记》《千字文》《古冢狐》《吕氏杂记》《武王伐纣书》《封神演义》《西游记》《狐狸缘》《九尾狐》《聊斋志异》《王成》《狐女》《再被狐狸骗一次》《猎狐》《以文学发展的视角论狐狸文化符号的认知变迁》</em></p><h3 id="番外"><a href="#番外" class="headerlink" title="番外"></a>番外</h3><h4 id="狐狸与神仙的关系"><a href="#狐狸与神仙的关系" class="headerlink" title="狐狸与神仙的关系"></a>狐狸与神仙的关系</h4><p>在道教和民间信仰中，狐狸被认为是具有灵性的动物，可以修炼成仙。修炼成仙的狐狸被称为狐仙。狐仙通常被认为具有法力，可以帮助人们实现愿望，但也有可能迷惑人心。</p><p>狐仙与神仙的关系比较复杂。一方面，狐仙被认为是神仙的追随者，可以向神仙求助。另一方面，狐仙也可能被视为妖邪，受到神仙的制约。</p><h4 id="狐狸的生物学特征"><a href="#狐狸的生物学特征" class="headerlink" title="狐狸的生物学特征"></a>狐狸的生物学特征</h4><ul><li><strong>分类地位：</strong> 犬科动物，与狼、豺的关系</li><li><strong>形态特征：</strong> 外形、毛色、体型等方面的多样性</li><li><strong>生理特征：</strong> 感官、适应环境的能力</li><li><strong>分布范围：</strong> 全球分布，不同种类的分布特点</li></ul><h4 id="狐狸的生态习性（赤狐）"><a href="#狐狸的生态习性（赤狐）" class="headerlink" title="狐狸的生态习性（赤狐）"></a>狐狸的生态习性（赤狐）</h4><ul><li><strong>生活习性：</strong> 通常成对或以家庭为单位组成小团体</li><li><strong>食性：</strong> 赤狐主要以啮齿类为食，但有时也捕食兔子、松鼠、禽类、爬行动物、无脊椎动物和有蹄类幼崽，它们偶尔也吃水果和植物。（想不到吧，它还会吃素）</li><li><strong>繁殖：</strong> 赤狐的繁殖期在每年春季，孕期49-58天，一胎可产4-6崽，偶尔一胎多达13个幼崽</li><li><strong>肢体语言：</strong> 赤狐的肢体语言由耳朵、尾巴的活动以及不同的身体姿态组成。</li></ul><h4 id="狐狸与人类的关系"><a href="#狐狸与人类的关系" class="headerlink" title="狐狸与人类的关系"></a>狐狸与人类的关系</h4><ul><li><strong>历史上的狐狸：</strong> <ul><li>希腊神话中曾描绘了一只身形巨大，永远无法被捕捉的透墨索斯恶狐</li><li>在凯尔特神话中，赤狐是一种重要的动物。例如在英国科茨沃尔德，当地人相信巫师会化身为赤狐偷取邻居家的黄油。</li></ul></li><li><strong>狐狸与人类的冲突：</strong> 赤狐偶尔会捕食小鸡、羊羔，它们通常不会捕食人工饲养的动物，除非饿的不行</li><li><strong>狐狸保护：</strong> 赤狐，属于<strong>国家二级保护动物</strong></li></ul><h4 id="狐狸在文学艺术中的形象"><a href="#狐狸在文学艺术中的形象" class="headerlink" title="狐狸在文学艺术中的形象"></a>狐狸在文学艺术中的形象</h4><ul><li><strong>文学作品中的狐狸：</strong> 在欧洲民俗中，列那狐的形象象征了狡诈与欺骗。列那狐最初是公元1150年的诗歌《Ysengrimus》里的一个次要角色，而后在1175年被皮埃尔·圣克劳德编入了小说《狐狸列那》，后来又出现在杰弗里·乔叟的《修女牧师故事集》中。许多有关列那狐的冒险故事都取材于赤狐在野外的真实习性，例如列那狐与狼为敌，喜爱黑莓与葡萄。</li><li><strong>艺术作品中的狐狸：</strong> 德国表现主义画家弗兰兹‧马尔克油曾绘制过一副油画《狐狸》，该画最终以4265.45万英镑拍卖成交</li></ul><img src="/images/人们对狐狸的印象/狐狸油画.webp" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%8B%90%E7%8B%B8-%E5%9C%A8%E5%8E%86%E5%8F%B2%E7%9A%84%E9%95%BF%E6%B2%B3%E4%B8%AD%E9%80%90%E6%B8%90%E6%B1%A1%E5%90%8D%E5%8C%96</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E7%8B%90%E7%8B%B8-%E5%9C%A8%E5%8E%86%E5%8F%B2%E7%9A%84%E9%95%BF%E6%B2%B3%E4%B8%AD%E9%80%90%E6%B8%90%E6%B1%A1%E5%90%8D%E5%8C%96"/>
    <published>2024-12-09T06:53:50.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="狐狸-在历史的长河中逐渐污名化"><a href="#狐狸-在历史的长河中逐渐污名化" class="headerlink" title="狐狸-在历史的长河中逐渐污名化"></a>狐狸-在历史的长河中逐渐污名化</h2><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>近来互联网上开始流传一个热梗：狐主任。</p>
<img]]>
    </summary>
    <title>狐狸-在历史的长河中逐渐污名化</title>
    <updated>2025-10-07T06:37:42.640Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="嘉立创开源工程" scheme="https://hcyhub.com/categories/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/"/>
    <category term="嘉立创" scheme="https://hcyhub.com/tags/%E5%98%89%E7%AB%8B%E5%88%9B/"/>
    <category term="PCB" scheme="https://hcyhub.com/tags/PCB/"/>
    <category term="硬件开源" scheme="https://hcyhub.com/tags/%E7%A1%AC%E4%BB%B6%E5%BC%80%E6%BA%90/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="厦门地铁图1-0（标准版-专业版）1-1（专业版）-喷锡版（专业版）制作完毕！"><a href="#厦门地铁图1-0（标准版-专业版）1-1（专业版）-喷锡版（专业版）制作完毕！" class="headerlink" title="厦门地铁图1.0（标准版&amp;专业版）1.1（专业版） 喷锡版（专业版）制作完毕！"></a>厦门地铁图1.0（标准版&amp;专业版）1.1（专业版） 喷锡版（专业版）制作完毕！</h2><p>此工程一共有四个版本，分别是：</p><ol><li><strong>1.0版本</strong> ，此版本有标准版和专业版的，区别在于专业版的用了布尔运算合并了填充区域；</li><li><strong>1.1版本</strong> ，此版本将字符位置移动到了地图上的陆地地区，微调客编区，并将顶上的厦门地铁图及其英文纵向放置；</li><li><strong>喷锡版</strong> ，此版本在1.1版本上将海洋区域放置开窗区喷锡，让锡模拟波光粼粼的大海。</li></ol><p>以下是三个版本的截图，我建议1.0、1.1版本用沉金工艺做比较好看，喷锡版建议用喷锡就好，当然，你也可以用沉金（要是能地铁路线用沉金，海洋部分用喷锡就好了）</p><p>啥？你问我什么时候开源？明年，因为今年开源的话积分会过期（悲~）</p><img src="/images/嘉立创开源工程/厦门地铁图/厦门地铁图1.0.webp" alt="1.0版本" style="zoom:67%;" /><img src="/images/嘉立创开源工程/厦门地铁图/厦门地铁图1.1.webp" alt="1.1版本" style="zoom:67%;" /><img src="/images/嘉立创开源工程/厦门地铁图/厦门地铁图喷锡版.webp" alt="喷锡版" style="zoom:67%;" />]]>
    </content>
    <id>https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E5%8E%A6%E9%97%A8%E5%9C%B0%E9%93%81%E5%9B%BE</id>
    <link href="https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E5%8E%A6%E9%97%A8%E5%9C%B0%E9%93%81%E5%9B%BE"/>
    <published>2024-12-08T06:07:36.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="厦门地铁图1-0（标准版-专业版）1-1（专业版）-喷锡版（专业版）制作完毕！"><a href="#厦门地铁图1-0（标准版-专业版）1-1（专业版）-喷锡版（专业版）制作完毕！" class="headerlink" title="厦门地铁图1.0（标准版&amp;专业版）1.1（专业版） 喷锡版（专业版）制作完毕！"></a>厦门地铁图1.0（标准版&amp;专业版）1.1（专业版）]]>
    </summary>
    <title>厦门地铁图开源预告</title>
    <updated>2025-01-23T05:39:43.840Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="编程" scheme="https://hcyhub.com/categories/%E7%BC%96%E7%A8%8B/"/>
    <category term="编程" scheme="https://hcyhub.com/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <category term="游戏汉化" scheme="https://hcyhub.com/tags/%E6%B8%B8%E6%88%8F%E6%B1%89%E5%8C%96/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="驾驶TU-95汉化版"><a href="#驾驶TU-95汉化版" class="headerlink" title="驾驶TU-95汉化版"></a>驾驶TU-95汉化版</h2><p>这个游戏我我小时候玩的，那时看不懂，只能一通瞎操作，坠机次数起码得有几十次，那时候百思不得其解，现在看得懂怎么操作了，成功过关，但因为英文看着实在难受，于是忍无可忍的我决定汉化它。</p><h3 id="项目立项"><a href="#项目立项" class="headerlink" title="项目立项"></a>项目立项</h3><p>2024年11月24日下午16点28分，正式新建好了文件夹</p><h3 id="汉化进度"><a href="#汉化进度" class="headerlink" title="汉化进度"></a>汉化进度</h3><p>16点29分，导入字体成功</p><p>16点29分，首页汉化完毕</p><p>16点59分，汉化第一个任务</p><p>17点17分，掌握技巧，熟练度+1</p><p>18点30分，汉化一半，吃饭</p><p>19点14分17秒，汉化完毕！</p><h2 id="成品"><a href="#成品" class="headerlink" title="成品"></a>成品</h2><blockquote><p>你们可以在线游玩，也可以下载后用播放器打开</p></blockquote><p><a href="https://flash.hcyhub.com/Games/%E9%A9%BE%E9%A9%B6TU-95/">Flash收藏站 | 驾驶TU-95</a></p><p>点击链接前往Flash收藏站游玩。</p><p>注：今天懒得弄在线播放，过几天再整（11月24日21点39分）</p><p>已经建立Flash纪念站–&gt;<a href="https://flash.hcyhub.com/">https://flash.hcyhub.com</a>&lt;–，可前往在线游玩（要装插件）</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BC%96%E7%A8%8B/%E6%88%91%E6%B1%89%E5%8C%96%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%B8%B8%E6%88%8F</id>
    <link href="https://hcyhub.com/%E7%BC%96%E7%A8%8B/%E6%88%91%E6%B1%89%E5%8C%96%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E6%B8%B8%E6%88%8F"/>
    <published>2024-11-24T11:39:09.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="驾驶TU-95汉化版"><a href="#驾驶TU-95汉化版" class="headerlink" title="驾驶TU-95汉化版"></a>驾驶TU-95汉化版</h2><p>这个游戏我我小时候玩的，那时看不懂，只能一通瞎操作，坠机次数起码得有几十次，那时候百思不得其解，现在看得懂怎么操作了，成功过关，但因为英文看着实在难受，于是忍无可忍的我决定汉化它。</p>
<h3 id="项目立项"><a href="#项目立项"]]>
    </summary>
    <title>我汉化的第一个游戏</title>
    <updated>2026-04-05T14:30:46.408Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="网站维护" scheme="https://hcyhub.com/categories/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/"/>
    <category term="作品集" scheme="https://hcyhub.com/tags/%E4%BD%9C%E5%93%81%E9%9B%86/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="更新网页音乐播放"><a href="#更新网页音乐播放" class="headerlink" title="更新网页音乐播放"></a>更新网页音乐播放</h2><blockquote><p>博客音乐播放器地址：<a href="https://music.hcyhub.com/">https://music.hcyhub.com</a></p></blockquote><img src="./../../images/音乐空间/播放器预览.png" style="zoom:67%;" /><p>这是我的在线音乐播放器界面，同时还有一个导航页：</p><img src="./../../images/音乐空间/导航页.png" style="zoom:67%;" /><p>这简洁优雅的界面，看着太舒服了，加加减减，还是现在这简约的风格好看，里面有星露谷物语、戴森球计划、三伏的原声音轨，还有改编于星露谷物语音乐的催眠曲，完美。</p><p>已经开源<a href="https://github.com/2010HCY/web-music-player">https://github.com/2010HCY/web-music-player</a></p><h3 id="2026-2-28更新"><a href="#2026-2-28更新" class="headerlink" title="2026.2.28更新"></a>2026.2.28更新</h3><p>今天把前几天更新一起推送了，本次大更新同样是把音乐空间做成了SSG网站方便更新维护，并给音乐空间加上了导航栏、页脚，关于页和友链页 <del>没错我是CV Flash收藏站的模板的</del>，并加入了搜索功能，可以搜索指定曲目或专辑、章节，然后一键跳转播放。<del>没错搜索JS也是我直接拿Flash收藏站的改的</del>。</p><img src="./../../images/音乐空间/关于页.png" alt="关于页" style="zoom:67%;" /><p>音乐空间也建立了一年多了，陆续上线了20个游戏的原声音轨，一开始它叫原声音轨播放网站，现在改名叫音乐空间了，因为未来我将不再局限于游戏的原声音轨，会加入更多好听的音乐分类，同时播放页也会改改，使其能够往下滚动查看更多介绍。</p><p>原先开源的项目就一个HTML页面，未来可能会考虑把SSG生成器模板文件整理放上去。</p><img src="./../../images/音乐空间/首页.png" alt="首页" style="zoom:67%;" /><h3 id="2026-3-17更新"><a href="#2026-3-17更新" class="headerlink" title="2026.3.17更新"></a>2026.3.17更新</h3><img src="./../../images/音乐空间/以前的移动端样式.png" alt="以前的移动端样式" style="zoom:67%;" /><p>这是以前的移动端样式，因为是直接沿用了 PC 端的横向布局思维，完美踩着了移动端<strong>横向宽度受限</strong>的缺点，空余大量的纵向空间，所以我改了，改成了下面的样子：</p><img src="./../../images/音乐空间/移动端适配.png" alt="移动端适配" style="zoom:67%;" /><p>新版移动端样式采用上下布局充分利用每一寸空间，同时，还给播放页丰富了页面内容：</p><img src="./../../images/音乐空间/播放页更新.png" alt="播放页更新" style="zoom:67%;" /><p>加入了全站统一的页首页脚，方便返回首页（怎么说呢，虽然浏览器自带后退按钮，但是网站在方便的位置加一个返回按钮仍会大大提升使用体验。），试着往下滑还能解锁评论区，今天暂时只想到这些，有空继续添加页面元素。</p><h3 id="2026-4-21更新"><a href="#2026-4-21更新" class="headerlink" title="2026.4.21更新"></a>2026.4.21更新</h3><img src="./../../images/音乐空间/曲目时间显示.png" alt="曲目时间显示" style="zoom:67%;" /><p>新增了显示曲目时长，更完善，同时新增了预加载功能，曲目播放到最后15秒时灰预加载下一首音乐，尽可能使得音乐不停气氛不断。</p><h3 id="2026-4-22更新"><a href="#2026-4-22更新" class="headerlink" title="2026.4.22更新"></a>2026.4.22更新</h3><p>先来看两张更新前后的界面对比：</p><p>更新前（浏览器默认 audio 播放器）：<br><img src="./../../images/音乐空间/浏览器默认audio播放器.png" alt="浏览器默认audio播放器" style="zoom:67%;" /></p><p>更新后（纯 DOM 重构的自定义播放器）：<br><img src="./../../images/音乐空间/纯DOM复刻浏览器默认audio播放器.png" alt="纯DOM复刻浏览器默认audio播放器" style="zoom:67%;" /></p><p>如果我不说，在视觉上是不是几乎看不出任何差别？—— <strong>而这正是本次重构的精髓所在。</strong></p><p>在过去，我使用的是浏览器原生媒体控件，实现起来极其简单，仅需一行代码：<br><code>&lt;audio id=&quot;audioPlayer&quot; class=&quot;progress-bar&quot; controls=&quot;&quot; src=&quot;/api/music/Alto/Alto&#39;s Adventure/01 Alto&#39;s Theme.mp3&quot;&gt;&lt;/audio&gt;</code></p><p>但原生的便捷也带来了致命的缺点：<strong>扩展性为零</strong>。原生播放器的 UI 是由浏览器底层封闭的 <code>User Agent Shadow DOM</code> 渲染的，这导致它的下限极低（一行代码就能用），但上限也完全被锁死——它有且只有这一种固定形态，我根本无法往里面塞入任何自定义的功能按钮。</p><p>为了让播放器支持单曲循环、随机播放等功能，我不得不使用DOM从零复刻一个播放器。我禁用了原生控件，完全使用纯 <code>div</code>、<code>SVG</code> 图标，从零复刻了一个长得和原生 Chrome 播放器一模一样的 UI 外壳。</p><p>这套纯 DOM 方案在视觉和交互（如音量条悬浮展开）上做到了完美还原，让我以后可以添加更多的功能。效果非常完美，这是重构后的更多菜单：</p><img src="./../../images/音乐空间/新加的菜单样子.png" alt="新加的菜单样子" style="zoom:67%;" /><p>播放模式设置（现在终于可以单曲循环了！）：</p><img src="./../../images/音乐空间/播放模式设置.png" alt="播放模式设置" style="zoom:67%;" /><p>并且，因为样式现在完全是由我定义，所以我可以确保我的播放器在各大浏览器<del>（IE死开）</del>、系统上完全一致了！终于不用在Firefox上看见那丑不拉几的播放器控件了。</p><p>更新前：</p><img src="./../../images/音乐空间/原先Firefox播放器控件样式.png" alt="原先Firefox播放器控件样式" style="zoom:67%;" /><p>更新后：</p><img src="./../../images/音乐空间/更新后Firefox播放器控件样式.png" alt="更新后Firefox播放器控件样式" style="zoom:67%;" /><h2 id="Flash收藏站成立"><a href="#Flash收藏站成立" class="headerlink" title="Flash收藏站成立"></a>Flash收藏站成立</h2><blockquote><p>Flash纪念站地址：<a href="https://flash.hcyhub.com/">https://flash.hcyhub.com</a></p></blockquote><p>这里面收藏了我小时候最爱的游戏，并且每一个英文游戏都有人工汉化（我亲自汉化）</p><p>而且我会同时收录原版，我汉化的版本，能够一键丝滑切换。</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E9%9F%B3%E4%B9%90%E7%A9%BA%E9%97%B4</id>
    <link href="https://hcyhub.com/%E7%BD%91%E7%AB%99%E7%BB%B4%E6%8A%A4/%E9%9F%B3%E4%B9%90%E7%A9%BA%E9%97%B4"/>
    <published>2024-11-24T11:39:09.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="更新网页音乐播放"><a href="#更新网页音乐播放" class="headerlink" title="更新网页音乐播放"></a>更新网页音乐播放</h2><blockquote>
<p>博客音乐播放器地址：<a href="https://music.hcyhub.com/">https://music.hcyhub.com</a></p>
</blockquote>
<img]]>
    </summary>
    <title>音乐空间</title>
    <updated>2026-04-22T06:43:16.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="Cloudflare" scheme="https://hcyhub.com/tags/Cloudflare/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="cloudflare今天发了42封邮件轰炸我"><a href="#cloudflare今天发了42封邮件轰炸我" class="headerlink" title="cloudflare今天发了42封邮件轰炸我"></a>cloudflare今天发了42封邮件轰炸我</h2><p>中午起床一看信箱，好家伙，20封来自cloudflare的邮件，提示我我的网站tls加密升级了，我邮件还没看完，霍，又来3封，这些邮件内容全是一模一样的，</p><img src="/images/cloudflare的邮件/中午.png" style="zoom:80%;" /><p>然后我下线了几小时，再次上线后，好家伙，整整42封邮件（看下图）</p><img src="/images/cloudflare的邮件/统计.png" style="zoom:80%;" /><p>如下是完整的邮件列表，恐怖如斯：</p><img src="/images/cloudflare的邮件/全部.png" style="zoom:80%;" />]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/cloudflare%E4%BD%A0%E8%BF%98%E5%A5%BD%E5%90%97</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/cloudflare%E4%BD%A0%E8%BF%98%E5%A5%BD%E5%90%97"/>
    <published>2024-11-22T08:37:35.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="cloudflare今天发了42封邮件轰炸我"><a href="#cloudflare今天发了42封邮件轰炸我" class="headerlink"]]>
    </summary>
    <title>发疯的cloudflare</title>
    <updated>2025-10-07T06:37:06.784Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="嘉立创开源工程" scheme="https://hcyhub.com/categories/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/"/>
    <category term="嘉立创" scheme="https://hcyhub.com/tags/%E5%98%89%E7%AB%8B%E5%88%9B/"/>
    <category term="PCB" scheme="https://hcyhub.com/tags/PCB/"/>
    <category term="硬件开源" scheme="https://hcyhub.com/tags/%E7%A1%AC%E4%BB%B6%E5%BC%80%E6%BA%90/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="信息"><a href="#信息" class="headerlink" title="信息"></a>信息</h2><ul><li>复刻成本：15元 <a href="/images/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%AD%90%E5%85%AB%E5%8D%A6%E7%9B%98/BOM_%E7%94%B5%E5%AD%90%E5%85%AB%E5%8D%A6%E7%9B%98%E5%BC%80%E6%BA%90%E7%89%88.xlsx">BOM文件下载</a></li><li>嘉立创开源链接：<a href="https://oshwhub.com/ethaniel/electronic-eight-diagrams-open-s">https://oshwhub.com/ethaniel/electronic-eight-diagrams-open-s</a></li><li>制板文件：<a href="/images/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%AD%90%E5%85%AB%E5%8D%A6%E7%9B%98/Gerber_%E7%94%B5%E5%AD%90%E5%85%AB%E5%8D%A6%E7%9B%98.zip">下载</a></li></ul><h2 id="电子八卦盘"><a href="#电子八卦盘" class="headerlink" title="电子八卦盘"></a>电子八卦盘</h2><blockquote><p>专业解决赛博灵异事件，监测赛博幽灵，电子八卦盘你值得拥有！</p></blockquote><p>电子八卦盘，精致的外观，完美的卦象，适用于安抚机魂，解决匪夷所思的电脑问题[doge]</p><p>正面为卦象面，反面是元器件面，带有LED发亮功能，触摸开关，个人标识区（比如你的Logo），电源5V输入，需自备电池充放电模块。</p><p>Logo不要放置在挖空区域，会影响透光，注意不要让其他金属物体靠近后面的焊接区域，要不然短路会搞坏触摸芯片</p><p>仿真图：</p><img src="/images/嘉立创开源工程/电子八卦盘/电子八卦盘正面.webp" alt="正面" style="zoom:30%;" /><img src="/images/嘉立创开源工程/电子八卦盘/电子八卦盘反面.webp" alt="反面" style="zoom:30%;" /><p>实物：</p><img src="/images/嘉立创开源工程/电子八卦盘/1.webp" style="zoom:10%;" /><img src="/images/嘉立创开源工程/电子八卦盘/2.webp" style="zoom:10%;" /><h2 id="成本详情"><a href="#成本详情" class="headerlink" title="成本详情"></a>成本详情</h2><table><thead><tr><th>PCB</th><th>BOM</th><th>电池</th><th>充放电模块</th></tr></thead><tbody><tr><td>可免费打样，不用券20元</td><td>10元</td><td>2元</td><td>3元</td></tr></tbody></table><p>注：不包含运费</p>]]>
    </content>
    <id>https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%AD%90%E5%85%AB%E5%8D%A6%E7%9B%98</id>
    <link href="https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%AD%90%E5%85%AB%E5%8D%A6%E7%9B%98"/>
    <published>2024-11-15T15:36:03.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="信息"><a href="#信息" class="headerlink" title="信息"></a>信息</h2><ul>
<li>复刻成本：15元 <a]]>
    </summary>
    <title>电子八卦盘</title>
    <updated>2025-01-23T05:39:40.543Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="嘉立创开源工程" scheme="https://hcyhub.com/categories/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/"/>
    <category term="嘉立创" scheme="https://hcyhub.com/tags/%E5%98%89%E7%AB%8B%E5%88%9B/"/>
    <category term="PCB" scheme="https://hcyhub.com/tags/PCB/"/>
    <category term="硬件开源" scheme="https://hcyhub.com/tags/%E7%A1%AC%E4%BB%B6%E5%BC%80%E6%BA%90/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="信息"><a href="#信息" class="headerlink" title="信息"></a>信息</h2><ul><li>复刻成本8.6035元</li><li>嘉立创开源链接：<a href="https://oshwhub.com/ethaniel/gao-ya-mu-kuai_copy">https://oshwhub.com/ethaniel/gao-ya-mu-kuai_copy</a></li><li>制板文件：<a href="/images/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%8E%8B%E5%80%8D%E5%A2%9E%E6%A8%A1%E5%9D%97/Gerber_%E7%94%B5%E5%8E%8B%E5%80%8D%E5%A2%9E%E6%A8%A1%E5%9D%97.zip">下载</a></li></ul><h2 id="描述"><a href="#描述" class="headerlink" title="描述"></a>描述</h2><p>这是一个电压倍增模块，设计用于给高压模块输出的电流升压，使电弧更长，升压模块，懂吧</p><p>输入端可以用电弧打火机的高压模块（当然，其他的高压模块也行，我设计是用一个不知道什么机器上拆的废旧的迷你高压逆变器）</p><p>在不考虑运费的前提下，2024.11.10日材料成本如下：</p><table><thead><tr><th>名称</th><th>单价（元）</th><th>数量</th><th>总价（单位元）</th><th>备注</th></tr></thead><tbody><tr><td>电路板</td><td>20</td><td>1个以上</td><td>20</td><td>嘉立创可以<a href="https://lceda.cn/editor#project_id=2ae2d71b73c94abc826f30ba0aaca87a">免费打样</a>，不考虑打样券的话20元</td></tr><tr><td>9.1钠法的CBB电容</td><td>0.7991</td><td>1~3个</td><td>0.7991~2.3973</td><td>根据需求添加电容数量，只用一个也行，但记得修改PCB。型号<a href="https://item.szlcsc.com/3198282.html?fromZone=s_s__%2522C2913185%2522">CAP-TH_L24.0-W13.5-P22.5-D0.7</a></td></tr><tr><td>高压二极管</td><td>1.8880</td><td>3</td><td>5.664</td><td>型号<a href="https://item.szlcsc.com/418065.html?fromZone=s_s__%2522C424513%2522">DIO-TH_BD3.0-L12.0-P16.00-D0.6</a>，2CL77款</td></tr><tr><td>150PF独石电容</td><td>0.2711</td><td>2</td><td>0.5422</td><td>型号<a href="https://item.szlcsc.com/297366.html?fromZone=s_s__%2522C315664%2522">CAP-TH_L4.2-W3.8-P5.08-D0.6</a>，制造商风华</td></tr></tbody></table><p>注：制造商，型号其实不重要，重要的是能不能装上去，数值对不对，以上价格来自嘉立创商城，若自行购买清单在下面</p><table><thead><tr><th>PCB电路板</th><th>9.1钠法的CBB电容</th><th>高压二极管</th><th>150PF独石电容</th></tr></thead><tbody><tr><td>x1</td><td>x3</td><td>x3</td><td>x2</td></tr></tbody></table>]]>
    </content>
    <id>https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%8E%8B%E5%80%8D%E5%A2%9E%E7%94%B5%E8%B7%AF</id>
    <link href="https://hcyhub.com/%E5%98%89%E7%AB%8B%E5%88%9B%E5%BC%80%E6%BA%90%E5%B7%A5%E7%A8%8B/%E7%94%B5%E5%8E%8B%E5%80%8D%E5%A2%9E%E7%94%B5%E8%B7%AF"/>
    <published>2024-11-10T11:36:03.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="信息"><a href="#信息" class="headerlink" title="信息"></a>信息</h2><ul>
<li>复刻成本8.6035元</li>
<li>嘉立创开源链接：<a]]>
    </summary>
    <title>电压倍增电路</title>
    <updated>2025-10-07T06:34:16.445Z</updated>
  </entry>
  <entry>
    <author>
      <name>Ethaniel</name>
    </author>
    <category term="生活随记" scheme="https://hcyhub.com/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <category term="生活随记" scheme="https://hcyhub.com/tags/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/"/>
    <content>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="长满头发的猫"><a href="#长满头发的猫" class="headerlink" title="长满头发的猫"></a>长满头发的猫</h2><p>昨晚做了个梦，梦见在一个下午，阳光透过玻璃照进来，我正一边撸着一只小猫，一边和人聊天（不记得聊啥了）。</p><p>撸着撸着，我发现猫的手感变了，原本是毛绒绒的，带有一点温度，现在慢慢的变了，变成了冰冰的，油油的，毛发变得细长，我转过头一看，小猫原本身上的毛变成了一根根乌黑的长发，因为油油的所以带着反光，而小猫却仍然闭着眼睛享受，仿佛它身上什么变化也没有。</p><img src="/images/长满头发的猫.webp" alt="AI生成的，完全不像，我梦到的是没有绒毛的，猫身上的头发是长发" style="zoom:60%;" /><p>这个噩梦好像也不算噩梦，因为我并没有被吓到（要是我被吓到了就不会写出来了），但醒来后我却百思不得其解，我从未见过长满头发的猫，甚至我很难将猫和头发联系起来，但我是怎么在梦中梦到的呢？醒来后感觉这样的猫十分的怪诞，令人不安。</p>]]>
    </content>
    <id>https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%9C%80%E8%BF%91%E5%81%9A%E7%9A%84%E6%A2%A6</id>
    <link href="https://hcyhub.com/%E7%94%9F%E6%B4%BB%E9%9A%8F%E8%AE%B0/%E6%9C%80%E8%BF%91%E5%81%9A%E7%9A%84%E6%A2%A6"/>
    <published>2024-11-01T00:50:58.000Z</published>
    <summary>
      <![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h2 id="长满头发的猫"><a href="#长满头发的猫" class="headerlink"]]>
    </summary>
    <title>昨晚的噩梦：长满头发的猫</title>
    <updated>2025-10-07T06:36:31.766Z</updated>
  </entry>
</feed>
