<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Alexander</title><description>生活原本沉闷，但跑起来就有风</description><link>https://idea.lanerc.me/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>V3.0.2</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年11月5日 10:57:04</lastBuildDate><item><title>本站 MDX 组件介绍与使用方法</title><link>https://idea.lanerc.me/posts/others-blog-mdx-components/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/others-blog-mdx-components/</guid><description>本站 MDX 组件使用说明：介绍 MDX 如何在 Markdown 中嵌入 Astro 组件，系统整理行级与行内组件的用途、参数和写法，并为每个组件提供可直接复制的语法示例与渲染演示，方便在文章、关于页和项目记录中快速选用与组合。</description><pubDate>Thu, 22 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>import Accordion from "@components/mdx/Accordion.astro";
import Badge from "@components/mdx/Badge.astro";
import Blur from "@components/mdx/Blur.astro";
import CardList from "@components/mdx/CardList.astro";
import Chat from "@components/mdx/Chat.astro";
import Folding from "@components/mdx/Folding.astro";
import Key from "@components/mdx/Key.astro";
import LinkCard from "@components/mdx/LinkCard.astro";
import LinkBanner from "@components/mdx/LinkBanner.astro";
import ProfileCard from "@components/mdx/ProfileCard.astro";
import SocialLinks from "@components/mdx/SocialLinks.astro";
import Timeline from "@components/mdx/Timeline.astro";
import Tip from "@components/mdx/Tip.astro";
import Alert from "@components/mdx/Alert.astro";
import ArtText from "@components/mdx/ArtText.astro";
import CodeLang from "@components/mdx/CodeLang.astro";
import Copy from "@components/mdx/Copy.astro";
import EmojiTail from "@components/mdx/EmojiTail.astro";
import Pic from "@components/mdx/Pic.astro";
import Quote from "@components/mdx/Quote.astro";
import Tab from "@components/mdx/Tab.astro";
import Tabs from "@components/mdx/Tabs.astro";
import Title from "@components/mdx/Title.astro";
import VideoEmbed from "@components/mdx/VideoEmbed.astro";
import { siteConfig } from "@/config";</p>
<p>export const ownerAvatar = siteConfig.avatar.owner;</p>
<p>MDX 是 Markdown 的超集：在普通 Markdown 里可以直接写 JSX/Astro 组件，让文章从纯文本变成可交互的内容。本站把常用的正文能力封装成 MDX 组件，写文章时用一套简短的指令即可插入提示框、标签页、时间线、链接卡片、图片和视频等内容。</p>
<p>组件按写法分为两类：</p>
<ul>
<li><strong>行级</strong>：以 <code>::name{...}</code> 或 <code>:::name{...}</code> 独占一行，适合提示框、时间线、标签页、链接卡片等块状内容。</li>
<li><strong>行内</strong>：以 <code>:name[文字]{...}</code> 嵌在句子中，适合徽章、键帽、术语提示、复制、艺术字等文字级标记。</li>
</ul>
<p>本站目前提供的组件：</p>
<p><strong>行级组件</strong></p>
<table>
<thead>
<tr>
<th>组件</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><a href="#%E6%89%8B%E9%A3%8E%E7%90%B4-accordion">手风琴 Accordion</a></td>
<td>分组卡片，适合技术栈和入口列表</td>
</tr>
<tr>
<td><a href="#%E6%97%B6%E9%97%B4%E7%BA%BF-timeline">时间线 Timeline</a></td>
<td>可展开的时间线记录</td>
</tr>
<tr>
<td><a href="#%E5%AF%B9%E8%AF%9D-chat">对话 Chat</a></td>
<td>用户、助手和系统消息气泡</td>
</tr>
<tr>
<td><a href="#%E7%A4%BE%E4%BA%A4%E9%93%BE%E6%8E%A5-sociallinks">社交链接 SocialLinks</a></td>
<td>行级容器，渲染为行内社交头像组</td>
</tr>
<tr>
<td><a href="#%E6%8A%98%E5%8F%A0%E9%9D%A2%E6%9D%BF-folding">折叠面板 Folding</a></td>
<td>纸面折叠内容，带展开过渡</td>
</tr>
<tr>
<td><a href="#%E5%8D%A1%E7%89%87%E5%88%97%E8%A1%A8-cardlist">卡片列表 CardList</a></td>
<td>把 Markdown 列表渲染成卡片</td>
</tr>
<tr>
<td><a href="#%E9%93%BE%E6%8E%A5%E5%8D%A1%E7%89%87-linkcard">链接卡片 LinkCard</a></td>
<td>站外链接卡片，可组成响应式网格</td>
</tr>
<tr>
<td><a href="#%E9%93%BE%E6%8E%A5%E6%A8%AA%E5%B9%85-linkbanner">链接横幅 LinkBanner</a></td>
<td>横向大图链接横幅</td>
</tr>
<tr>
<td><a href="#%E6%8F%90%E7%A4%BA%E6%A1%86-alert">提示框 Alert</a></td>
<td>带类型配色的提示块，支持 card 和 flat</td>
</tr>
<tr>
<td><a href="#%E6%A0%87%E7%AD%BE%E9%A1%B5-tabs">标签页 Tabs</a></td>
<td>多标签内容容器</td>
</tr>
<tr>
<td><a href="#%E9%87%91%E5%8F%A5-quote">金句 Quote</a></td>
<td>带装饰图标的引用块</td>
</tr>
<tr>
<td><a href="#%E6%A0%87%E9%A2%98%E8%A3%85%E9%A5%B0-title">标题装饰 Title</a></td>
<td>带装饰线的标题块</td>
</tr>
<tr>
<td><a href="#%E5%9B%BE%E7%89%87%E7%94%BB%E5%BB%8A-pic">图片画廊 Pic</a></td>
<td>单图与多种宫格画廊</td>
</tr>
<tr>
<td><a href="#%E8%A7%86%E9%A2%91%E5%B5%8C%E5%85%A5-videoembed">视频嵌入 VideoEmbed</a></td>
<td>嵌入 Bilibili 或 YouTube 视频</td>
</tr>
<tr>
<td><a href="#%E8%A1%A8%E6%83%85%E5%8C%85%E8%83%8C%E6%99%AF-emojitail">表情包背景 EmojiTail</a></td>
<td>正文后方堆叠表情装饰</td>
</tr>
</tbody></table>
<p><strong>行内组件</strong></p>
<table>
<thead>
<tr>
<th>组件</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><a href="#%E5%BE%BD%E7%AB%A0-badge">徽章 Badge</a></td>
<td>行内胶囊标签</td>
</tr>
<tr>
<td><a href="#%E9%94%AE%E5%B8%BD-key">键帽 Key</a></td>
<td>键帽样式，适合快捷键说明</td>
</tr>
<tr>
<td><a href="#%E6%9C%AF%E8%AF%AD%E6%8F%90%E7%A4%BA-tip">术语提示 Tip</a></td>
<td>术语下划线加悬停解释</td>
</tr>
<tr>
<td><a href="#%E8%A1%8C%E5%86%85%E5%A4%8D%E5%88%B6-copy">行内复制 Copy</a></td>
<td>点击复制正文内容</td>
</tr>
<tr>
<td><a href="#%E4%BB%A3%E7%A0%81%E8%AF%AD%E8%A8%80%E6%A0%87-codelang">代码语言标 CodeLang</a></td>
<td>带语言标签的行内代码</td>
</tr>
<tr>
<td><a href="#%E4%BA%BA%E7%89%A9%E5%90%8D%E7%89%87-profilecard">人物名片 ProfileCard</a></td>
<td>悬停或聚焦展开的人物名片</td>
</tr>
<tr>
<td><a href="#%E6%A8%A1%E7%B3%8A-blur">模糊 Blur</a></td>
<td>悬停或聚焦后显现，支持块级</td>
</tr>
<tr>
<td><a href="#%E8%89%BA%E6%9C%AF%E5%AD%97-arttext">艺术字 ArtText</a></td>
<td>四种行内艺术字变体</td>
</tr>
</tbody></table>
<p>使用前有三条约定：</p>
<ol>
<li>组件要在 MDX 顶部 <code>import</code>，指令只负责生成对应的组件。</li>
<li>非字符串参数用 <code>$变量</code>，变量在顶层 import 或 <code>export const</code> 定义。</li>
<li><code>{}</code> 会被 MDX 当作表达式，Accordion / Timeline 的行式 DSL 必须放在代码围栏内。</li>
</ol>
<h2>行级组件</h2>
<h3>手风琴 Accordion</h3>
<p>分组卡片手风琴。分组行控制标题和默认展开状态，卡品行定义名称、描述、链接和图标。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>label</code></td>
<td>否</td>
<td>组件 aria-label，默认“手风琴”</td>
</tr>
<tr>
<td>分组行</td>
<td>是</td>
<td><code>{标题 · open}</code>；<code>open</code> 控制默认展开</td>
</tr>
<tr>
<td>卡品行</td>
<td>是</td>
<td>依次填写名称、描述、URL、图标、颜色、深色颜色；最后一项可省略</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::accordion{label="MDX 组件速查"}
```accordion
{基础组件 · open}
- Badge | 行内小标签 | https://mdxjs.com | material-symbols:label | #00a29b
- Key | 键帽样式 | https://developer.mozilla.org/docs/Web/HTML/Element/kbd | material-symbols:keyboard-arrow-up-rounded | #8b5cf6

{内容容器}
- Folding | 折叠面板 | https://developer.mozilla.org/docs/Web/HTML/Element/details | material-symbols:folder-outline | #2563eb
- CardList | 卡片式列表 | https://developer.mozilla.org/docs/Web/HTML/Element/ul | material-symbols:format-list-bulleted-rounded | #d97706
```
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::accordion{label="MDX 组件速查"}</p>
<pre><code class="language-accordion">{基础组件 · open}
- Badge | 行内小标签 | https://mdxjs.com | material-symbols:label | #00a29b
- Key | 键帽样式 | https://developer.mozilla.org/docs/Web/HTML/Element/kbd | material-symbols:keyboard-arrow-up-rounded | #8b5cf6

{内容容器}
- Folding | 折叠面板 | https://developer.mozilla.org/docs/Web/HTML/Element/details | material-symbols:folder-outline | #2563eb
- CardList | 卡片式列表 | https://developer.mozilla.org/docs/Web/HTML/Element/ul | material-symbols:format-list-bulleted-rounded | #d97706
</code></pre>
<p>:::</p>
<h3>时间线 Timeline</h3>
<p>可展开的时间线。每条记录包含时间、标题、可选标签、图标和色调，详情写在记录行下方。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>label</code></td>
<td>否</td>
<td>组件 aria-label，默认“时间线”</td>
</tr>
<tr>
<td>记录行</td>
<td>是</td>
<td><code>{时间 · 标题 · 可选标签 · icon=图标 · tone=色调}</code></td>
</tr>
<tr>
<td>详情</td>
<td>是</td>
<td>记录行下方的文本，多行合并成一段</td>
</tr>
<tr>
<td><code>tone</code></td>
<td>否</td>
<td><code>neutral</code>、<code>success</code>、<code>danger</code></td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::timeline{label="MDX 组件时间线"}
```timeline
{2026.05 · 建立组件目录 · 起点 · icon=mdi:source-fork}
把散落在关于页的专属组件收进统一的 MDX 组件库。

{2026.10 · 接入指令糖 · icon=material-symbols:auto-awesome · tone=success}
::: 容器与 :badge[] 行内指令可以直接映射到 Astro 组件。

{2026.10 · 补齐通用组件 · icon=material-symbols:sync-rounded}
新增 Chat、Folding、LinkCard 等正文组件。
```
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::timeline{label="MDX 组件时间线"}</p>
<pre><code class="language-timeline">{2026.05 · 建立组件目录 · 起点 · icon=mdi:source-fork}
把散落在关于页的专属组件收进统一的 MDX 组件库。

{2026.10 · 接入指令糖 · icon=material-symbols:auto-awesome · tone=success}
::: 容器与 :badge[] 行内指令可以直接映射到 Astro 组件。

{2026.10 · 补齐通用组件 · icon=material-symbols:sync-rounded}
新增 Chat、Folding、LinkCard 等正文组件。
</code></pre>
<p>:::</p>
<h3>对话 Chat</h3>
<p>对话气泡。角色行区分用户、助手和系统消息，消息文本按纯文本渲染。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>:u</code></td>
<td>是</td>
<td>用户消息</td>
</tr>
<tr>
<td><code>:a</code></td>
<td>是</td>
<td>助手回复</td>
</tr>
<tr>
<td><code>:s</code></td>
<td>否</td>
<td>系统提示</td>
</tr>
<tr>
<td><code>:u{name="..."}</code></td>
<td>否</td>
<td>指定用户显示名</td>
</tr>
<tr>
<td>消息文本</td>
<td>是</td>
<td>写在角色前缀之后，不解析 Markdown</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">::chat
:s 下面是一段组件演示
:u{name="访客"} 这些指令需要提前 import 吗
:a 要的，指令只负责换节点，组件作用域还得自己建。
::
</code></pre>
<p><strong>演示</strong></p>
<p>::chat
:s 下面是一段组件演示
:u{name="访客"} 这些指令需要提前 import 吗
:a 要的，指令只负责换节点，组件作用域还得自己建。
::</p>
<h3>社交链接 SocialLinks</h3>
<p>社交头像组。账号行按固定字段顺序填写，渲染时并入前一段末尾；超过 <code>max</code> 会折叠为 <code>+N</code>。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>label</code></td>
<td>否</td>
<td>组件 aria-label，默认“社交账号”</td>
</tr>
<tr>
<td><code>max</code></td>
<td>否</td>
<td>最多显示数量，默认 4</td>
</tr>
<tr>
<td>账号行</td>
<td>是</td>
<td>依次填写平台、昵称、备注、URL、图标、brand、状态；备注、brand、状态可空</td>
</tr>
<tr>
<td><code>brand</code></td>
<td>否</td>
<td><code>github</code>、<code>bilibili</code>、<code>qq</code></td>
</tr>
<tr>
<td><code>status</code></td>
<td>否</td>
<td><code>online</code>、<code>offline</code>、<code>none</code></td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">头像组会自动接在上一段文字末尾，适合放在一句介绍之后：

:::social-links{label="演示社交账号"}
- GitHub | MmzMing | 代码与项目 | https://github.com/MmzMing | fa7-brands:github | github | online
- B站 | Mmz明崽 | 关注一下 | https://space.bilibili.com/15446538 | fa7-brands:bilibili | bilibili | offline
- QQ群 | 加入群聊 | 吹水摸鱼 | https://qm.qq.com/q/2R07cjGTZ0 | fa7-brands:qq | qq | none
:::
</code></pre>
<p><strong>演示</strong></p>
<p>头像组会自动接在上一段文字末尾，适合放在一句介绍之后：</p>
<p>:::social-links{label="演示社交账号"}</p>
<ul>
<li>GitHub | MmzMing | 代码与项目 | <a href="https://github.com/MmzMing">https://github.com/MmzMing</a> | fa7-brands:github | github | online</li>
<li>B站 | Mmz明崽 | 关注一下 | <a href="https://space.bilibili.com/15446538">https://space.bilibili.com/15446538</a> | fa7-brands:bilibili | bilibili | offline</li>
<li>QQ群 | 加入群聊 | 吹水摸鱼 | <a href="https://qm.qq.com/q/2R07cjGTZ0">https://qm.qq.com/q/2R07cjGTZ0</a> | fa7-brands:qq | qq | none
:::</li>
</ul>
<h3>折叠面板 Folding</h3>
<p>纸面折叠面板，正文支持普通 Markdown；沿用 Accordion 的毛边纸面，但内边距、字号和展开动效更轻量。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>title</code></td>
<td>否</td>
<td>折叠标题，默认“展开查看”</td>
</tr>
<tr>
<td>内容</td>
<td>是</td>
<td>容器内的 Markdown</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::folding{title="展开查看参数说明"}
- `title`：折叠标题，默认“展开查看”。
- 正文支持列表、代码块、链接等 Markdown 语法。
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::folding{title="展开查看参数说明"}</p>
<ul>
<li><code>title</code>：折叠标题，默认“展开查看”。</li>
<li>正文支持列表、代码块、链接等 Markdown 语法。
:::</li>
</ul>
<h3>卡片列表 CardList</h3>
<p>把一组 Markdown 列表项渲染成卡片，桌面默认三列，窄屏自动降为两列或一列。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>内容</td>
<td>是</td>
<td>容器内的 Markdown 列表</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::card-list
- **行级指令**：`::` 或 `:::` 开头的指令独占一行，渲染为块级组件。
- **行内指令**：`:name[文字]` 嵌在段落中，适合标签、键帽、术语解释。
- **数据驱动**：Accordion、Timeline 只接收结构化数据，内容仍留在 MDX。
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::card-list</p>
<ul>
<li><strong>行级指令</strong>：<code>::</code> 或 <code>:::</code> 开头的指令独占一行，渲染为块级组件。</li>
<li><strong>行内指令</strong>：<code>:name[文字]</code> 嵌在段落中，适合标签、键帽、术语解释。</li>
<li><strong>数据驱动</strong>：Accordion、Timeline 只接收结构化数据，内容仍留在 MDX。
:::</li>
</ul>
<h3>链接卡片 LinkCard</h3>
<p>站外链接卡片。外观与友链卡片一致：1px 边框、卡片底色、双层投影，悬停时放大到 1.03 并加深背景、边框和阴影。单张最大宽度 <code>24rem</code> 并水平居中；连续写多个会自动合并为水平居中的网格，网格宽度 ≥ <code>44rem</code> 时 3 列，≥ <code>29rem</code> 时 2 列，其余 1 列；末行未占满时整体居中。</p>
<p>设置 <code>banner</code> 后，封面固定高度 <code>9.5rem</code>，图片居中裁切，下方保留图标、标题和描述；无图卡片保持紧凑横向布局。连续卡片之间插入段落、标题等块级内容会打断自动合并。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>link</code></td>
<td>是</td>
<td>跳转地址，新标签页打开</td>
</tr>
<tr>
<td><code>title</code></td>
<td>否</td>
<td>卡片标题，缺省时使用域名</td>
</tr>
<tr>
<td><code>desc</code></td>
<td>否</td>
<td>卡片描述，缺省时使用域名</td>
</tr>
<tr>
<td><code>icon</code></td>
<td>否</td>
<td>图标名或图片地址，显示在标题左侧</td>
</tr>
<tr>
<td><code>banner</code></td>
<td>否</td>
<td>封面图地址；固定高度 <code>9.5rem</code>，直接作为 <code>&lt;img src&gt;</code>，不走 Astro 图片优化</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">::link-card{link="https://astro.build/" title="Astro 官方站点" desc="内容驱动的静态站点框架" icon="simple-icons:astro" banner="/assets/images/example.webp"}

::link-card{link="https://mdxjs.com/" title="MDX 官方文档" desc="在 Markdown 中直接写 JSX" icon="simple-icons:mdx" banner="/assets/images/example.webp"}

::link-card{link="https://github.com/MmzMing/my-blog" title="博客源码" desc="本站的完整实现" icon="fa7-brands:github" banner="/assets/images/example.webp"}

::link-card{link="https://developer.mozilla.org/" title="MDN Web Docs" desc="Web 开发文档" icon="simple-icons:mdnwebdocs"}
</code></pre>
<p><strong>演示</strong></p>
<p>::link-card{link="<a href="https://astro.build/">https://astro.build/</a>" title="Astro 官方站点" desc="内容驱动的静态站点框架" icon="simple-icons:astro" banner="/assets/images/example.webp"}</p>
<p>::link-card{link="<a href="https://mdxjs.com/">https://mdxjs.com/</a>" title="MDX 官方文档" desc="在 Markdown 中直接写 JSX" icon="simple-icons:mdx" banner="/assets/images/example.webp"}</p>
<p>::link-card{link="<a href="https://github.com/MmzMing/my-blog">https://github.com/MmzMing/my-blog</a>" title="博客源码" desc="本站的完整实现" icon="fa7-brands:github" banner="/assets/images/example.webp"}</p>
<p>::link-card{link="<a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a>" title="MDN Web Docs" desc="Web 开发文档" icon="simple-icons:mdnwebdocs"}</p>
<h3>链接横幅 LinkBanner</h3>
<p>横向大图链接横幅，适合展示站点入口或专题；外观与友链卡片一致。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>link</code></td>
<td>是</td>
<td>跳转地址，新标签页打开</td>
</tr>
<tr>
<td><code>title</code></td>
<td>否</td>
<td>横幅标题，缺省时使用域名</td>
</tr>
<tr>
<td><code>desc</code></td>
<td>否</td>
<td>横幅描述，缺省时使用域名</td>
</tr>
<tr>
<td><code>banner</code></td>
<td>否</td>
<td>横幅图片地址，固定高度 <code>12rem</code></td>
</tr>
<tr>
<td><code>icon</code></td>
<td>否</td>
<td>图标名或图片地址</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">::link-banner{link="https://astro.build/" title="Astro 官方站点" desc="内容驱动的静态站点框架" banner="/assets/images/example.webp" icon="simple-icons:astro"}
</code></pre>
<p><strong>演示</strong></p>
<p>::link-banner{link="<a href="https://astro.build/">https://astro.build/</a>" title="Astro 官方站点" desc="内容驱动的静态站点框架" banner="/assets/images/example.webp" icon="simple-icons:astro"}</p>
<h3>提示框 Alert</h3>
<p>带类型配色的提示块，支持普通、卡片和轻量三种外观。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>type</code></td>
<td>否</td>
<td><code>tip</code>、<code>info</code>、<code>question</code>、<code>warning</code>、<code>error</code>，默认 <code>tip</code></td>
</tr>
<tr>
<td><code>title</code></td>
<td>否</td>
<td>覆盖类型默认标题</td>
</tr>
<tr>
<td><code>card</code></td>
<td>否</td>
<td>卡片风格，带顶部光晕与阴影</td>
</tr>
<tr>
<td><code>flat</code></td>
<td>否</td>
<td>轻量风格；与 <code>card</code> 同时设置时优先</td>
</tr>
<tr>
<td><code>color</code></td>
<td>否</td>
<td>自定义主题色，支持 hex、rgb、hsl、oklch、var</td>
</tr>
<tr>
<td><code>icon</code></td>
<td>否</td>
<td>覆盖默认图标，写 Iconify 名称</td>
</tr>
<tr>
<td><code>text</code></td>
<td>否</td>
<td>无正文时的回落内容</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::alert{type="tip" title="小提示"}
这里是提示框正文，支持 **加粗** 与 [链接](/about)。
:::

:::alert{type="warning" title="自定义配色" color="#7c3aed" card}
卡片风格使用顶部光晕和阴影，适合放在重点段落前。
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::alert{type="tip" title="小提示"}
这里是提示框正文，支持 <strong>加粗</strong> 与 <a href="https://idea.lanerc.me/about">链接</a>。
:::</p>
<p>:::alert{type="warning" title="自定义配色" color="#7c3aed" card}
卡片风格使用顶部光晕和阴影，适合放在重点段落前。
:::</p>
<h3>标签页 Tabs</h3>
<p>多标签内容容器。提供 <code>pill</code>、<code>underline</code> 两种样式：<code>pill</code> 为胶囊分段，<code>underline</code> 为底部下划线。标签由子 <code>Tab</code> 提供；外层用 4 个冒号包裹内层 <code>:::tab</code>。设置 <code>centered</code> 可让标签栏水平居中，切换标签时指示器会平滑滑动到目标标签，面板按方向淡入淡出，容器高度平滑过渡。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>Tabs.label</code></td>
<td>否</td>
<td>标签栏 aria-label，默认“标签页”</td>
</tr>
<tr>
<td><code>Tabs.variant</code></td>
<td>否</td>
<td><code>pill</code>、<code>underline</code>，默认 <code>underline</code></td>
</tr>
<tr>
<td><code>Tabs.centered</code></td>
<td>否</td>
<td>标签栏水平居中，默认关闭</td>
</tr>
<tr>
<td><code>Tab.label</code></td>
<td>是</td>
<td>子标签标题</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">**Pill**

::::tabs{label="Pill 示例" variant="pill"}
:::tab{label="概览"}
高层摘要。
:::
:::tab{label="动态"}
最近的用户活动与日志。
:::
:::tab{label="设置"}
管理账户偏好。
:::
::::

**Underline**

::::tabs{label="Underline 示例"}
:::tab{label="全部"}
显示全部工单。
:::
:::tab{label="进行中"}
显示需要处理的工单。
:::
:::tab{label="已关闭"}
已归档和已解决的请求。
:::
::::

**Pill + centered**

::::tabs{label="居中示例" variant="pill" centered}
:::tab{label="概览"}
标签栏在容器内水平居中。
:::
:::tab{label="设置"}
切换标签后内容同步更新。
:::
::::
</code></pre>
<p><strong>演示</strong></p>
<p><strong>Pill</strong></p>
<p>::::tabs{label="Pill 示例" variant="pill"}
:::tab{label="概览"}
高层摘要。
:::
:::tab{label="动态"}
最近的用户活动与日志。
:::
:::tab{label="设置"}
管理账户偏好。
:::
::::</p>
<p><strong>Underline</strong></p>
<p>::::tabs{label="Underline 示例"}
:::tab{label="全部"}
显示全部工单。
:::
:::tab{label="进行中"}
显示需要处理的工单。
:::
:::tab{label="已关闭"}
已归档和已解决的请求。
:::
::::</p>
<p><strong>Pill + centered</strong></p>
<p>::::tabs{label="居中示例" variant="pill" centered}
:::tab{label="概览"}
标签栏在容器内水平居中。
:::
:::tab{label="设置"}
切换标签后内容同步更新。
:::
::::</p>
<h3>金句 Quote</h3>
<p>带装饰图标的引用块，正文支持 Markdown。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>icon</code></td>
<td>否</td>
<td>装饰图标，默认消息气泡图标</td>
</tr>
<tr>
<td>内容</td>
<td>是</td>
<td>容器内的 Markdown</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::quote
知识要能被重新发现，而不是只靠标题记忆。
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::quote
知识要能被重新发现，而不是只靠标题记忆。
:::</p>
<h3>标题装饰 Title</h3>
<p>在正文中插入带装饰线的标题块。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>内容</td>
<td>是</td>
<td>标题文字</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::title
这里是装饰标题
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::title
这里是装饰标题
:::</p>
<h3>图片画廊 Pic</h3>
<p>单图或宫格图片。单图默认限制在 <code>36rem × 24rem</code> 内完整显示，设置 <code>full</code> 可取消上限；宫格提供 <code>duo</code> 双列、<code>feature</code> 首图放大两种布局，图片按格子裁切填充。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>src</code></td>
<td>单图</td>
<td>图片地址</td>
</tr>
<tr>
<td><code>layout</code></td>
<td>否</td>
<td>宫格布局：<code>duo</code>、<code>feature</code>，默认 <code>duo</code></td>
</tr>
<tr>
<td><code>caption</code></td>
<td>否</td>
<td>单图说明</td>
</tr>
<tr>
<td><code>mirror</code></td>
<td>否</td>
<td>单图水平镜像</td>
</tr>
<tr>
<td><code>full</code></td>
<td>否</td>
<td>单图取消默认尺寸上限，按内容宽度完整显示</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">::pic{src="/assets/images/example.webp" caption="示例图片"}
</code></pre>
<p><strong>演示</strong></p>
<p>::pic{src="/assets/images/example.webp" caption="示例图片"}</p>
<p><strong>宫格布局</strong></p>
<p><code>feature</code> 首图占左侧两行，右侧由一张宽图和两张小图填充；<code>duo</code> 是等宽双列。容器内每行一张图片，格式为 <code>- 地址 | 说明 | alt</code>，说明和 alt 可省略；宫格图片不带外框和背景，说明文字居中排在图片下方。</p>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::pic{layout="feature"}
- /assets/images/example.webp | 示例图片一
- /assets/images/example.webp | 示例图片二
- /assets/images/example.webp | 示例图片三
- /assets/images/example.webp | 示例图片四
:::

:::pic{layout="duo"}
- /assets/images/example.webp | 示例图片一
- /assets/images/example.webp | 示例图片二
- /assets/images/example.webp | 示例图片三
- /assets/images/example.webp | 示例图片四
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::pic{layout="feature"}</p>
<ul>
<li>/assets/images/example.webp | 示例图片一</li>
<li>/assets/images/example.webp | 示例图片二</li>
<li>/assets/images/example.webp | 示例图片三</li>
<li>/assets/images/example.webp | 示例图片四
:::</li>
</ul>
<p>:::pic{layout="duo"}</p>
<ul>
<li>/assets/images/example.webp | 示例图片一</li>
<li>/assets/images/example.webp | 示例图片二</li>
<li>/assets/images/example.webp | 示例图片三</li>
<li>/assets/images/example.webp | 示例图片四
:::</li>
</ul>
<h3>视频嵌入 VideoEmbed</h3>
<p>嵌入白名单域名下的视频，目前支持 Bilibili 与 YouTube；其他地址回退为原链接。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>src</code></td>
<td>是</td>
<td>视频页面地址，仅支持 Bilibili 与 YouTube</td>
</tr>
<tr>
<td><code>title</code></td>
<td>否</td>
<td>iframe 标题，默认“嵌入视频”</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">::video-embed{src="https://www.bilibili.com/video/BV1GJ411x7h7"}
</code></pre>
<p><strong>演示</strong></p>
<p>::video-embed{src="<a href="https://www.bilibili.com/video/BV1GJ411x7h7%22%7D">https://www.bilibili.com/video/BV1GJ411x7h7"}</a></p>
<h3>表情包背景 EmojiTail</h3>
<p>表情堆叠在正文后方，悬停时整体提亮并轻微上浮。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>emojis</code></td>
<td>否</td>
<td>表情列表，逗号分隔或 JSON 数组，最多 6 个</td>
</tr>
<tr>
<td>内容</td>
<td>是</td>
<td>容器内的 Markdown</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">:::emoji-tail{emojis="📄,🦌,🙌"}
这是配了表情包背景装饰的正文，透明底无边框，hover 会让表情轻轻上浮。
:::
</code></pre>
<p><strong>演示</strong></p>
<p>:::emoji-tail{emojis="📄,🦌,🙌"}
这是配了表情包背景装饰的正文，透明底无边框，hover 会让表情轻轻上浮。
:::</p>
<h2>行内组件</h2>
<p>行内组件直接嵌在句子里，适合强调、标注和补充信息。</p>
<h3>徽章 Badge</h3>
<p>胶囊标签，可选外链。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>文字</td>
<td>是</td>
<td>徽章内容，写在 <code>:badge[...]</code> 中</td>
</tr>
<tr>
<td><code>link</code></td>
<td>否</td>
<td>外链地址</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">状态标签 :badge[Astro 7]、:badge[MDX]，带链接的 :badge[组件文档]{link="https://docs.astro.build/"}。
</code></pre>
<p><strong>演示</strong></p>
<p>状态标签 :badge[Astro 7]、:badge[MDX]，带链接的 :badge[组件文档]{link="<a href="https://docs.astro.build/%22%7D%E3%80%82">https://docs.astro.build/"}。</a></p>
<h3>键帽 Key</h3>
<p>键帽样式，适合快捷键说明。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>文字</td>
<td>是</td>
<td>键帽内容</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">在编辑器里按 :key[Ctrl] + :key[K] 打开命令面板。
</code></pre>
<p><strong>演示</strong></p>
<p>在编辑器里按 :key[Ctrl] + :key[K] 打开命令面板。</p>
<h3>术语提示 Tip</h3>
<p>术语下划线加悬停提示。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>文字</td>
<td>是</td>
<td>术语文字</td>
</tr>
<tr>
<td><code>tip</code></td>
<td>否</td>
<td>悬停提示；缺省时只保留普通文本</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">Astro 的岛屿架构会把交互组件单独 :tip[水合]{tip="浏览器接管静态 HTML 并绑定事件的过程"}，其余部分保持静态。
</code></pre>
<p><strong>演示</strong></p>
<p>Astro 的岛屿架构会把交互组件单独 :tip[水合]{tip="浏览器接管静态 HTML 并绑定事件的过程"}，其余部分保持静态。</p>
<h3>行内复制 Copy</h3>
<p>点击复制正文内容，适合命令和短代码。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>内容</td>
<td>是</td>
<td>要显示并复制的文本</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">构建命令：:copy[npm run build]。
</code></pre>
<p><strong>演示</strong></p>
<p>构建命令：:copy[npm run build]。</p>
<h3>代码语言标 CodeLang</h3>
<p>带语言标签的行内代码。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>lang</code></td>
<td>否</td>
<td>语言标签</td>
</tr>
<tr>
<td>内容</td>
<td>是</td>
<td>行内代码内容</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">构建命令：:code[npm run build]{lang="bash"}。
</code></pre>
<p><strong>演示</strong></p>
<p>构建命令：:code[npm run build]{lang="bash"}。</p>
<h3>人物名片 ProfileCard</h3>
<p>人物名片。正文里显示触发词，悬停或聚焦后展开姓名、身份和简介。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>id</code></td>
<td>是</td>
<td>全篇唯一标识</td>
</tr>
<tr>
<td><code>name</code></td>
<td>是</td>
<td>姓名</td>
</tr>
<tr>
<td><code>role</code></td>
<td>是</td>
<td>身份或职位</td>
</tr>
<tr>
<td><code>description</code></td>
<td>是</td>
<td>简介</td>
</tr>
<tr>
<td><code>trigger</code></td>
<td>否</td>
<td>触发词，默认使用 <code>name</code></td>
</tr>
<tr>
<td><code>avatar</code></td>
<td>否</td>
<td>头像图片，用 <code>$变量</code> 传入</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">有没有想过，这个博客背后其实是一个 :profile-card{id="owner" trigger="全干工程师" name="MmzMing" role="全干工程师" description="白天处理业务代码，空闲时折腾 AI、博客和各种小项目。" avatar="$ownerAvatar"} 在维护？
</code></pre>
<p><strong>演示</strong></p>
<p>有没有想过，这个博客背后其实是一个 :profile-card{id="owner" trigger="全干工程师" name="MmzMing" role="全干工程师" description="白天处理业务代码，空闲时折腾 AI、博客和各种小项目。" avatar="$ownerAvatar"} 在维护？</p>
<h3>模糊 Blur</h3>
<p>模糊文字，悬停或键盘聚焦后显现；支持行内与块级。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>内容</td>
<td>是</td>
<td>行内文字或容器内的 Markdown</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">遇到报错时，正确的顺序是 :blur[先看文档再改代码]。整段内容也可以隐藏：

:::blur
块级模糊会把整段内容一起遮住，适合答案、剧透或折叠前的提示。
:::
</code></pre>
<p><strong>演示</strong></p>
<p>遇到报错时，正确的顺序是 :blur[先看文档再改代码]。整段内容也可以隐藏：</p>
<p>:::blur
块级模糊会把整段内容一起遮住，适合答案、剧透或折叠前的提示。
:::</p>
<h3>艺术字 ArtText</h3>
<p>四种行内艺术字变体：<code>cre</code> 流动渐变、<code>story</code> 衬线批注、<code>zoom</code> 滚动放大、<code>repeat</code> 跟手回声（悬停拖影，点击扩散）。</p>
<p><strong>参数</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>variant</code></td>
<td>是</td>
<td><code>cre</code>、<code>story</code>、<code>zoom</code>、<code>repeat</code></td>
</tr>
<tr>
<td>内容</td>
<td>是</td>
<td>文字</td>
</tr>
</tbody></table>
<p><strong>语法</strong></p>
<pre><code class="language-mdx">四种效果：[!cre:流动渐变] [!story:故事感] [!zoom:放大] [!repeat:回声]。
</code></pre>
<p><strong>演示</strong></p>
<p>四种效果：[!cre:流动渐变] [!story:故事感] [!zoom:放大] [!repeat:回声]。</p>
<p>以上是本站 MDX 组件的完整说明。<code>::github</code>、callout、Mermaid 属于 Markdown 扩展，不在这批组件范围内。</p>
<h2>参考来源</h2>
<p>本文的组件设计参考了 RAGnote 的组件语法指南：</p>
<p>::link-card{link="<a href="https://ragnote.top/article/c636666dc6644140919010e78008e287">https://ragnote.top/article/c636666dc6644140919010e78008e287</a>" title="RAGnote 组件语法完全指南" desc="参考来源：RAGnote 富文本组件说明" icon="<a href="https://api.ragnote.top/files/bussiness/site_logo/4543f719e787499f8f3fb47782532368_1544604283489600.webp%22%7D">https://api.ragnote.top/files/bussiness/site_logo/4543f719e787499f8f3fb47782532368_1544604283489600.webp"}</a></p>
]]></content:encoded></item><item><title>Firefly 博客魔改总结：Astro 内容系统、Svelte 交互与部署</title><link>https://idea.lanerc.me/posts/others-blog-firefly-mod/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/others-blog-firefly-mod/</guid><description>记录 Firefly 博客主题的二次开发，涵盖 Astro 内容系统、Svelte 交互、首页动效、音乐播放器、标签图谱、留言板和 Cloudflare 集成。</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>[!NOTE] 提示
本文记录基于 Firefly 主题进行二次开发的实现取舍，覆盖首页动效、音乐播放器、标签图谱、留言板、Cloudflare 集成和部署流程。项目目标是保留 Astro 内容系统，同时将交互功能拆分为可独立维护的模块。</p>
</blockquote>
<h2>选型背景</h2>
<p>项目最初定位为个人主页，后续增加了文章、评论、搜索和统计能力，因此选择继续在 Astro 内容系统上演进。没有迁移到 Fuwari 的主要原因是现有文章、组件和部署配置已经围绕 Astro 组织，迁移成本高于继续维护。</p>
<p>截至本文发布时，项目本地构建时间约为 24 s；性能结果取决于图片数量、网络环境和部署平台，不能直接作为所有环境的基准。后续重构的主要成本来自交互组件、Swup 生命周期和外部服务配置之间的耦合。</p>
<p><strong>项目地址</strong></p>
<p><a href="https://github.com/MmzMing/my-blog">https://github.com/MmzMing/my-blog</a></p>
<p>项目属于二次开发，代码和配置以仓库当前版本为准。</p>
<h2>一、重点</h2>
<h3>1、首页</h3>
<ol>
<li>Hero 区域采用 Galgame 风格</li>
<li>站点地图一览</li>
<li>作品展示和博客主要方向</li>
</ol>
<table>
<thead>
<tr>
<th>技术栈</th>
<th>版本</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>GSAP</td>
<td><code>3.15.0</code></td>
<td>处理进入动画、碎片拼合和数字过渡</td>
</tr>
<tr>
<td>GSAP ScrollTrigger</td>
<td><code>3.15.0</code></td>
<td>根据滚动位置驱动首页 Hero 与展示层动画</td>
</tr>
<tr>
<td>SVG Filter</td>
<td>浏览器原生 API</td>
<td>提供首页标题的轻量熔化文字效果</td>
</tr>
<tr>
<td>Canvas 2D API</td>
<td>浏览器原生 API</td>
<td>绘制首页雨滴等轻量动态效果</td>
</tr>
<tr>
<td><code>@swup/astro</code></td>
<td><code>1.8.0</code></td>
<td>提供页面缓存、预加载和页面切换；切换后重新初始化动态组件</td>
</tr>
<tr>
<td>Tailwind CSS</td>
<td><code>4.2.4</code></td>
<td>提供通用布局、排版和响应式样式</td>
</tr>
</tbody></table>
<h3>2、音乐播放器</h3>
<p>保留全局音乐播放器：桌面悬浮组件与移动端 dock 共用同一播放引擎，支持 Meting API、本地曲目、播放列表与歌词，不包含独立的 3D 音乐页面。</p>
<h3>3、分类标签</h3>
<p>分类页现在只保留标签关系图谱：标签是节点，同一篇文章中同时出现的标签会连成边，边越粗表示共现次数越多。</p>
<table>
<thead>
<tr>
<th>技术栈</th>
<th>版本</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>Astro Content Collections</td>
<td><code>6.4.6</code></td>
<td>在构建时校验文章元数据并生成归档、分类和标签数据</td>
</tr>
<tr>
<td>Markdown Frontmatter</td>
<td>Markdown 标准能力</td>
<td>维护 <code>category</code>、<code>tags</code> 和发布日期</td>
</tr>
<tr>
<td>URLSearchParams</td>
<td>浏览器原生 API</td>
<td>读取标签和分类筛选参数</td>
</tr>
<tr>
<td>（核心）D3.js</td>
<td><code>7.9.0</code></td>
<td>使用 <code>d3-force</code> 计算力导向布局，使用 <code>d3-zoom</code> 处理缩放与拖拽</td>
</tr>
<tr>
<td>Canvas 2D API</td>
<td>浏览器原生 API</td>
<td>绘制节点、连线、标签和悬停高亮，避免大量 SVG 节点带来的渲染压力</td>
</tr>
<tr>
<td>ResizeObserver、IntersectionObserver、MutationObserver</td>
<td>浏览器原生 API</td>
<td>在容器尺寸、可见性和主题变化时分别调整图谱尺寸、暂停动画和刷新配色</td>
</tr>
</tbody></table>
<p>实现上，构建阶段会遍历所有文章的 <code>tags</code>：每个标签生成一个节点，并记录它关联的文章；同一篇文章内的任意两个标签生成一条共现边，边的权重就是它们共同出现的次数。客户端按连通关系给节点分组，再交给 D3 力导向模拟进行排布；Canvas 根据模拟结果逐帧绘制图谱。节点大小由文章数量决定，边的透明度和粗细由共现权重决定。用户可以缩放、拖拽节点、悬停查看关联文章，点击或按回车跳转到对应标签页；同时支持键盘选择、减少动态效果偏好和亮暗主题切换。</p>
<h3>4、留言</h3>
<p>转变UI为聊天室，并复用 Waline 的登录、审核、表情和访问量能力。原本做了个翻卡牌的，因为这个在KV上面天天给我报警告，后面就取消了。</p>
<table>
<thead>
<tr>
<th>技术栈</th>
<th>版本</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>Waline Client</td>
<td><code>3.15.2</code></td>
<td>初始化普通文章评论区与访问量统计</td>
</tr>
<tr>
<td>（核心）<code>@waline/api</code></td>
<td><code>1.1.2</code></td>
<td>调用留言读取、登录、发布、编辑和删除接口</td>
</tr>
<tr>
<td>Lucide Svelte</td>
<td><code>0.468.0</code></td>
<td>提供刷新、状态和操作图标</td>
</tr>
<tr>
<td>Fetch API、Web Storage API</td>
<td>浏览器原生 API</td>
<td>校验登录回调 Token，并保存草稿、资料和登录状态</td>
</tr>
</tbody></table>
<p>Waline 服务独立部署，博客只保存服务地址和客户端配置；项目 Worker 不保存评论内容，也不维护留言数据库或登录系统。</p>
<p>留言板调用的接口如下。读取接口每 <code>30 s</code> 轮询一次；页面不可见或浏览器离线时停止发起无效请求。</p>
<p>管理员 Token 仅保存到 <code>sessionStorage</code>；普通用户根据"记住登录"选项保存到 <code>sessionStorage</code> 或 <code>localStorage</code>。任何读取、发布、修改或删除请求返回鉴权错误时，页面都会清除本地 Token 并要求重新登录。</p>
<h4>4.1 接口列表</h4>
<p>以下为 <code>@waline/api</code> 中留言板实际调用的 CRUD 接口。</p>
<pre><code class="language-ts">// GET /api/comment?path=...&amp;pageSize=...&amp;page=...&amp;lang=...&amp;sortBy=...
// Headers: (token 存在时) Authorization: Bearer &lt;token&gt;
// 读取留言列表（分页，首次加载 + 轮询 + 加载历史）
getComment({
  serverURL: string,     // Waline 服务端地址
  lang: string,          // 语言
  path: string,          // 页面路径（留言板固定为 /guestbook/）
  page: number,          // 页码，从 1 开始
  pageSize: number,      // 每页条数
  sortBy: string,        // 排序方式（如 "insertedAt_desc"）
  token?: string,        // 登录令牌（可选，管理员可看到待审核留言）
  signal?: AbortSignal,  // 取消请求信号
})
// Response: { count: number, page: number, pageSize: number, totalPages: number, data: WalineRootComment[] }

// --------------------------------------------------------------------------

// POST /api/comment?lang=&lt;string&gt;
// Headers: Content-Type: application/json
//         (token 存在时) Authorization: Bearer &lt;token&gt;
// Body: { nick, mail?, link?, comment, ua, url, pid?, rid?, at? }
// 发布留言
addComment({
  serverURL: string,
  lang: string,
  token?: string,           // 登录令牌（登录用户可选，匿名时不需要）
  comment: {                // WalineCommentData
    nick: string,           // 昵称
    mail?: string,          // 邮箱
    link?: string,          // 网站地址
    comment: string,        // 留言内容（含回复标记 HTML 注释）
    ua: string,             // User Agent
    url: string,            // 页面路径
    pid?: number,           // 父评论 ID（回复时）
    rid?: number,           // 根评论 ID（回复时）
    at?: string,            // @用户 ID（回复时）
  },
})
// Response: { errno: number, errmsg?: string, data?: WalineComment }

// --------------------------------------------------------------------------

// PUT /api/comment/&lt;objectId&gt;?lang=&lt;string&gt;
// Headers: Content-Type: application/json
//          Authorization: Bearer &lt;token&gt;
// Body: { comment?, status?, sticky?, like? }
// 编辑留言（仅本人或管理员可编辑）
updateComment({
  serverURL: string,
  lang: string,
  token: string,            // 登录令牌（必需）
  objectId: number,         // 留言 objectId
  comment?: {               // UpdateWalineCommentData
    comment?: string,       // 修改后的内容
    status?: "approved" | "waiting" | "spam",  // 审核状态（管理员）
    sticky?: 0 | 1,         // 置顶状态（管理员）
    like?: boolean,         // 点赞/取消点赞
  },
})
// Response: { errno: number, errmsg?: string, data: WalineComment }

// --------------------------------------------------------------------------

// DELETE /api/comment/&lt;objectId&gt;?lang=&lt;string&gt;
// Headers: Authorization: Bearer &lt;token&gt;
// 删除留言（仅本人或管理员可删除）
deleteComment({
  serverURL: string,
  lang: string,
  token: string,            // 登录令牌（必需）
  objectId: number,         // 留言 objectId
})
// Response: { errno: number, errmsg: string, data: "" }

// --------------------------------------------------------------------------

// GET /api/token?lang=&lt;string&gt;
// Headers: Authorization: Bearer &lt;token&gt;
// 登录回调 Token 校验（Waline OAuth 重定向回博客后验证身份）
fetch(`${serverURL}/api/token?lang=${lang}`, {
  headers: { Authorization: `Bearer ${token}` },
})
// Response: { errno: number, errmsg?: string, data?: UserInfo }
</code></pre>
<h4>4.2 登录流程</h4>
<pre><code class="language-mermaid">sequenceDiagram
    participant User as 用户
    participant Page as 博客页面
    participant Waline as Waline 服务端
    participant Window as 浏览器窗口

    Note over User, Page: 桌面端：弹窗 + postMessage
    User-&gt;&gt;Page: 点击"登录"
    Page-&gt;&gt;Waline: 打开登录弹窗 (window.open)
    Waline-&gt;&gt;Waline: 用户完成 OAuth 认证
    Waline--&gt;&gt;Window: postMessage ({ type: "userInfo", data: UserInfo })
    Page-&gt;&gt;Page: 验证 UserInfo 合法性

    alt 验证成功
        Page-&gt;&gt;Page: 进入存储策略
    else 验证失败
        Page-&gt;&gt;Page: 清除 Token，提示重新登录
    end

    Note over User, Page: 移动端：跳转 + token 回传
    User-&gt;&gt;Page: 点击"登录"
    Page-&gt;&gt;Waline: location.href 跳转到登录页
    Waline-&gt;&gt;Waline: 用户完成 OAuth 认证
    Waline--&gt;&gt;Page: 302 重定向回博客 (?token=...)
    Page-&gt;&gt;Waline: GET /api/token (Authorization: Bearer &lt;token&gt;)
    alt 验证成功
        Waline--&gt;&gt;Page: 返回用户信息
        Page-&gt;&gt;Page: 进入存储策略
    else 验证失败
        Waline--&gt;&gt;Page: 返回错误
        Page-&gt;&gt;Page: 清除 Token，提示重新登录
    end

    Note over Page: 存储策略
    alt 管理员
        Page-&gt;&gt;Page: 存入 sessionStorage
    else 普通用户 + 勾选"记住登录"
        Page-&gt;&gt;Page: 存入 localStorage
    else 普通用户 + 未勾选"记住登录"
        Page-&gt;&gt;Page: 存入 sessionStorage
    end

    Page-&gt;&gt;Page: 刷新留言列表
</code></pre>
<h3>5、关于</h3>
<p>关于页内容使用 MDX 编写，正文里直接内嵌 Astro 组件（资料卡、技术栈卡片、时间线、社交链接和聊天气泡），排版交给框架的 Markdown 渲染管线，无需手动处理换行。页面底部附带一张更新日志图谱：构建时解析 <code>log.md</code> 的变更记录，生成按类型着色的日志卡片，并用 SVG 连线标注条目之间的关联页面。</p>
<table>
<thead>
<tr>
<th>技术栈</th>
<th>版本</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>MDX</td>
<td>Markdown 标准能力 + 组件语法</td>
<td>维护个人资料文本并内嵌交互组件，内容更新不需要修改页面逻辑</td>
</tr>
<tr>
<td>Astro 组件</td>
<td><code>6.4.6</code></td>
<td>资料卡、技术栈、时间线、社交链接等区块均为 <code>.astro</code> 组件，构建时静态渲染</td>
</tr>
<tr>
<td>SVG</td>
<td>浏览器标准</td>
<td>绘制更新日志图谱中条目之间的关联连线与箭头</td>
</tr>
<tr>
<td>Pointer Events</td>
<td>浏览器原生 API</td>
<td>处理日志卡片的悬停高亮与展开交互</td>
</tr>
<tr>
<td>Tailwind CSS</td>
<td><code>4.2.4</code></td>
<td>提供排版和响应式样式</td>
</tr>
<tr>
<td>TypeScript</td>
<td><code>5.9.2</code></td>
<td>约束日志解析工具和组件 Props 的类型</td>
</tr>
</tbody></table>
<h3>6、日历</h3>
<p>日历以全局小组件形式提供，聚合文章发布日期、法定节假日、内置节日和生日/纪念日，在固定的 <code>6 × 7</code> 月视图中展示公历和农历信息，并提供近期事件与当天详情。</p>
<table>
<thead>
<tr>
<th>技术栈</th>
<th>版本</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td><code>lunar-typescript</code></td>
<td><code>1.8.6</code></td>
<td>将公历与农历日期互转，生成农历日期和农历生日、节日事件</td>
</tr>
<tr>
<td>Fetch API</td>
<td>浏览器原生 API</td>
<td>日历小组件在浏览器端获取文章元数据和节假日静态 JSON 数据</td>
</tr>
<tr>
<td>CSS Grid</td>
<td>浏览器标准</td>
<td>使用 <code>6 × 7</code> 网格稳定渲染每月 42 个日期单元格</td>
</tr>
</tbody></table>
<h4>6.1 接口列表</h4>
<p>以下两个内部 API 在构建时预渲染为静态 JSON；日历小组件在浏览器端运行时 fetch 这两份数据。其中 <code>/api/holidays.json</code> 在构建时会调用第三方节假日 API 获取数据。</p>
<pre><code class="language-ts">// --------------------------------------------------------------------------

// GET /api/allPostMeta.json
// Headers: 无
// 调用方：日历小组件客户端脚本（浏览器运行时 fetch）
// 构建时由 Astro Content Collections 生成并预渲染为静态 JSON，包含所有文章的元数据
fetch("/api/allPostMeta.json")
// Response: Array&lt;{ id: string, title: string, published: number, category?: string, password?: boolean }&gt;

// --------------------------------------------------------------------------

// GET /api/holidays.json
// Headers: 无
// 调用方：日历小组件客户端脚本（浏览器运行时 fetch）
// 构建时内部调用第三方 API 获取节假日数据后合并内置节日，预渲染为静态 JSON
fetch("/api/holidays.json")
// Response: Array&lt;{ date: string, name: string, isOfficial?: boolean, isWorkday?: boolean, icon?: string, source: "api" | "builtin", rest?: number }&gt;

// --------------------------------------------------------------------------

// GET https://timor.tech/api/holiday/year/&lt;year&gt;
// Headers: Accept: application/json
// 调用方：/api/holidays.json 内部（构建时由 holidayApi 配置驱动）
// 获取中国法定节假日、调休补班日
// 配置路径：src/config/calendarConfig.ts → holidayApi.url
fetch("https://timor.tech/api/holiday/year/2026")
// Response: { code: number, holiday: Record&lt;string, { holiday: boolean, name: string, rest?: number }&gt; }
</code></pre>
<p>两个内部 API 只在 <code>astro build</code> 时执行并输出为静态 JSON，生产环境由静态资源直接返回，浏览器端 fetch 到的是静态文件。文章或节假日更新后需要重新构建才能反映到日历上。</p>
<h3>7、归档</h3>
<p>归档页按年、月和文章组织时间线，支持分类和标签筛选，并显示年度文章进度。文章列表与统计在构建时根据文章元数据生成；由于静态构建无法读取查询参数，分类和标签筛选在客户端执行，不依赖额外的动态接口。</p>
<table>
<thead>
<tr>
<th>技术栈</th>
<th>版本</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>Intl.DateTimeFormat</td>
<td>浏览器原生 API</td>
<td>构建时按站点时区归组年月，用于年度/月度文章统计</td>
</tr>
<tr>
<td>URLSearchParams</td>
<td>浏览器原生 API</td>
<td>客户端读取 <code>?tag</code> / <code>?category</code> / <code>?uncategorized</code> 筛选参数</td>
</tr>
<tr>
<td>Svelte</td>
<td><code>5.55.5</code></td>
<td>统计卡片组件，配合 <code>requestAnimationFrame</code> 做数字过渡动画（尊重减少动态效果偏好）</td>
</tr>
</tbody></table>
<h3>8、其他</h3>
<ol>
<li>取消了侧边栏，首页和文章页将主要导航集中到顶部与移动端 Dock。</li>
<li>修改了整体 UI 风格，保留亮色与暗色两种主题，不再维护背景图和多套背景配置。</li>
<li>添加了日历功能，按文章发布日期展示内容；节假日数据在构建时从第三方 API 拉取并合并内置节日，运行时只读静态 JSON。</li>
<li>删除了追番功能，避免相关数据请求和资源处理进入构建流程。</li>
<li>使用 Pagefind <code>1.5.2</code> 构建本地全文索引，并在构建期生成 LLM Wiki 的 JSON / Markdown 机器入口。</li>
<li>站点完全静态生成，可直接部署到 Cloudflare Pages、Vercel、Netlify 或其他静态托管平台；评论和统计使用各自的外部服务。</li>
</ol>
<h2>二、用到的AI模型</h2>
<ul>
<li>MIMO V2.5/PRO（送的百亿补贴）</li>
<li>claude opus 4.64.74.8fable 5</li>
<li>GPT 5.5/5.6</li>
<li>antigravity的gemini 3.1/3.5</li>
<li>TRAE上的 GLM/豆包/KIMI/QWEN/DeepSeek（都是拿来测试性能好在工作上确定是否实用）</li>
</ul>
<p>本次试用成本约为 30 元。不同平台的模型、上下文管理和工具链存在差异，不能仅凭一次试用归因于模型或平台。实际接入时应使用小任务验证代码质量，并通过测试和审查控制回归风险。</p>
<h2>三、优点与UI复制</h2>
<p>纯静态，部署快，维护简单，成本低（只需要域名的费用）。</p>
<p>外部 UI 参考可以加速原型制作，但接入前需要统一交互规范、无障碍要求和许可证边界，避免把不兼容的组件直接拼接到站点中。</p>
<p>::github{repo="MmzMing/my-blog"}</p>
]]></content:encoded></item><item><title>.pages.dev 飞快，自定义域名却慢得要死</title><link>https://idea.lanerc.me/posts/alexander-console/alexander-console/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/alexander-console/alexander-console/</guid><description>为了让写博客这件事变得赏心悦目，我重构了整套系统：自研控制台、评论迁移，与一个未解决的难题</description><pubDate>Sat, 24 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h2>引子</h2>
<p>为了让写博客这件事变得赏心悦目，我重构了整套博客系统：前端上了 Cloudflare Pages，后台让 AI 帮我写了一套，评论也迁了新家（<mark>小猪手没迁好，小鸡限速，好难好难呜呜</mark>），好在重要评论都还在，就是格式乱了。万事俱备之后，灵异事件来了——<strong>我在电脑上打开自己的博客，慢得要死；手机打开，秒开。</strong></p>
<h2>装备升级：让写作成为一种享受</h2>
<p>后台这事我调研得很认真：Qexo、Hexo CMS 看着不够漂亮，Kirameku 的毛玻璃、Halo 的清爽、ColaMD 的主题各有各的好，但没有一个完全对胃口。最后我的选择是——<strong>一个都不用，让 AI 帮我自己写一套</strong>。</p>
<p>成果就是 <a href="https://lanerc.me/admin">Alexander Console</a>。思路是：不要数据库，不要后端服务器，<strong>GitHub 仓库就是后台</strong>。GitHub OAuth 登录，所有内容保存即一次 commit，仓库在，数据就在。仔细检查调试之后，发现它管的东西比我预想的多：</p>
<ul>
<li><strong>全站可管</strong>：文章、动态、相册（带加密相册和上下排序）、导航栏分组、首页 12 张卡片、书签、时间线、公告栏、碎碎念，连 Waline 评论审核都做成了内置页，躺床上拿手机就能审评论；</li>
<li><strong>写稿不丢</strong>：编辑器草稿自动保存，写一半杀后台回来接着写；再加一道基于文件版本的守卫，别处改过的新版本，永远不会被旧草稿覆盖；新建文件撞名自动改名顺延，删除前必须二次确认；</li>
<li><strong>图片自由</strong>：图床走 Cloudflare R2；四处背景（桌面/手机 × 登录/内页）都能攒多张自定义图，可固定、可进轮换、可单张删；</li>
<li><strong>颜值与仪式感</strong>：日夜双主题、毛玻璃细边框、波奇酱背景、CRT 开关机加虫洞切换动画，还能以 PWA 形态装到桌面和手机主屏，像个正经 App；</li>
<li><strong>彩蛋</strong>：它会记操作日志，月底自己弹一份小红书周报风的总结报告，告诉我这个月写了几篇、折腾了什么。</li>
</ul>
<p>话虽如此：写作的地方顺眼，人是真的更愿意打开它码字。而这一整套，是我提需求、AI 写代码、人机配合一点点攒出来的。</p>
<h2>基建优化：Waline 评论系统的零成本新家</h2>
<p>评论系统 Waline 最终落在 <strong>Vercel + MongoDB Atlas</strong> 免费层，零成本零运维。避坑点留三个，全是实锤：</p>
<ul>
<li>数据库连接参数（AI可查）必须<strong>拆开填</strong>：主机分片、端口数组、副本集逐项配，整串粘贴进去，部署会在你以为成功时起不来；</li>
<li>导入历史评论<strong>绝不能带管理员令牌</strong>，否则所有评论都会挂在博主本人名下；</li>
<li>社区有 Workers 移植版，但官方原版和 Workers 运行时不兼容，这条路我没走，看冷汐成功了<a href="https://lengxiqwq.com/posts/%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F-twikoo-%E5%A5%BD%E5%A4%9A-bug%E8%A2%AB%E8%BF%AB%E6%8D%A2%E6%88%90%E4%BA%86-waline/">评论系统 Twikoo 好多 bug！被迫换成了 Waline</a>。有兴趣可以去学习下！</li>
</ul>
<h2>系统全景：我的博客长什么样</h2>
<p>都已经到这个地步了，我觉得有必要先上全景。目前我的博客是一套「仓库即后台」的静态架构：</p>
<pre><code>lanerc.me（Cloudflare Pages · Astro 静态站）
├─ 内容：GitHub 仓库（文章、动态、相册、导航全是文件）
│    └─ Alexander Console → GitHub API 读写 → 保存即 commit → 自动重建
├─ 图片/视频：Cloudflare R2（img.lanerc.me）
├─ 评论：Waline（Vercel + MongoDB Atlas）
│    └─ zhz-ai 机器人：轮询新评论，自动回复
├─ 统计：Umami 自建，前端直连公开接口
└─ 构建：数据脚本五件套 → pnpm build → Pagefind 站内搜索
</code></pre>
<p>拆开看就三层：<strong>写作层</strong>是控制台和仓库，我只管写，保存就是提交；<strong>托管层</strong>是 Pages，代码一推全站自动重建上线；<strong>服务层</strong>是评论、图床、统计三个独立小服务，各自跑在最适合的免费额度上，坏一个不影响其他。</p>
<p>更详细的可以查看站点<a href="https://lanerc.me/changelog/">博客日志</a>，文章最后我也会说一下的。</p>
<h2>排错：为什么 CF Pages 自定义域名「慢得要死」？</h2>
<p>先摆现象：<code>.pages.dev</code> 默认域名飞快，绑定的自定义域名 <code>lanerc.me</code> 在电脑上巨慢，手机平板一切正常。注意前提：<strong>没开任何代理</strong>，电脑连的是校园网 Wi-Fi（SEU-WLAN）。</p>
<p><strong>嫌疑人一：豪华网卡阵容与跃点数。</strong> 打开网络连接一看，好家伙：Radmin VPN、VPN Client、深信服 aTrust 的虚拟网卡，加上正在用的 WLAN，四块网卡同台竞技。</p>
<p><img src="https://img.lanerc.me/posts/2026-10-24/mvml56f2-24e778f872771a63bb43c3e1e68f6481.webp" alt="图片" loading="lazy" /></p>
<p>PowerShell 一查，当场抓到异常：</p>
<pre><code class="language-powershell">Get-NetIPInterface | Sort-Object InterfaceMetric | Format-Table InterfaceAlias, InterfaceMetric, AddressFamily
</code></pre>
<p>结果：<code>VPN - VPN Client</code> 的 IPv4 跃点数是 <strong>1</strong>，正在上网的 WLAN 是 <strong>35</strong>。Windows 的规矩是跃点数越小优先级越高——系统会优先扑向那块没在干活的虚拟网卡，DNS 查询死等超时再回退，慢就慢在这儿。听起来严丝合缝，于是继续动手查查：</p>
<pre><code class="language-powershell">Set-NetIPInterface -InterfaceAlias "VPN - VPN Client" -InterfaceMetric 50
</code></pre>
<p><img src="https://img.lanerc.me/posts/2026-10-24/mvmlahlp-e59b24862f023065474283f4347be726.webp" alt="图片" loading="lazy" /></p>
<p><strong>然后，反转来了。</strong> 改成 50 之后，自定义域名没变快，连原本飞快的 <code>.pages.dev</code> 也跟着慢了。这说明那块虚拟网卡的低跃点数没准还在替系统扛着什么，或者这条链压根不是主因。没有对照证据，我不硬撑结论——<strong>把跃点数改回去了</strong>，恢复原状。</p>
<p><strong>嫌疑人二：校园网 DNS 与 IPv6。</strong> 清掉缓存再对比解析（示例）：</p>
<pre><code class="language-powershell">ipconfig /flushdns
nslookup lanerc.me
nslookup firefly-6sp.pages.dev
</code></pre>
<p><img src="https://img.lanerc.me/posts/2026-10-24/mvmlb6oj-dd987cb7e90302a299062c349a7370ce.webp" alt="图片" loading="lazy" /></p>
<p>实锤：校园网 DNS（172.19.2.2）给 <code>lanerc.me</code> <strong>先返回两个 IPv6 地址</strong>再给 IPv4，而校园网的 IPv6 路由质量一向一言难尽；查 <code>.pages.dev</code> 时 DNS 干脆<strong>先超时一次</strong>才给出结果。嫌疑很大，但关 IPv6、换公共 DNS 这些候选解法，我还没逐一验证出唯一真凶，所以这一节的结论是：<strong>未破案</strong>。</p>
<h2>总结与启发</h2>
<p>这篇没有漂亮的破案结尾，只有一份完整的排查记录和一次老实的回滚。我的体会是：排错最忌讳把「改过参数」当成「破了案」——假设要验证，改坏了就回滚，现象记录清楚，下次接着查。折腾的乐趣有一半在坑里，愿你踩坑时手边有日志，改参数前记得留好退路。</p>
<p><em>顺带交代一下：博客本体是<a href="https://github.com/withastro/astro">Astro</a>静态站，跑在 Cloudflare Pages 上；内容全部存在<a href="https://github.com/Misty-ui-source/Firefly">GitHub 仓库</a>里，我用自研的 <a href="https://lanerc.me/admin">Alexander Console</a> 经 GitHub API 读写，保存即提交、提交即自动重建；图片和视频走 Cloudflare R2（img.lanerc.me），评论是 Vercel + MongoDB Atlas 上的 Waline（另有 AI 机器人自动回复），统计用自建的 Umami。整套架构只有一台服务器是为博客本体付费的（<mark>Azure的免费学生机</mark>）。</em></p>
]]></content:encoded></item><item><title>和AI“谈了”三天“恋爱”：来说说这三天重建个人网站的感受</title><link>https://idea.lanerc.me/posts/blog-rebuild-reflections/blog-rebuild-reflections/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/blog-rebuild-reflections/blog-rebuild-reflections/</guid><description>今天基本上bug也修改完了，这三天的重构过程真的是让我头昏脑胀啊</description><pubDate>Sun, 18 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>zhz的折腾过程</h1>
<h2>想法的萌生</h2>
<p>首先来说一下为什么会想着重新搭建一个博客，是因为原本的不好吗？当然有一定的原因，但是并不是全部，这里来讲一下我的旧站的维护吧。</p>
<p>旧站采取Fuwari + Cloudflare Pages自托管的模式，是现在的一个性价比很高的搭建方式，<strong>Fuwari 负责提供极致的视觉与性能体验，Cloudflare Pages 负责提供稳定、免费且高速的全球分发</strong>。但是我为什么要放弃呢，其实我想最主要的原因是，目前我的推送流程的阻碍，现在推送的主要流程是：
<strong>本地文件更新</strong> —<strong>git push</strong> — <strong>github push推送</strong> — <strong>Cloudflare pages自动推送</strong> —<strong>部署完成</strong>
看似很好很轻松的过程，但是其中隐含的缺点也有很多：</p>
<ol>
<li><p><strong>写作被工具链绑架</strong>：改一个错别字、换一张图，也要走 commit/push/build，灵感场景下很重。</p>
</li>
<li><p><strong>反馈链路过长</strong>：push 成功不等于部署成功，还要等构建、看日志、处理失败；故障点分散很难查找。</p>
</li>
<li><p><strong>移动端和多设备不友好</strong>：手机上很难完成完整 Git 流程，临时修改只能等电脑。</p>
</li>
<li><p><strong>频繁小提交会消耗构建额度</strong>：Cloudflare Pages 免费版 Git 集成有每月构建次数限制，频繁 push 会浪费额度。
但更准确地说：我打算放弃的并不是<strong>Fuwari + Cloudflare Pages</strong>，而是“<strong>每次更新都必须自动触发 Git 构建</strong>”的方式。</p>
</li>
</ol>
<p><strong>所以我改为了VPS加AI自托管的模式：</strong></p>
<p>在旧方案里，发布一篇文章本质上是一次<strong>软件部署</strong>：修改文件、commit、push、等待构建、处理构建失败。我的写作意愿被这条链路的摩擦不断消耗。而更新频率也确实如所看到的一样。</p>
<p>在 VPS + AI 托管模式下，发布变成了直接的内容操作。新方案（VPS + AI）通过一个具备操作能力的 AI 代理，直接接管了<strong>发布与运营</strong>这个最消耗精力的环节，完全绕过了 Git 和自动构建。</p>
<p>但是这并不足以让我放弃Fuwari ，这个基于 Astro 框架的静态博客模板，在<strong>设计感和开箱即用的优秀体验</strong>上有着极大的吸引力的一个静态博客。而原因在于我最近经常混迹于各种论坛，也和许多优秀的人交流中不定时的读一读他们的项目经历，在这其中我就发现了一位大佬，他的基于<strong>Firefly</strong>魔改版本的个人网站深深吸引我了 —— [<a href="https://www.9ll.uk/">折腾进行时 - 9LL.UK</a><br />所以我也萌生了魔改的想法，附上HY站长的几张siteshot：
<img src="https://idea.lanerc.me/_astro/1.BC8PlvIf_1YMUHp.webp" alt="HY 站长站点界面截图之一" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/2.dfutoqPT_1g1Wxq.webp" alt="HY 站长站点界面截图之二" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/3.CjyGx6dx_Z288F3a.webp" alt="HY 站长站点界面截图之三" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/4.DbnO3kXm_Z17jav0.webp" alt="HY 站长站点界面截图之四" loading="lazy" /></p>
<p>经过调查我发现：</p>
<p>Firefly 直接把评论、说说/动态做成了内置的功能。根据一些迁移者的对比，它<strong>内置了评论系统、说说/动态、赞助页面和实验室/工具</strong>，大部分定制都可以通过配置文件完成，不再需要魔改核心代码。对我来说，这意味着 AI 可以操作和发布的“内容类型”变多了——它不仅能写文章，还能直接处理动态、管理内置评论，而不需要我先花时间搭建这些基础设施。这里要致敬一下<strong>大佬</strong>——[[<a href="https://blog.cuteleaf.cn/">夏夜流萤 - 飞萤之火自无梦的长夜亮起，绽放在终竟的明天。</a>]]</p>
<h2>将调研成果实际落地</h2>
<p>一个很直接的证据是，社区里已经出现了专门适配 Firefly 的 <strong>AI Agent Skill</strong>（<code>firefly-post-writing</code>）。这个技能让 AI 能够按照 Firefly 的内容集合（Content Collections）规范，自动将 Markdown 内容放入 <code>src/content/posts/</code> 下的正确位置，并生成符合其 schema 的 frontmatter（标题、日期、标签、分类等）。这意味着你的 AI 托管不需要自己去摸索 Firefly 的文件结构，可以直接调用现成的技能来完成发布，降低了 AI 操作出错的概率。链接：<a href="https://skillsmp.com/zh/creators/godblf/godblf.github.io/agents-skills-firefly-post-writing">firefly-post-writing Agent Skill | GodBlf/godblf.github.io</a></p>
<p>那有了这些基础，选哪个模型呢？我想起来前几天白嫖了 170亿 token 的 <strong>Muse</strong>，Meta 旗下刚出的类似沙盒功能的 AI 助手，平时只帮助我处理一些 Outlook 邮件。评估一下折腾项目的评分，这次为何不<strong>挑战</strong>一下自己呢？</p>
<p>（PS:现在想想有点胡闹了）</p>
<p>然而，这次博客重构，我决定拿它当主力，看看一个 AI Agent 到底能不能独立扛下一个完整的建站项目。</p>
<p>我要的不是一个能聊天的模型，而是一个能动手干活的助手：读写文件、跑构建脚本、调 GitHub API、看日志、修 bug。Muse 的定位正好包含这些吧？是这个吗？。</p>
<p>现在给出结论：<strong>能，但是真的很累。</strong></p>
<h2>实战：从 Fuwari 到 Firefly 的迁移</h2>
<h3>选型</h3>
<p>Firefly 是 CuteLeaf 基于Astro写的博客主题，Fuwari 的继任者。选它有三个原因：</p>
<ol>
<li><strong>配置集中化</strong>：所有定制项都在 <code>src/config/</code> 下，十几个 TypeScript 配置文件，改配置就能换脸，不用动核心代码</li>
<li><strong>功能内置</strong>：评论、动态、赞助页、实验室都是内置的，Fuwari 时代要自己搭的，Firefly 直接给了</li>
<li><strong>AI 友好</strong>：目录结构清晰，<code>src/content/posts/</code> 放文章，<code>src/content/dynamic/</code> 放动态，AI 读写不容易出错</li>
</ol>
<p>HY 站长（9ll.uk）的魔改版是我的视觉目标：卡片式布局、3px 纯黑边框、青绿色主题（hue 174）。我没直接抄代码，只定了视觉规范，让 Muse 按这个调。</p>
<h3>迁移过程</h3>
<p><strong>第一步：内容迁移</strong></p>
<p>旧站 11 篇文章 + About 页，直接拷到 <code>src/content/posts/</code>。Fuwari 和 Firefly 的 frontmatter 大体兼容，<code>title</code>、<code>published</code>、<code>tags</code>、<code>category</code> 都能直接用。有问题的手动修——比如图片路径，Fuwari 用 <code>./1.jpg</code>，Firefly 推荐用 <code>./images/</code> 子目录，但实测发现 Fuwari 的构建认不出子目录（这个后面单独说）。</p>
<p><strong>第二步：视觉定制</strong></p>
<p>按 HY 风格改了这几处：</p>
<ul>
<li>全站 hue 174 青绿，卡片 3px 纯黑边框</li>
<li>首页可拖拽贴纸（4 张 AI 生成的图，<code>src/config/stickerConfig.ts</code>）</li>
<li>Live2D：雪初音（主）+ 金发 z16（右），桌面端显示</li>
<li>轮播图按横竖版分离：横版放桌面，竖版放手机</li>
</ul>
<h3>魔改过程：Firefly 的配置分层</h3>
<p>Firefly 相比 Fuwari 最大的变化，是把魔改分成了两层。理解这两层，就理解了怎么在不碰核心代码的情况下，把站点改成 HY 那味。</p>
<p><strong>第一层：配置驱动（零代码改动）</strong></p>
<p>所有定制项集中在 <code>src/config/</code> 下，十几个独立的 TypeScript 文件：</p>
<ul>
<li><code>siteConfig.ts</code>：站点标题、描述、URL。我的站名 "Alexander"，横幅 "Lovely Life"</li>
<li><code>navBarConfig.ts</code>：顶部导航。我在"我的"下拉里加了 Steam（番组计划下面）、书签分组</li>
<li><code>profileConfig.ts</code>：侧边栏个人卡。名字 "zhz"，bio "Hello, I'm zhz."</li>
<li><code>commentConfig.ts</code>：评论系统。切到 Waline，<code>waline.lanerc.me</code></li>
<li><code>backgroundWallpaper.ts</code>：背景壁纸模式</li>
<li><code>stickerConfig.ts</code>：首页可拖拽贴纸（我自研的，4 张 AI 图）</li>
</ul>
<p>这一层覆盖了 80% 的视觉差异。HY 站的卡片布局、配色，基本都是改配置就能实现。AI 改这一层最安全——改错了也只是显示问题，不会构建失败。</p>
<p><strong>第二层：组件与样式微调</strong></p>
<p>配置搞不定的，才进 <code>src/components/</code> 和样式层：</p>
<ul>
<li>统计页（<code>src/pages/analytics.astro</code>）：HY 式卡片，加了 GitHub 推送热力图、数据卡。卡片视觉冻结后只改数据层，整体的Umami数据拉取还是不尽人意。</li>
<li>Steam 页（<code>src/pages/steam.astro</code>）：照着 HY 的 steam 页抄的布局（玩家卡 + 统计卡 + 游戏网格），配色换成咱的青绿 <code>oklch(0.65 0.15 174)</code></li>
<li>全站 hue 174、卡片 3px 纯黑边框：在全局样式里定的</li>
</ul>
<p>这一层我让 Muse 打下手，但主要板权在我。AI 生成 diff，我 review 后再合——它今天就因为多手改了不该改的，被我骂了四次。（<strong>一共让我生气了不下16次了吧，应该是。。没数到，反正最后的包体来到了117版</strong>）</p>
<p><strong>两层之间的边界</strong></p>
<p>内容层（<code>src/content/</code>）AI 全权负责写，配置层（<code>src/config/</code>）AI 改完我要看一眼，组件层（<code>src/components/</code>、<code>src/pages/</code>）AI 只给建议不动手。这个边界是血泪教训：v108 那次 AI 自作主张换了头像文件，差点把友链的头像地址搞崩。</p>
<p><strong>第三步：评论系统</strong></p>
<p>从 Artalk 换回 Waline（Artalk 2.10.0 停服了）。Waline 跑在 HK 机 Docker 里，<code>127.0.0.1:8360</code>，SQLite 存数据。配了个 AI 自动回复 <code>zhz-ai</code>——访客留言后，跑在 ID 机上的 Python 服务（智谱 glm-4-flash）60 秒轮询一次，自动回评论。昵称显示 <code>zhz-ai</code> + 🤖 勋章，回复内容自称"zhz"。</p>
<p><strong>第四步：统计系统</strong></p>
<p>Umami 自托管，跑在 HK 机 Docker（<code>127.0.0.1:8362</code>）。前端不直连，走了三层：</p>
<ol>
<li>构建时 <code>scripts/fetch-umami-stats.py</code> 拉一份静态数据兜底</li>
<li>HK 机 cron 每 5 分钟生成 <code>/api/stats.json</code></li>
<li>前端优先读 <code>/api/stats.json</code>，8 秒超时后降级读构建时数据</li>
</ol>
<p>统计页还加了 GitHub 推送热力图（构建时 <code>scripts/fetch-github-activity.py</code> 拉 52 周 commit 数据）。</p>
<p><em>整体上效果待定吧，这个也是以后修改的一个方向</em></p>
<h2>踩坑记录</h2>
<p><strong>1：Fuwari 图片子目录</strong></p>
<p>新文章的图片放在 <code>images/</code> 子目录，<code>./images/img22.png</code> 这种引用，Fuwari 构建直接报 <code>ImageNotFound</code>。旧站 11 篇文章都是图片放根目录，Fuwari 的 Astro 配置认不出子目录。总结了一下：<strong>同步到旧站的文章，图片必须打平</strong>，<code>./images/X</code> 改成 <code>./X</code>。</p>
<p><strong>2：Cloudflare 构建队列</strong></p>
<p>用 GitHub API 一篇一篇推文章，每篇一个 commit，Cloudflare Pages 疯狂触发构建，队列堵死，大部分显示 "No deployment available"。后来给AI讲<strong>批量操作要打包</strong>，用 Git Data API 把一篇文章的所有文件打成一个 commit。</p>
<p><strong>3：Waline 容器 OOM</strong></p>
<p>HK 机只有 887MB 内存，Waline 的 better-sqlite3 原生模块直接崩了，nginx 报 502。容器自动重启后恢复，但内存还是紧张。把不用的 whatsapp-proxy 停了，也只释放了 6MB。<strong>2C/887MB 跑 Waline + Umami + Postgres 就是勉强</strong>。（后悔没用其他机子了）</p>
<p><strong>大佬们如果以后光临本站发现评论加载不出来那多半是挂了，访问的人数一多，刷新一多的话香港机子跑的就很勉强了</strong></p>
<p><strong>坑 4：Umami 分享 token 调不到 realtime</strong></p>
<p>统计页的"在线人数"用分享 token 调 <code>/api/realtime/</code> 返回 401。排查发现是前端 localStorage 缓存了过期的 token，换了缓存 key（v2）强制刷新后解决。</p>
<p><strong>这个部分是AI做的最差的部分，目前解决起来确实很困难，但是访客视觉上不会收到太大影响。</strong></p>
<h3>AI 托管的工作流</h3>
<p>现在的工作流是：</p>
<p>我在聊天里下指令/提交推文<br />→ Muse 写 Markdown 到 src/content/posts/<br />→ Muse 跑 ./build.sh（8 步：清缓存 → 拉 Umami → 拉 Steam → 拉 GitHub → 建索引 → AI 摘要 → Astro 构建 → Pagefind）（<strong>够复杂</strong>！！）<br />→ 打包 dist（148MB，split 成 80M 两卷）  （<strong>免费版最大了吗</strong>？）
→ 我手动在 HK 机部署（curl 下载 → 解压 → chmod → purge CF 缓存）</p>
<p>其实这个流程也很糟心，主要是<strong>Muse应对魔改的需求还是太勉强了</strong>，其实很大部分是因为VPS的问题，<strong>跑不起那些Muse改的再好也是落地实现不了</strong>。</p>
<p>AI 负责写和构建，我负责部署和构思采用。配置层（<code>src/config/</code>）的改动我人工确认，内容层（<code>src/content/</code>）AI 直接写。这个边界守住的话，AI 再抽风也只影响文章，不会把站点布局搞崩。（当然他天生不是这么智能，已经把站点搞崩了3次了吧，<strong>印象中</strong>）<code>firefly-post-writing</code> 的护栏本身也体现了这个倾向：它要求 AI 不去改动非内容配置文件，不删除必需的 frontmatter，保持日期格式稳定。</p>
<h1>致谢</h1>
<p> <a href="https://9ll.uk/">9LL.UK</a> 
 <a href="https://blog.cuteleaf.cn/">夏夜流萤 - 飞萤之火自无梦的长夜亮起，绽放在终竟的明天。</a></p>
<h1>附录</h1>
<p>这几天烧了这么多token，Muse的量还是大啊。用不完<strong>根本用不完</strong>！
<img src="https://idea.lanerc.me/_astro/5.Dla3cmGn_BJhi.webp" alt="AI 对话平台的 token 用量统计截图" loading="lazy" /></p>
]]></content:encoded></item><item><title>给博客装了个 AI 评论员：zhz-ai 的折腾全记录</title><link>https://idea.lanerc.me/posts/zhz-ai-launch/zhz-ai-launch/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/zhz-ai-launch/zhz-ai-launch/</guid><description>博客评论区接入 AI 自动回复，从改名到修三个离谱 bug，再到评论区自动刷新，一天的折腾全记录。</description><pubDate>Sun, 18 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>给博客装了个 AI 评论员：zhz-ai 的折腾全记录</h1>
<p>博客评论区一直是我心里的一个结——访客留言了，我不能 24 小时蹲着回。于是有了这个想法：搞个 AI 自动回评论，简单的它搞定，难的再叫我。</p>
<p>说干就干，一天时间，从 0 到 1，外加三个离谱 bug。记录一下。</p>
<h2>起名：从"暮色"到 zhz-ai</h2>
<p>一开始叫"Muse"，太直白了。后改"暮色"——汉字版的 muse，有点味道。但最后还是定了 <strong>zhz-ai</strong>，简单直接，一看就知道是站长的 AI 分身。</p>
<p>头像用 QQ 邮箱头像（<a href="mailto:2099621514@qq.com">2099621514@qq.com</a>），Waline 认邮箱不认 avatar 字段，踩了个小坑。</p>
<h2>架构：Flask + 智谱 + 轮询兜底</h2>
<p>服务跑在 ID 那台机子上（HK 机子内存太小了，887MB 跑不动），Flask + gunicorn 单 worker，60 秒轮询一次 Waline 的 recent API。</p>
<p>为啥不用 webhook？Waline 的 WEBHOOK 是服务端环境变量，配了，但真实评论就是不触发。原因没查清——先跑起来，轮询兜底。</p>
<p>模型试了一圈：glm-4.7-flash 过载，glm-4.5-flash 返回空，只有 <strong>glm-4-flash</strong> 稳定。就它了。</p>
<p>提示词写了双风格：随笔类短平快玩梗，技术类大胆展开给建议。之前测试时回得太水（"发给我看看"这种空话），被我骂了一顿重写了——现在技术类会针对具体技术点给建议。</p>
<h2>三个离谱的 bug</h2>
<h3>Bug 1：轮询线程从没启动过</h3>
<p>最离谱的一个。部署了两次，AI 就是不回评论。查了半天，发现轮询启动代码写在 <code>if __name__ == "__main__":</code> 里——gunicorn 导入模块根本不执行这个块！</p>
<p>改成模块加载时直接启动线程。两分钟的事，找了一小时。🤡</p>
<h3>Bug 2：重复回复</h3>
<p>修好轮询后，AI 开始回了——一次回两条，一模一样。</p>
<p>原因：webhook 处理完没把 objectId 记到已处理集合里，轮询又扫到同一条，又回一遍。修法：在生成回复<strong>之前</strong>先标记已处理，防竞态。</p>
<h3>Bug 3：改了 systemd 没生效</h3>
<p>想把 gunicorn 从双 worker 改成单 worker（省内存），改完重启，没变化。查了半天——改错文件了！</p>
<p>systemd 实际用的是 <code>/etc/systemd/system/</code> 下的 service 文件，我改的是 <code>/opt/</code> 下的副本。Linux 老坑了，记录一下。</p>
<h2>评论区自动刷新</h2>
<p>访客发完评论，AI 回了，但页面不刷新，得按 F5 才看得到。这体验不行。</p>
<p>调研了 Waline 官方源码：<code>init()</code> 返回的 <code>update()</code> 只在 path 变化时重拉，同页调用无效。唯一靠谱的办法是 <code>destroy()</code> + 重新 <code>init()</code>。</p>
<p>最后方案：每 30 秒查一次服务端评论数，有新增<strong>且</strong>用户没在输入框打字时，才重建评论区。无新增零打扰，用户打字时不打断——草稿丢了是要骂人的。</p>
<h2>小修小补</h2>
<ul>
<li>实验报告《Analog Basic Amplifier》的电路图乱码了：ASCII 电路图转 Markdown 时对齐全丢，换成原图</li>
<li>转换速率表格重排成标准 Markdown 表格</li>
<li>两篇报告清掉 Word 分页符残留（<code>\x0c</code>，渲染会出怪字符）</li>
<li>Circuit Lab 6 的仿真截图放错了（放了张公式图），换成正确的 Multisim 截图</li>
<li>友链加了<a href="https://blog.fqzlr.top/"><strong>番茄主理人</strong></a>（排第一）、<a href="https://pasule.com/"><strong>Pasule</strong></a></li>
</ul>
<h2>还没搞定的</h2>
<ul>
<li>轮询 60 秒还是有点慢，AI 回复要 70-80 秒才可见。想改 15 秒，还在犹豫（怕被智谱限流）</li>
<li>Webhook 不触发的原因还没查清</li>
<li>统计页 Swup 导航时的数据竞态修了，等验证</li>
</ul>
<p>折腾一天，博客又活过来一点。AI 评论员已上岗，欢迎来调戏——它现在叫 zhz-ai，别叫错了。</p>
]]></content:encoded></item><item><title>Umami 统计加速：VPS 定时任务 + 静态 JSON，让统计页毫秒级加载</title><link>https://idea.lanerc.me/posts/umami-static-json-cache/umami-static-json-cache/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/umami-static-json-cache/umami-static-json-cache/</guid><description>博客统计页直连 Umami API 太慢？用 VPS cron 每 5 分钟拉数据写成静态 JSON，前端优先读 JSON、失败降级走 API。Cloudflare CDN 缓存，毫秒级加载，附完整脚本和部署步骤。</description><pubDate>Sat, 17 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>博客统计页（/analytics/）之前是浏览器直连 Umami API 拉数据。在我自己网络好的时候没问题，但在某些网络环境下（比如 PC 到 Cloudflare 的链路差），要等好几秒甚至失败。这篇讲我是怎么做加速的：<strong>VPS 上跑定时任务，每 5 分钟拉一次 Umami 数据写成静态 JSON，前端优先读这个 JSON，读不到再降级走原来的 API</strong>。</p>
<h2>一、为什么慢</h2>
<p>先捋一下原来的流程：</p>
<pre><code>浏览器 → Cloudflare → umami.lanerc.me → VPS 上的 Umami → PostgreSQL 查数据 → 原路返回
</code></pre>
<p>一次页面加载要调 4 个接口：</p>
<ol>
<li><code>GET /api/share/{shareId}</code> —— 拿 websiteId 和 token（token 缓存 24h）</li>
<li><code>GET /api/websites/{id}/stats?startAt=...&amp;endAt=...</code> —— 30 天统计</li>
<li><code>GET /api/websites/{id}/stats?...</code> —— 今日统计</li>
<li><code>GET /api/realtime/{id}</code> —— 实时在线</li>
</ol>
<p>慢的原因：</p>
<ul>
<li><strong>Umami 的 stats 查询是实时聚合</strong>，30 天的数据要在数据库里扫一遍，本身就要几百毫秒到几秒</li>
<li><strong>多一跳 Cloudflare</strong>，每个请求都要过 CDN</li>
<li><strong>浏览器到 Cloudflare 的链路</strong>如果差，每个请求都要等</li>
</ul>
<p>HY（9ll.uk）快是因为他的访客到 Cloudflare 的路好，架构跟我是一样的。</p>
<h2>二、方案：静态 JSON 缓存</h2>
<p>核心思路：<strong>把慢查询挪到服务器端定时做，浏览器只读一个静态文件</strong>。</p>
<pre><code>VPS cron（每5分钟）→ Umami localhost（快）→ 写 /api/stats.json
浏览器 → Cloudflare CDN（缓存）→ /api/stats.json（毫秒级）
</code></pre>
<p>好处：</p>
<ul>
<li>浏览器只拉一个几百字节的 JSON，走 CDN 缓存，基本是毫秒级</li>
<li>Umami 的慢查询在服务器端做，用户无感</li>
<li>数据最多 5 分钟延迟，对统计页来说完全够用</li>
</ul>
<p>代价：</p>
<ul>
<li>不是严格实时，有 5 分钟延迟（但比之前刷不出来强多了）</li>
<li>需要 VPS 上多一个 cron 任务</li>
</ul>
<h2>三、VPS 定时脚本</h2>
<p>脚本放在 VPS 上，比如 <code>/opt/umami-stats-cron.sh</code>：</p>
<pre><code class="language-bash">#!/bin/bash
# Umami 统计数据定时拉取脚本
# 每 5 分钟跑一次，把数据写成静态 JSON，供博客统计页优先读取

set -e

# ===== 配置区 =====
UMAMI_BASE="https://umami.lanerc.me"
SHARE_ID="EG15WwHeRvz2lmd2"  # 换成你自己的 share ID
# 网站根目录（nginx 的 root），stats.json 会写到 $WEB_ROOT/api/stats.json
WEB_ROOT="/var/www/lanerc"
# ==================

API_DIR="$WEB_ROOT/api"
OUT_FILE="$API_DIR/stats.json"
TMP_FILE="$API_DIR/.stats.json.tmp"

mkdir -p "$API_DIR"

# 1. 拿 websiteId 和 token
SHARE_JSON=$(curl -s --max-time 15 "$UMAMI_BASE/api/share/$SHARE_ID")
WEBSITE_ID=$(echo "$SHARE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('websiteId',''))")
TOKEN=$(echo "$SHARE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('token',''))")

if [ -z "$WEBSITE_ID" ] || [ -z "$TOKEN" ]; then
  echo "[$(date '+%F %T')] ERROR: 获取 share token 失败"
  exit 1
fi

NOW_MS=$(date +%s)000
DAY_MS=86400000
P30_START=$(( $(date +%s) * 1000 - 30 * DAY_MS ))
TODAY_START=$(date -d "$(date +%F) 00:00:00" +%s)000

HDR=(-H "x-umami-share-token: $TOKEN" -H "x-umami-share-context: 1")

# 2. 拉 30 天统计、今日统计、实时数据（并行写临时文件）
curl -s --max-time 20 "${HDR[@]}" "$UMAMI_BASE/api/websites/$WEBSITE_ID/stats?startAt=$P30_START&amp;endAt=$NOW_MS&amp;unit=day&amp;timezone=Asia/Shanghai" -o /tmp/umami_s30.json &amp;
P1=$!
curl -s --max-time 20 "${HDR[@]}" "$UMAMI_BASE/api/websites/$WEBSITE_ID/stats?startAt=$TODAY_START&amp;endAt=$NOW_MS&amp;unit=day&amp;timezone=Asia/Shanghai" -o /tmp/umami_today.json &amp;
P2=$!
curl -s --max-time 20 "${HDR[@]}" "$UMAMI_BASE/api/realtime/$WEBSITE_ID" -o /tmp/umami_rt.json &amp;
P3=$!
wait $P1 $P2 $P3 || true

# 3. 组装成前端需要的格式
python3 &lt;&lt; 'PYEOF'
import json, time

def load(p):
    try:
        with open(p) as f:
            return json.load(f)
    except Exception:
        return None

s30 = load('/tmp/umami_s30.json') or {}
today = load('/tmp/umami_today.json') or {}
rt = load('/tmp/umami_rt.json') or {}

# 在线人数：5 分钟内有活动的去重 session
online = 0
try:
    seen = set()
    cutoff = time.time() * 1000 - 5 * 60 * 1000
    for e in (rt.get('events') or []):
        from datetime import datetime
        ts = e.get('createdAt', '')
        try:
            t = datetime.fromisoformat(ts.replace('Z', '+00:00')).timestamp() * 1000
        except Exception:
            continue
        sid = e.get('sessionId')
        if t &gt;= cutoff and sid and sid not in seen:
            seen.add(sid)
            online += 1
except Exception:
    pass

out = {
    'totalVisitors': s30.get('visitors'),
    'totalPageviews': s30.get('pageviews'),
    'todayVisitors': today.get('visitors'),
    'todayPageviews': today.get('pageviews'),
    'online': online,
    'generatedAt': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
}
with open('/tmp/umami_stats_out.json', 'w') as f:
    json.dump(out, f)
print('OK', out.get('generatedAt'))
PYEOF

# 4. 原子写入（先写临时文件再 mv，避免读到一半的文件）
mv /tmp/umami_stats_out.json "$TMP_FILE"
mv "$TMP_FILE" "$OUT_FILE"
chmod 644 "$OUT_FILE"
echo "[$(date '+%F %T')] stats.json 已更新"
</code></pre>
<h3>设置 cron</h3>
<pre><code class="language-bash"># 给脚本执行权限
chmod +x /opt/umami-stats-cron.sh

# 先手动跑一次，确认能生成文件
/opt/umami-stats-cron.sh
cat /var/www/lanerc/api/stats.json

# 加到 crontab，每 5 分钟跑一次
crontab -e
# 添加这一行：
*/5 * * * * /opt/umami-stats-cron.sh &gt;&gt; /var/log/umami-stats.log 2&gt;&amp;1
</code></pre>
<h3>nginx 配置</h3>
<p>确保 <code>/api/stats.json</code> 能被访问。如果你的 nginx root 已经是 <code>/var/www/lanerc</code>，那 <code>https://lanerc.me/api/stats.json</code> 会自动生效。不需要额外配置。</p>
<p>建议给这个文件加个短缓存（CDN 层面），比如 1 分钟：</p>
<pre><code class="language-nginx">location = /api/stats.json {
    expires 1m;
    add_header Cache-Control "public, max-age=60";
}
</code></pre>
<h2>四、前端改造</h2>
<p>前端逻辑：<strong>先尝试拉 <code>/api/stats.json</code>，成功就用它；失败则走原来的 Umami API</strong>（原逻辑一行不动，作为兜底）。</p>
<p>我在 <code>analytics.astro</code> 里加了一个独立的 <code>&lt;script&gt;</code> 块，放在主逻辑之前：</p>
<pre><code class="language-html">&lt;script is:inline&gt;
// 静态 JSON 优先尝试：VPS 定时任务每 5 分钟生成 /api/stats.json
// 成功则渲染并设置标志，主 script 会直接返回；失败则静默，主 script 走原有 API 逻辑
(function () {
    function fmt(n) { return Number(n || 0).toLocaleString(); }
    function renderStatic(d) {
        var map = {
            totalVisitors: d.totalVisitors,
            totalPageviews: d.totalPageviews,
            todayVisitors: d.todayVisitors,
            todayPageviews: d.todayPageviews
        };
        Object.keys(map).forEach(function (k) {
            var el = document.querySelector('[data-stat="' + k + '"]');
            if (el &amp;&amp; map[k] != null) el.textContent = fmt(map[k]);
        });
        var onlineEl = document.getElementById("live-online");
        if (onlineEl &amp;&amp; d.online != null) {
            onlineEl.innerHTML = '&lt;span class="online-dot"&gt;&lt;/span&gt;' +
                (d.online &gt; 0 ? d.online + " 人在线" : "在线");
        }
        var updatedEl = document.getElementById("live-updated");
        if (updatedEl) {
            var t = new Date().toLocaleString("zh-CN", { hour12: false }).slice(0, 16);
            updatedEl.textContent = "实时更新于 " + t + " · 30天区间";
        }
        try {
            localStorage.setItem("lanerc-umami-live",
                JSON.stringify({ ts: Date.now(), data: d }));
        } catch (e) {}
    }
    fetch("/api/stats.json", { cache: "no-store" })
        .then(function (r) { if (!r.ok) throw 0; return r.json(); })
        .then(function (d) {
            if (d &amp;&amp; (d.totalVisitors != null || d.totalPageviews != null)) {
                renderStatic(d);
                window.__lanercStatsDone = true;  // 标记已命中
            }
        })
        .catch(function () {});  // 失败静默，主逻辑会兜底
})();
&lt;/script&gt;
</code></pre>
<p>主 script 开头加一行检查：</p>
<pre><code class="language-js">(function () {
    if (window.__lanercStatsDone) return;  // 静态 JSON 已命中，直接返回
    // ... 原有 Umami API 逻辑（未改动）
})();
</code></pre>
<p>关键点：</p>
<ul>
<li><strong>两个 script 块互相独立</strong>，静态 JSON 的那个失败了不会影响主逻辑</li>
<li>用 <code>window.__lanercStatsDone</code> 做标记，避免重复渲染</li>
<li><code>fetch</code> 用 <code>{ cache: "no-store" }</code>，确保拿到的是最新的（CDN 层面可以设 1 分钟缓存，平衡实时性和速度）</li>
<li>原有 API 逻辑一行没动，JSON 文件不存在或拉取失败时自动降级</li>
</ul>
<p>注意 <code>is:inline</code>：Astro 构建时会处理 <code>&lt;script&gt;</code> 标签，不加 <code>is:inline</code> 的会被打包优化掉，导致线上不执行。这个坑我踩过两次了，血的教训。</p>
<h2>五、效果对比</h2>
<table>
<thead>
<tr>
<th>指标</th>
<th>改造前</th>
<th>改造后</th>
</tr>
</thead>
<tbody><tr>
<td>请求数</td>
<td>4 个 API</td>
<td>1 个静态文件</td>
</tr>
<tr>
<td>响应时间（网络好）</td>
<td>1-2s</td>
<td>&lt;100ms</td>
</tr>
<tr>
<td>响应时间（网络差）</td>
<td>5-10s 或失败</td>
<td>&lt;500ms</td>
</tr>
<tr>
<td>数据延迟</td>
<td>实时</td>
<td>最多 5 分钟</td>
</tr>
<tr>
<td>失败时</td>
<td>显示构建时的旧数据</td>
<td>自动降级走 API</td>
</tr>
</tbody></table>
<h2>六、踩坑记录</h2>
<ol>
<li><p><strong>Astro 的 <code>is:inline</code></strong>：内联 script 必须加 <code>is:inline</code>，否则构建时会被 Astro 处理掉，线上 JS 根本不执行。我之前已经因为这个坑修过两次统计页了。</p>
</li>
<li><p><strong>原子写入</strong>：cron 脚本写 JSON 时先写临时文件再 <code>mv</code>，避免浏览器读到写一半的文件。</p>
</li>
<li><p><strong>时区</strong>：Umami API 的 <code>timezone=Asia/Shanghai</code> 参数别漏，否则今日数据会对不上。</p>
</li>
<li><p><strong>在线人数计算</strong>：realtime 接口返回的是 events 列表，需要按 sessionId 去重，只算 5 分钟内有活动的。这个逻辑在前后端都要保持一致。</p>
</li>
</ol>
<h2>七、总结</h2>
<p>这个方案的核心就是<strong>用空间换时间</strong>：VPS 上多一个 cron 任务，换来前端毫秒级的加载体验。对于统计页这种"数据可以容忍几分钟延迟"的场景，非常划算。</p>
<p>如果你也在用 Umami 做博客统计，且访客网络环境复杂，可以试试这套方案。完整脚本在上面，直接拿去改改配置就能用。</p>
]]></content:encoded></item><item><title>Waline 评论 + Umami 统计：从零部署到接入博客全教程</title><link>https://idea.lanerc.me/posts/analytics-rebuild-diary/analytics-rebuild-diary/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/analytics-rebuild-diary/analytics-rebuild-diary/</guid><description>香港 VPS 上 docker 部署 Waline（评论）和 Umami（统计），nginx 反代 + Cloudflare HTTPS，博客端接入配置。踩坑全记录，命令都验证过。</description><pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>博客的评论和统计，我全用自建的：Waline 做评论，Umami 做访问统计。都在一台香港 VPS 上跑 Docker，nginx 反代，Cloudflare 做 HTTPS。这篇把部署全过程写清楚，命令都是亲测有效的。</p>
<h2>一、Waline：评论系统</h2>
<h3>1. Docker 部署</h3>
<p>Waline 官方镜像 <code>lizheming/waline</code>，用 SQLite 就行，不用额外数据库。</p>
<pre><code class="language-bash"># 生成随机 JWT 密钥（在你自己的终端执行）
openssl rand -hex 32

# 启动容器（把上面生成的密钥填进去）
sudo docker run -d \
  --name waline \
  --restart always \
  -p 127.0.0.1:8360:8360 \
  -v waline-data:/app/data \
  -e SQLITE_PATH=/app/data \
  -e JWT_TOKEN=你生成的密钥 \
  -e SERVER_URL=https://waline.lanerc.me \
  lizheming/waline:latest
</code></pre>
<p><strong>三个必加的环境变量，一个都不能少</strong>（都是 10-16 亲测踩坑）：</p>
<table>
<thead>
<tr>
<th>变量</th>
<th>值</th>
<th>不加的后果</th>
</tr>
</thead>
<tbody><tr>
<td><code>SQLITE_PATH</code></td>
<td><code>/app/data</code>（必须是<strong>目录</strong>，不是文件）</td>
<td>写成 <code>/app/data/waline.db</code> 会被当成目录，容器起不来</td>
</tr>
<tr>
<td><code>JWT_TOKEN</code></td>
<td>随机字符串</td>
<td>SQLite 分支没有 fallback，登录报 <code>secretOrPrivateKey must have a value</code></td>
</tr>
<tr>
<td><code>SERVER_URL</code></td>
<td><code>https://waline.lanerc.me</code></td>
<td>Cloudflare Flexible SSL 下，不设会导致管理后台混合内容被拦截</td>
</tr>
</tbody></table>
<p>验证：</p>
<pre><code class="language-bash">curl -s http://127.0.0.1:8360/api/comment | head -c 200
# 应返回 {"errno":0,...}，不是 000
</code></pre>
<h3>2. 手动建表（必须）</h3>
<p>Waline 镜像<strong>不会</strong>自动建表。首次部署后手动建三张表：</p>
<pre><code class="language-bash"># 起个临时容器连上 waline-data 卷
sudo docker run --rm -it -v waline-data:/app/data alpine sh
apk add sqlite
sqlite3 /app/data/waline.sqlite
</code></pre>
<pre><code class="language-sql">-- wl_Comment（注意必须有 sticky 列，漏了查评论列表会报错）
CREATE TABLE wl_Comment (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id INTEGER, comment TEXT, insertedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  ip VARCHAR(100), link VARCHAR(255), mail VARCHAR(255), nick VARCHAR(255),
  pid INTEGER DEFAULT 0, rid INTEGER DEFAULT 0, sticky INTEGER DEFAULT 0,
  status VARCHAR(50) DEFAULT 'approved', like INTEGER DEFAULT 0,
  ua TEXT, url VARCHAR(255), createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE wl_Counter (id INTEGER PRIMARY KEY AUTOINCREMENT, time INTEGER, url VARCHAR(255), createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
CREATE TABLE wl_Users (id INTEGER PRIMARY KEY AUTOINCREMENT, display_name VARCHAR(255), email VARCHAR(255), password VARCHAR(255), type VARCHAR(50) DEFAULT 'guest', url VARCHAR(255), avatar VARCHAR(255), github VARCHAR(255), twitter VARCHAR(255), facebook VARCHAR(255), google VARCHAR(255), weibo VARCHAR(255), qq VARCHAR(255), createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
</code></pre>
<p>真正的库文件是 <code>/app/data/waline.sqlite</code>（<code>waline.db</code> 是 0 字节空文件，别搞错）。</p>
<h3>3. nginx 反代 + Cloudflare</h3>
<p><code>/etc/nginx/conf.d/waline.conf</code>：</p>
<pre><code class="language-nginx">server {
    listen 80;
    server_name waline.lanerc.me;
    location / {
        proxy_pass http://127.0.0.1:8360;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
</code></pre>
<pre><code class="language-bash">sudo nginx -t &amp;&amp; sudo systemctl reload nginx
</code></pre>
<p>Cloudflare 加 A 记录 <code>waline</code> → VPS IP，橙色云朵（代理），SSL 设 Flexible。</p>
<h3>4. 博客端接入</h3>
<p><code>src/config/commentConfig.ts</code>：</p>
<pre><code class="language-ts">export const commentConfig = {
  type: 'waline',
  waline: {
    serverURL: 'https://waline.lanerc.me',
    // 其他按需
  },
};
</code></pre>
<p><strong>管理员机制</strong>：第一个注册的用户自动成为管理员。如果之前测试账号先注册占了位置，查库：</p>
<pre><code class="language-sql">SELECT id, display_name, email, type FROM wl_Users;
-- 把测试账号删掉，真实账号 type 改成 'administrator'
UPDATE wl_Users SET type='administrator' WHERE email='你的邮箱';
</code></pre>
<h3>5. 时间戳坑（1970 问题）</h3>
<p>Waline 前端有个 bug：用 <code>createdAt</code> 而不用 <code>insertedAt</code> 会导致 1970 时间。博客首页的"最近评论"组件用的是 <code>insertedAt</code>，记得统一。老数据用触发器回填，存北京时间。</p>
<hr />
<h2>二、Umami：访问统计</h2>
<h3>1. 为什么不用 Umami Cloud</h3>
<p>自建免费、数据在自己手里。代价是要个 PostgreSQL（Umami 不支持 SQLite/MySQL）。</p>
<h3>2. Docker 部署（纯 docker run 版）</h3>
<p>注意：我这台香港 VPS 的 Docker 29.1.3 没有 compose 插件，所以用纯 <code>docker run</code> 脚本。包在 <code>~/workspace/blog-build/umami/</code>，两个文件：<code>deploy-umami-docker-run.sh</code> + <code>nginx-umami.conf</code>。</p>
<pre><code class="language-bash">mkdir ~/umami &amp;&amp; cd ~/umami
# 把 umami-deploy.tar.gz 解压到这里
tar -xzf umami-deploy.tar.gz
sudo bash deploy-umami-docker-run.sh
</code></pre>
<p>脚本做的事情：</p>
<ol>
<li>自动生成 <code>.env</code>（强密码，600 权限，复跑沿用）</li>
<li>建 <code>umami-net</code> 独立 Docker 网络</li>
<li>起 <code>umami-db</code>（<code>postgres:15-alpine</code>，带 healthcheck，轮询等 healthy）</li>
<li>起 <code>umami</code>（<code>ghcr.io/umami-software/umami:3.4.0</code>，只绑 <code>127.0.0.1:8362</code>）</li>
<li>等 <code>/api/heartbeat</code> 通</li>
</ol>
<p>关键环境变量（脚本自动处理，手动部署时注意）：</p>
<pre><code class="language-bash"># umami 容器必需
-e DATABASE_URL=postgresql://umami:密码@umami-db:5432/umami
-e APP_SECRET=随机字符串  # 必须显式设置，不设静默降级有安全隐患
</code></pre>
<p>首次启动自动建表 + 创建 <code>admin</code> / <code>umami</code> 账号——<strong>立刻改掉默认密码</strong>。</p>
<p>数据不丢：PostgreSQL 用命名卷 <code>umami-db-data</code>，重装容器数据还在。</p>
<h3>3. nginx 反代</h3>
<p><code>nginx-umami.conf</code>（脚本包里自带，拷到 <code>/etc/nginx/conf.d/</code>）：</p>
<pre><code class="language-nginx">server {
    listen 80;
    server_name umami.lanerc.me;
    location / {
        proxy_pass http://127.0.0.1:8362;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
</code></pre>
<p>Cloudflare 加 A 记录 <code>umami</code> → VPS IP，橙色云朵。</p>
<h3>4. 创建网站 + 拿 Website ID</h3>
<p>登录 <code>https://umami.lanerc.me</code> → Settings → Websites → Add website，填域名 <code>lanerc.me</code>。创建后点进网站详情，URL 里那串 UUID 就是 Website ID。</p>
<p>博客 <code>src/config/analyticsConfig.ts</code>：</p>
<pre><code class="language-ts">export const analyticsConfig = {
  umami: {
    enabled: true,
    websiteId: '你的-website-id',
    scriptUrl: 'https://umami.lanerc.me/script.js',
    // 会话回放（可选，v3.1+）
    replays: {
      enabled: true,
      scriptUrl: 'https://umami.lanerc.me/recorder.js',
    },
  },
};
</code></pre>
<h3>5. 构建时拉数据（给统计页用）</h3>
<p>统计页 <code>/analytics/</code> 的数据是构建时从 Umami API 拉的，不是实时查：</p>
<pre><code class="language-bash"># 在你自己的终端（不要贴 key 到聊天里）
export UMAMI_API_KEY="你的api-key"
python3 scripts/fetch-umami-stats.py
</code></pre>
<p>脚本拉取：</p>
<ul>
<li>90 天 daily（给 7/30/90 天切换）</li>
<li>30 天 hourly（给 7×24 热力图）</li>
<li>devices / browsers / topPages / referrers</li>
</ul>
<p>输出 <code>src/data/umami-stats.json</code>。</p>
<p><strong>两个坑</strong>：</p>
<ol>
<li><strong>403 限流</strong>：Umami 对密集请求返回 403，不是 key 错。脚本里每个请求间隔 2 秒。</li>
<li><strong>type 参数</strong>：metrics 接口用 <code>type=path</code>，<code>type=url</code> 会 400。realtime 接口路径是 <code>/api/realtime/{websiteId}</code>。</li>
</ol>
<p>API Key 在 Umami 后台 Settings → API Keys 创建。<strong>Key 只显示一次，丢了就重新生成</strong>。</p>
<hr />
<h2>三、统计页前端：SVG 环形图</h2>
<p>数据有了，前端展示。学 HY 的 donut 图，不用 ECharts，SVG 手画：</p>
<pre><code class="language-astro">---
const R = 54, C = 2 * Math.PI * R;
let offset = 25;
const segs = items.map((item, i) =&gt; {
  const len = (item.count / total) * C;
  const el = (
    &lt;circle cx="70" cy="70" r={R} fill="none"
      stroke={colors[i]} stroke-width="18"
      stroke-dasharray={`${len} ${C - len}`}
      stroke-dashoffset={-offset}
      transform="rotate(-90 70 70)" /&gt;
  );
  offset += len;
  return { el, pct: Math.round((item.count / total) * 100) };
});
---
&lt;svg viewBox="0 0 140 140"&gt;
  &lt;circle cx="70" cy="70" r={R} fill="none" stroke="#f3f0ea" stroke-width="18" /&gt;
  {segs.map(s =&gt; s.el)}
&lt;/svg&gt;
</code></pre>
<p>原理：<code>stroke-dasharray</code> 控制每段弧的显示长度，<code>stroke-dashoffset</code> 累加实现拼接，<code>rotate(-90)</code> 让起点从顶部开始。</p>
<p>淡背景图必须用 CSS <code>background-image</code>，不要用 <code>&lt;img&gt;</code> 绝对定位：</p>
<pre><code class="language-css">.device-card {
  background-image:
    linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.9)),
    url('/images/analytics/card-11.jpg');
  background-size: cover;
  background-position: center;
}
</code></pre>
<hr />
<h2>踩坑总表</h2>
<table>
<thead>
<tr>
<th>坑</th>
<th>症状</th>
<th>解法</th>
</tr>
</thead>
<tbody><tr>
<td>Waline <code>SQLITE_PATH</code> 写成文件路径</td>
<td>容器起不来</td>
<td>必须是目录 <code>/app/data</code></td>
</tr>
<tr>
<td>Waline 不设 <code>JWT_TOKEN</code></td>
<td>登录报 <code>secretOrPrivateKey must have a value</code></td>
<td>SQLite 无 fallback，必须设</td>
</tr>
<tr>
<td>Waline 不设 <code>SERVER_URL</code></td>
<td>CF Flexible 下后台混合内容被拦</td>
<td>设为 <code>https://</code> 开头</td>
</tr>
<tr>
<td>Waline 不建表</td>
<td><code>no such table: wl_Comment</code></td>
<td>手动建三张表，别漏 <code>sticky</code> 列</td>
</tr>
<tr>
<td>第一个注册的不是你</td>
<td>你变成 guest</td>
<td>SQL 把 type 改成 administrator</td>
</tr>
<tr>
<td>Umami 403</td>
<td>拉数据失败</td>
<td>请求间隔 2 秒</td>
</tr>
<tr>
<td>Umami <code>type=url</code></td>
<td>400</td>
<td>用 <code>type=path</code></td>
</tr>
<tr>
<td>部署完没变化</td>
<td>看到旧页面</td>
<td>清 Cloudflare 缓存</td>
</tr>
<tr>
<td>img 当背景</td>
<td>被骂重做</td>
<td>用 CSS background-image</td>
</tr>
</tbody></table>
<hr />
<p>两套服务跑下来，评论和统计全在自己手里，不依赖第三方 SaaS。备份记得带上 <code>waline-data</code> 和 <code>umami-db-data</code> 两个 Docker 卷。</p>
<hr />
<h2>四、站点统计页：设计思路</h2>
<h3>为什么学 HY</h3>
<p>HY 的 <a href="https://www.9ll.uk/analytics/">9ll.uk/analytics</a> 是我见过最好看的个人站统计页。核心三招：</p>
<ol>
<li><strong>双栏错落</strong>：左宽右窄，卡片高低错开，不是一排排堆下去——单栏看着像后台管理系统，双栏才像"展示页"。</li>
<li><strong>环形图 + 条排布</strong>：设备、浏览器用 donut 图，左边图右边图例（彩色圆点 + 名称 + 百分比），信息密度高又不挤。</li>
<li><strong>淡背景</strong>：二次元妹子图 8-10% 透明度铺底，若隐若现。纯白卡片太素，全图背景太吵，淡化是中间解。</li>
</ol>
<h3>卡片规划（11 张）</h3>
<table>
<thead>
<tr>
<th>#</th>
<th>卡片</th>
<th>数据源</th>
<th>备注</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>Hero（站点统计）</td>
<td>Umami allTime</td>
<td>大标题 + 妹子图，不折腾</td>
</tr>
<tr>
<td>2-5</td>
<td>数字卡×4</td>
<td>Umami</td>
<td>累计访客/浏览、今日访客/浏览</td>
</tr>
<tr>
<td>6</td>
<td>访问脉冲</td>
<td>Umami daily</td>
<td>7/30/90 天切换 + 热门页面</td>
</tr>
<tr>
<td>7</td>
<td>推送节奏</td>
<td>GitHub API</td>
<td>52 周热力图 + 4 统计</td>
</tr>
<tr>
<td>8</td>
<td>访客活跃时间</td>
<td>Umami hourly</td>
<td>7×24 点阵 + 4 统计</td>
</tr>
<tr>
<td>9</td>
<td>设备与浏览器</td>
<td>Umami</td>
<td>两个 donut 图</td>
</tr>
<tr>
<td>10</td>
<td>访客地域分布</td>
<td>Umami</td>
<td>暂无数据，占位</td>
</tr>
<tr>
<td>11</td>
<td>流量来源</td>
<td>Umami</td>
<td>暂无数据，占位</td>
</tr>
<tr>
<td>12</td>
<td>最近评论</td>
<td>Waline API</td>
<td>复用首页组件</td>
</tr>
</tbody></table>
<p>地域和来源暂无数据（站太新），先上架子等数据——总比"即将上线"强。</p>
<h3>技术选型</h3>
<ul>
<li><strong>不用 ECharts</strong>：donut 图用 SVG 原生 <code>&lt;circle&gt;</code> + <code>stroke-dasharray</code> 手画，零依赖，加载快。</li>
<li><strong>构建时拉数据</strong>：Umami 和 GitHub 都是构建时跑 Python 脚本写 JSON，页面纯静态。坏处是不是实时，好处是访问快、不怕 API 挂。</li>
<li><strong>Waline 评论客户端拉</strong>：评论需要实时性，用 <code>client:load</code> + 2 分钟本地缓存。</li>
</ul>
<hr />
<h2>五、调试过程：三次翻车</h2>
<h3>翻车一：Cloudflare 缓存（两次）</h3>
<p><strong>症状</strong>：部署完 v46，打开网站一看——导航栏没有"站点统计"按钮。本地构建明明有。</p>
<p><strong>排查</strong>：</p>
<pre><code class="language-bash"># 查线上 HTML
curl -s https://lanerc.me/ | grep -c 'href="/analytics/"'
# 输出 0

# 查 8880 直连（不走 Cloudflare）
curl -s http://20.239.49.52:8880/ | grep -c 'href="/analytics/"'
# 输出 2
</code></pre>
<p>8880 有，lanerc.me 没有——Cloudflare 把旧 HTML 缓存了。</p>
<p><strong>解法</strong>：Cloudflare 后台 purge 缓存。或者先用 8880 验证，确认没问题再清缓存看正式站。</p>
<p><strong>教训</strong>：部署完第一件事不是问"看到了吗"，而是先 purge。</p>
<h3>翻车二：img 冒充背景图</h3>
<p><strong>症状</strong>：设备卡和推送卡的淡背景图，我用 <code>&lt;img class="device-bg"&gt;</code> 绝对定位实现。一看效果：这叫背景图？语义完全错了，重做。</p>
<p><strong>原因</strong>：<code>&lt;img&gt;</code> 绝对定位虽然视觉上像背景，但语义错了，而且要额外处理 z-index、pointer-events。CSS <code>background-image</code> 才是正解。</p>
<p><strong>修复</strong>：</p>
<pre><code class="language-css">/* 错误示范（已删） */
.device-bg { position: absolute; inset: 0; opacity: 0.1; }

/* 正确做法 */
.device-card {
  background-image:
    linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.9)),
    url('/images/analytics/card-11.jpg');
  background-size: cover;
}
</code></pre>
<h3>翻车三：图片被裁得只剩一条</h3>
<p><strong>症状</strong>：推送卡热力图下方加了张樱花图，设了 <code>height: 120px</code> + <code>object-fit: cover</code>，结果一看：这叫调整大小？？？整个图片被裁得只剩中间一条。</p>
<p><strong>原因</strong>：想着固定高度更整齐，但我要的是完整图片。<code>object-fit: cover</code> 会裁掉上下，16:9 的图只剩中间一条。</p>
<p><strong>修复</strong>：<code>height: auto</code>，宽度 100% 顶满，完整显示。</p>
<p><strong>教训</strong>：图片展示这事，整齐和完整只能二选一，先想清楚你要哪个。</p>
<hr />
<h2>六、优化过程：v46 → v62</h2>
<p>一晚上 16 个版本，每个版本只改一件事：</p>
<table>
<thead>
<tr>
<th>版本</th>
<th>改动</th>
</tr>
</thead>
<tbody><tr>
<td>v46</td>
<td>基座：双栏、7/30/90 切换、7×24 热力图</td>
</tr>
<tr>
<td>v47</td>
<td>访问脉冲加淡背景，8 小框统一样式</td>
</tr>
<tr>
<td>v48</td>
<td>8 框统一 72px 高，字体缩小防截断</td>
</tr>
<tr>
<td>v49</td>
<td>设备/浏览器改 SVG 环形图 + 右侧图例</td>
</tr>
<tr>
<td>v50</td>
<td>热门页面改成可点击 <code>&lt;a&gt;</code> 跳转</td>
</tr>
<tr>
<td>v51</td>
<td>流量来源加樱花背景 + 环形图，6 号卡起字体调小</td>
</tr>
<tr>
<td>v52</td>
<td>Hero 图边缘渐变 + 光晕，GitHub 真实数据接入</td>
</tr>
<tr>
<td>v53</td>
<td>除前 5 卡外全部加落樱动画</td>
</tr>
<tr>
<td>v54</td>
<td>设备卡加暗黑妹子背景（img 版，错的）</td>
</tr>
<tr>
<td>v55</td>
<td>推送卡按 HY 重构 2x2 色块</td>
</tr>
<tr>
<td>v56</td>
<td>设备卡/推送卡改 CSS background（重做 v54 的错）</td>
</tr>
<tr>
<td>v57</td>
<td>删推送卡底部"小蛇蛇"那段话</td>
</tr>
<tr>
<td>v58</td>
<td>地域卡加 Q 版妹子背景</td>
</tr>
<tr>
<td>v59</td>
<td>推送卡加樱花图（裁剪版，错的）</td>
</tr>
<tr>
<td>v60</td>
<td>樱花图改完整显示（重做 v59 的错）</td>
</tr>
<tr>
<td>v61</td>
<td>追踪仓库显示 folia-major</td>
</tr>
<tr>
<td>v62</td>
<td>最终版</td>
</tr>
</tbody></table>
<p><strong>优化原则</strong>：</p>
<ol>
<li><strong>一次只改一件事</strong>：方便回滚，v56 重做 v54、v60 重做 v59 都是这么来的。</li>
<li><strong>截图即需求</strong>：自己截图标红的地方，就是下一版的改动点，不用猜。</li>
<li><strong>字体只调小不调大</strong>：从第 6 张卡开始，标题 1.35rem、小节 0.95rem，信息密度上来了就不吵了。</li>
<li><strong>动画克制</strong>：落樱每个卡 3 片，opacity 0.45，多了就是杀马特。</li>
</ol>
<hr />
<p>源码在 <code>src/pages/analytics.astro</code>，单个文件 800+ 行。想抄的直接看文件，比看这篇管用。</p>
<hr />
<h2>七、后续方向：国内访问加速</h2>
<p>目前博客在国内访问很慢，这是下一步要解决的。思路：</p>
<p><strong>先分析原因</strong>：到底是 Cloudflare 边缘节点问题、VPS 到国内的线路问题，还是纯粹的备案缺失导致的绕路？得先抓数据——不同地区、不同运营商的延迟和丢包率，找出瓶颈在哪。这部分分析后续补充。</p>
<p><strong>备案的打算</strong>：如果分析下来是线路问题，考虑给域名做 ICP 备案，然后上国内 CDN。但备案意味着服务器要迁回国内，整套 Docker（Waline、Umami）都要跟着迁，成本不小。还在看，先把原因分析清楚再决定。</p>
<p>总之：先诊断，再开药。盲目上 CDN 烧钱没意义。</p>
]]></content:encoded></item><item><title>博客重建：从 Fuwari 到 Firefly，一天的折腾记录</title><link>https://idea.lanerc.me/posts/blog-rebuild-diary/blog-rebuild-diary/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/blog-rebuild-diary/blog-rebuild-diary/</guid><description>把博客从 Fuwari 搬到 Firefly，踩了一堆坑：Astro content 缓存、VPS 构建内存爆炸、Live2D 的 DOM 定位、下载站的反爬。记录一下。</description><pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>旧博客是 Fuwari 主题，用了一阵子，越看越觉得功能不够施展。今天一咬牙，整个搬到 Firefly——同样是 Astro 生态，但卡片风格、轮播横幅、自带音乐播放器和 Live2D，可玩性高得多。</p>
<h2>迁移：11 篇文章，一次过</h2>
<p>Firefly 用 Astro 的 content collections 管内容，文章丢进 <code>src/content/posts/</code> 就行。旧站 11 篇文章加 About 页，图片路径改成相对路径，构建一次通过，没出幺蛾子。新域名 <code>lanerc.me</code>，旧站留着 <code>www.lanerc.me</code>，导航栏加个"开往旧站"，体面分手。</p>
<h2>构建：别在 VPS 上作死</h2>
<p>第一个坑出现在构建环节。<code>pnpm build</code> 会先跑一堆联网的生成脚本（GitHub 卡片数据、封面抓取之类的），在网络差的环境直接卡死。解决办法：只改内容的时候直接跑 <code>./node_modules/.bin/astro build</code>，跳过那些脚本。</p>
<p>第二个坑更狠：之前试过在 VPS 上直接构建，结果 Node 进程被 OOM killer 干掉，exit 133。887MB 内存的小鸡就别想本地构建这种事了。从此定下规矩：<strong>本地构建 dist，VPS 只做静态托管</strong>，nginx 伺候。</p>
<p>还有个玄学坑：删掉 <code>src/content/posts/</code> 下的 md 文件后重新构建，dist 里居然还有已删除文章的残留——Astro 的 content 层缓存在 <code>node_modules/.astro</code> 里没失效。删文件后构建前先 <code>rm -rf node_modules/.astro</code>，百试百灵。</p>
<h2>样式：3px 黑边框的执念</h2>
<p>看中了某个站长的方框质感，卡片统一改成 <code>3px solid #1c1c1c</code> 粗黑边框，hue 调到 174 的青绿色。favicon 换成双猫图，深浅色自动切换——最骚的是把主题里所有旧 favicon 文件名的内容全都替换成新图，防止任何回退路径冒出旧图标。别问，问就是被浏览器缓存坑过。</p>
<p>页脚加了萌 ICP 备案和实时运行时间计数器。侧栏的建站时长一开始显示 653 天，原因是 <code>siteStartDate</code> 写着 2025-01-01，改成今天，世界清净了。</p>
<h2>音乐：下载站的攻防战</h2>
<p>站内播放器加了三首歌。下载的时候发现下载站耍花招："下载"按钮实际是打开新标签页播放，根本不触发文件下载。绕过去的办法是让它暴露音频直链，然后 <code>curl</code> 直接抓——网易云的签名 URL 有效期大概一小时，手要快。</p>
<p>更绝的是这站现在加了"口令解锁"，要拿快手极速版扫码。行吧，以后再下歌就手动过。</p>
<h2>Live2D：从五个到一个</h2>
<p>主角色雪初音常驻，旁边最多的时候摆了五个小伙伴：白猫 tororo、金发 z16、chitose、shizuku、wanko。中间还闹过笑话——把西装男 chitose 认成 z16 删错了，又换回来。</p>
<p>技术上有个坑：<code>l2d-widget</code> 的根节点是个没有 class 的 <code>position: fixed</code> div，没法用常规选择器定位。最后用的办法是记录组件创建前后的 DOM 差集，找到带 canvas 的 fixed div 来定位每个小伙伴。</p>
<p>最后还是决定做减法：只留金发 z16 一个站在右下角，和主角色左右对称。五个确实太吵了。</p>
<h2>项目页与书签：从占位到自家东西</h2>
<p>主题自带的"Firefly 主题模版"和"示例项目"两个占位直接删掉，换上自己的五个：Folia、Komari Monitor、哪吒管理面板、Cloud Mail、IP 检测工具，每个都配了主页截图。Komari 的介绍里专门写了后台可视化和 WebSSH——电脑没电的时候，手机平板开网页就能 SSH 连服务器，这体验谁用谁知道。</p>
<p>书签导航加了"论坛"分组（Linux Do、NodeSeek、NodeLoc、奶昔论坛），工具分组塞了硬核指南，图标一个不少。</p>
<h2>部署：一键脚本</h2>
<p>写了个 <code>deploy.sh</code>，做几件事：装 nginx、删 Debian 默认站点、解压 dist、修权限防 403、监听 80 和 8880（高位端口方便直连预览）。VPS 上跑一遍，完事。</p>
<p>一天下来发了 22 个版本，博客算是彻底换了个样子。剩下的就是慢慢写文章了。</p>
]]></content:encoded></item><item><title>b站2233中银联名万事达卡和招行b站联名纯白花嫁卡拿下</title><link>https://idea.lanerc.me/posts/bilibilicard/bilibili-cards/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/bilibilicard/bilibili-cards/</guid><description>两周前拿了招行万事达借记卡，昨天又拿下这很美的一对卡啊</description><pubDate>Wed, 14 Oct 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>文章内容</h1>
<p>先交代一下背景：上周收到短信说卡到网点了，我兴冲冲杀过去，结果——没带身份证。
<img src="https://idea.lanerc.me/_astro/4.D9m2HSNu_2z36x.webp" alt="到银行网点取卡当天的照片" loading="lazy" />
柜员小姐姐保持着职业微笑：「先生，没有身份证我们没办法给您发卡。」再一看表，支行 16:30 关门。我站在门口，像个没交作业被赶出教室的小学生。</p>
<p>很巧的是晚上招行的联名花嫁卡也下来了，五天真是神速啊，正好顺手一起拿
<img src="https://idea.lanerc.me/_astro/2.CjTi0rqT_ZUFEnk.webp" alt="招行 × b 站花嫁卡到手时的照片" loading="lazy" /></p>
<p>一天后，也就是昨天，身份证揣兜里揣得死死的，趁中午短休时间，两张卡，一次拿下！</p>
<h2>第一张：中银 × b 站万事达 —— 干活的卡</h2>
<p>这张是冲着「海外支付」去的。万事达通道，境外网站、各种订阅扣款就靠它了。</p>
<p>说实话，办它的理由特别务实：VPS 续费、域名续费、时不时冒出来的境外小额订阅，以前总要绕来绕去。现在一张万事达在手，全球 200 多个国家和地区的商户都能刷，省心。</p>
<p>卡面是 b 站联名设计，低调里带点二次元味，不会太社死，拿得出手。
<img src="https://idea.lanerc.me/_astro/1.kMljZl4g_2o0eHX.webp" alt="b 站联名卡卡面特写" loading="lazy" /></p>
<h2>第二张：招行 × b 站纯白花嫁 —— 好看的卡</h2>
<p>如果说中银那张是干活的，这张就是纯粹的颜值消费。</p>
<p>纯白卡面，2233 娘的花嫁装，拿到手第一反应是：这哪是银行卡，这是收藏品。白色卡身干干净净，阳光下看还有点质感，刷卡的时候掏出来，收银员都得多看两眼。</p>
<p>至于权益？不重要。好看，就是它最大的权益。</p>
<h2>总结</h2>
<p>一对卡，一个负责征战海外，一个负责貌美如花，分工明确，配合默契。</p>
<p>唯一的问题是：卡是拿下了，额度是银行的，账单可是我的。。。</p>
<h2>补充：</h2>
<p>招商银行的服务质量确实好啊，两次拿卡都非常的丝滑流畅</p>
<p><img src="https://idea.lanerc.me/_astro/3.DlkPcU20_ZAic0J.webp" alt="招行网点取卡过程的照片" loading="lazy" /></p>
]]></content:encoded></item><item><title>GitHub 账号未满足Linux do入社资质，如何申请年轻版资质？——从失落 to 惊喜：GitHub 未满5年，我还是拿到了 LINUX DO 的门票</title><link>https://idea.lanerc.me/posts/linux-do/sign-in-for-linux-do/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/linux-do/sign-in-for-linux-do/</guid><description>文章描述</description><pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>文章内容</h1>
<p>一直听说 LINUX DO 是个技术氛围很好的地方，最近便想着去注册一个账号看看。</p>
<p>结果去了解了一下申请规则，心凉了半截——常规申请要求 GitHub 账号注册满 5 年。看了看自己那个才建了两年多的 GitHub 主页，只能默默关掉页面。当时确实有点失落，感觉硬性门槛就把自己挡在门外了。</p>
<p>后来不甘心又去翻论坛的帖子，发现社区其实还有个<a href="https://pre.anglergap.org/zh/dashboard/pre-application">预申请系统 | 预申请系统</a>，也就是大家俗称的“年轻版”，专门给 GitHub 年限不够的用户准备的通道。于是抱着试一试的心态，认真填写了申请，之后就进入了等待。</p>
<p>这里想给想申请的小白朋友一个建议就是认真写明自己是从哪来，想要来这个社区做什么事情即可，感情真挚管理员一般会通过的。
<img src="https://idea.lanerc.me/_astro/4.DjwWwmxb_Z1X4Jm8.webp" alt="预申请通过信件" loading="lazy" /></p>
<p>今天晚上，手机突然弹出 QQ 邮箱的提醒。点开一看，是来自 <code>noreply</code> 的邮件：</p>
<blockquote>
<p>✓ 审核通过 🎉 预申请已通过 恭喜！你的预申请已通过审核，请根据指导意见完成...
<img src="https://idea.lanerc.me/_astro/2.BHi5wMZm_Z1RTmFS.webp" alt="QQ邮箱提醒截图" loading="lazy" />
看到“审核通过”那几个字的时候，心里还是挺高兴的。连忙按照邮件里的指引完成了注册流程。</p>
</blockquote>
<h2>新手教程与年轻版的限制</h2>
<p>进站第一件事当然是过新手教程。跟着流程走完，收到了 <code>@discobot</code> 的消息，还发了一张专属的证书。
<img src="https://idea.lanerc.me/_astro/1.amnEv-m-_2lAm63.webp" alt="证书" loading="lazy" /></p>
<p>不过，申请通过是一回事，年轻版的限制确实是存在的。在论坛里逛了逛才发现，因为走的是预申请通道，账号在初期有很多权限受限。比如一些热门板块（像“资源荟萃”之类的）可能进不去，或者只能看不能回，另外信任等级的提升也会比较慢。</p>
<p>其实这也完全能理解，毕竟社区要控制质量，防范小号和水军。对我这种 GitHub 年限不够的人来说，能有个“先上车”的机会已经很感激了。</p>
<p>接下来的日子，大概率就是老老实实潜水，多看看大佬们的开发调优帖。遵守社区规则，慢慢攒信任等级。</p>
<p><strong>能进来就好。Hello, LINUX DO。</strong></p>
<p><img src="https://idea.lanerc.me/_astro/3.Brme1KTo_Z26PqLh.webp" alt="Hello" loading="lazy" /></p>
]]></content:encoded></item><item><title>申请了第一张海外借记卡（不过遗憾的是是张海外虚拟u卡）</title><link>https://idea.lanerc.me/posts/bybit-card/bybit-card/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/bybit-card/bybit-card/</guid><description>简单记录一下自己申请bybit卡的过程和成功绑定微信支付宝还有Google play商店的经历，不过我还没有买币，可能只能薅一些免费的羊毛。</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>申请注册过程</h1>
<ul>
<li>我本人是在YouTube上根据博主：Porter科技迷 的视频一步步做的，我本人使用的是身份证进行的KYC认证，后续如果有小伙伴想要买币有疑问的尽管去学习博主的视频，非常高质。</li>
<li>视频网址是：<a href="https://www.youtube.com/watch?v=DjMRuKxsqyE&amp;t=531s">【最强U卡】Bybit Card格鲁吉亚卡｜支持订阅GPT｜支持微信、支付宝、Apple Pay等｜中国大陆身份免费申请｜0门槛线上开卡 | 新客福利拉满 | 从申请Bybit交易所到入金充值全过程</a></li>
</ul>
<h2>核心区别</h2>
<p><strong>视频发布时可能还不支持绑定微信支付宝还有apple pay以及Google play商店，但是主包目前实测是可以的，感兴趣的小伙伴可以去尝试一下</strong>！</p>
<p><strong>PS:绑定的过程均不需要挂代理哦</strong></p>
]]></content:encoded></item><item><title>eSIM.gg 小白卡 + EasyEUICC 写卡与收短信排查全记录(成功下岸版)</title><link>https://idea.lanerc.me/posts/esim-gg-easyeuicc/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/esim-gg-easyeuicc/</guid><description>主包人胆大，不提前搜索攻略就买了这张号码，收不到短信了于是上网浏览了一下才发现很多人买的加0欧的收不到消息，也有很多人说买那种加0.几欧的可以收到，这个具体什么原理我也不清楚，主播买的号段是5704段0欧的，然后过了两天就可以收到验证码了，前前后后一共花费了44RMB，保号现在政策能保到6-7年，也是非常有性价比啊。</description><pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>eSIM.gg 小白卡 + EasyEUICC 写卡与收短信排查全记录(成功下岸版)</h1>
<p>**申请网址为：<a href="https://esim.gg/new/number/estonia">爱沙尼亚乌龟卡eSIM申请及写入过程</a></p>
<h2>背景</h2>
<p>用 EasyEUICC 把 eSIM 写入小白卡，写卡成功后却收不到短信，折腾了一圈终于搞定。把过程整理出来，供后来人参考。</p>
<ul>
<li>上网浏览了一下很多人买的加0欧的收不到消息，这个具体什么原理我也不清楚，主播买的号段是5704段0欧的，前前后后一共花费了44RMB，保号现在政策能保到6-7年，也是非常有性价比啊。*</li>
<li>第一次入坑的小白浏览网页经常遇到类似这样的评论，大家不要慌啊，我也是被这些搞得破崩了，放弃的两天后试试结果成了，关键在于等待吧。*</li>
</ul>
<hr />
<h2>一、写卡流程（Android）</h2>
<ol>
<li>小白卡插入安卓手机卡槽。</li>
<li>打开 EasyEUICC → 右上角菜单 → <strong>兼容性检查</strong>，通过后重启 App。</li>
<li>右下角 <strong>“+”</strong> → 选择’二维码写入‘，“手动输入”或“从剪贴板读取”。</li>
<li>粘贴 <strong><code>LPA:1$...</code></strong> 格式激活码。</li>
<li>写入完成后，点卡片菜单 → <strong>启用</strong>，等待信号出现。</li>
</ol>
<p><strong>注意：</strong></p>
<ul>
<li>激活码必须以 <code>LPA:1$</code> 开头。</li>
<li>EasyEUICC 只能操作小白卡，管不了手机自带 eSIM。</li>
<li>写卡后建议先关闭数据漫游。</li>
</ul>
<h2>以下内容来自<a href="https://linux.do/">Linux do社区</a>
<img src="https://idea.lanerc.me/posts/esim-gg-easyeuicc/4.png" alt="Linux do 社区相关讨论截图" loading="lazy" /></h2>
<h2>二、有信号但收不到短信？</h2>
<h3>1. 先确认信号</h3>
<ul>
<li>看状态栏是否有 <strong>“R”</strong> 和 4G/5G。</li>
<li>完全无信号 → 可能是运营商限制，联系卖家。</li>
</ul>
<ul>
<li>成功标志可以看屏幕左上栏：
<img src="https://idea.lanerc.me/posts/esim-gg-easyeuicc/2.jpg" alt="写卡成功后屏幕左上角的状态显示" loading="lazy" /></li>
</ul>
<h3>2. 检查短信中心号码（SMSC）</h3>
<ul>
<li>路径：<code>设置 → 关于手机 → SIM卡状态 → 短信中心号码</code></li>
<li>常见正确值示例：<strong><code>+37256100020</code></strong></li>
<li>保持默认也可以</li>
<li>号码错误会导致短信收发全废。</li>
</ul>
<h3>3. 检查拦截与默认卡</h3>
<ul>
<li>短信 App 的“拦截记录/垃圾箱”翻一翻。</li>
<li><code>设置 → 移动网络 → SIM卡管理</code>，默认短信卡切到小白卡。</li>
</ul>
<h3>4. 手动选网</h3>
<ul>
<li>关闭“自动选择”，手动搜索运营商，选信号最好的，重启手机。</li>
</ul>
<h3>5. 平台风控（重点）</h3>
<ul>
<li>官网测试短信能收到，但小红书/Telegram/Google 等收不到。</li>
<li>原因：平台对境外号段、虚拟运营商号有风控，<strong>从源头不下发</strong>。</li>
<li>平台提示“需要 1–2 天设置”是风控观察期，如果只能收到卖家发来的短信其他的收不到的话，建议等满 24 小时再试，别频繁点。</li>
<li>换干净节点有时也有帮助。</li>
</ul>
<h3>6. 主播心路历程</h3>
<p>这里也是成功了，最后也是松了一口气，按照之前的过程操作之后，给大家展示一下成果：
<img src="https://idea.lanerc.me/posts/esim-gg-easyeuicc/1.jpeg" alt="eSIM 号码写入成功后的应用界面" loading="lazy" />
然后主包这里也尝试注册了一下WhatsApp，也成功了：
<img src="https://idea.lanerc.me/posts/esim-gg-easyeuicc/3.jpg" alt="用该号码注册 WhatsApp 成功的界面" loading="lazy" /></p>
<hr />
<h2>三、移动数据与漫游</h2>
<ul>
<li>移动数据总开关关闭时，即使有信号也可能收不到短信。</li>
<li>打开数据，默认上网卡选小白卡。</li>
<li><strong>但要注意流量费</strong>：余额低于 0.1 欧会直接断网，国内建议切回国内卡上网，小白卡只收短信。</li>
<li>显示“无法识别号码”是正常现象（未写入 MSISDN），不影响收发短信。</li>
</ul>
<hr />
<h2>四、误删 Profile 昵称怎么办</h2>
<ul>
<li>只是删昵称：EasyEUICC 里信息还在，不影响使用。</li>
<li>可在 EasyEUICC 菜单里 <strong>重命名/编辑</strong> 改回来。</li>
<li>确认 Profile 状态是 <strong>“已启用”</strong>。</li>
<li><code>设置 → 移动网络 → SIM卡管理</code> 里确认开关打开，重启手机试试。</li>
<li>真正删除 Profile 后旧激活码会失效，需联系客服重新发码。</li>
</ul>
<hr />
<h2>五、iOS 能用 EasyEUICC 吗？</h2>
<p><strong>不能。EasyEUICC 没有 iOS 版。</strong></p>
<p>替代方案：</p>
<ol>
<li><strong>纯 iPhone</strong>：买 USB-C 读卡器或蓝牙 eLPA 读卡器，配合 <strong>9eSIM LPA</strong> 或 <strong>NekokoLPA</strong> App 使用。</li>
<li><strong>安卓写卡 + iPhone 用卡</strong>：用安卓机写好，拔卡插进 iPhone，通过 <strong>STK 菜单</strong>切号。</li>
</ol>
<p><strong>建议</strong>：有安卓备用机的话，第二种最省事。</p>
<hr />
<h2>总结</h2>
<ul>
<li>写卡不难，难在收短信。</li>
<li>优先查：信号 → SMSC → 拦截 → 平台风控。</li>
<li>“无法识别号码”别慌，不影响用。</li>
<li>余额别低于 0.1 欧。</li>
</ul>
]]></content:encoded></item><item><title>《剪灯新话》------谈《牡丹灯记》里的爱情</title><link>https://idea.lanerc.me/posts/novel/type-of-classical-novel/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/novel/type-of-classical-novel/</guid><description>《剪灯新话》中的《牡丹灯记》讲述了一段人鬼相恋的悲剧。书生乔生与女鬼符丽卿相爱，但乔生因恐惧而退缩，最终导致悲剧结局。文章分析了符丽卿的真诚与乔生的懦弱，并以此反思现实爱情中的勇气与坚持。或许真爱应超越身份和世俗偏见，珍惜眼前人，避免因犹豫而留下遗憾。在感情中需要勇敢面对压力，守护真心。</description><pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>《剪灯新话》------谈《牡丹灯记》里的爱情</h1>
<p>姓名：zhz 学号：06024436</p>
<p>课堂上听完老师解说的《牡丹灯记》之后，我的脑子里一直在盘旋着一个问题：如果你深爱的那个人，有一天你发现她不是人，而是鬼，你还会继续爱下去吗？这个问题看似荒诞，又像是只能出现在志怪小说里的情节，但实际上它问得很现实------我们对感情的坚持到底有多强，当遇到外界压力时，我们真的能守住自己的心吗？</p>
<p>《牡丹灯记》讲述的是书生乔生与女鬼符丽卿之间跨越 "生死鸿沟" 的爱情悲剧。元宵夜邂逅后，符丽卿每晚都会在丫鬟金莲的牡丹灯引路下，来到乔生的书房与他相会。两人朝夕相伴，情意渐浓，宛如寻常恋人般亲密无间。然而，随着乔生日渐憔悴，他在尾随符丽卿时意外发现真相------她原是已故奉化州判之女的魂魄，日夜相伴的不过是一段人鬼殊途的情缘。得知真相后，乔生满心恐惧，虽并未在他人劝说下动摇，但是主动求助了道士。道士赠予他一道符咒，乔生按法安置后，符丽卿便再未出现，两人以这种被动隔绝的方式结束了相处。遗憾的是，乔生后来醉酒忘形，违背道士的告诫重走相遇之路，再次遭遇符丽卿。最终，他被符丽卿拉入棺中同葬，这段跨越阴阳的爱情，终究以两人生死相随的悲剧落幕。</p>
<p>我第一次听到这个故事时，最触动我的，是符丽卿的真心。她虽然是鬼，可她对乔生的情感却比很多活人都要纯粹。没有功利、没有目的，她的出现只是因为喜欢，只是因为想陪伴他。符丽卿拥有的，是一种 "想爱却没有资格爱" 的悲哀------人鬼殊途的宿命早已注定了她的情感没有归途，她的真挚反而在乔生的犹豫面前，更显得珍贵。</p>
<p>乔生作为活生生的人，却在关键时刻暴露了懦弱的本质。最初，他以为符丽卿是普通孤女，两人的相处建立在纯粹的信任与喜欢之上，情意日渐深厚。可当他亲自尾随，亲眼目睹符丽卿进入湖心寺的棺材，才惊觉自己日夜相伴的竟是鬼魂------这一真相如晴天霹雳，瞬间击垮了他的勇气。随后，邻人告知曾窥见她是粉骷髅的惊悚事实，更让他恐惧加深。此时道士、邻人的告诫，不再是凭空而来的劝告，而是恰好击中了他内心的恐惧，成为压垮他的最后一根稻草。他不再念及过往情分，只想逃离这份跨越阴阳的危险，最终主动求助道士，用符咒将符丽卿被动隔绝。这份因恐惧而生的退缩，终究辜负了那段纯粹的陪伴。</p>
<p>读到这里，我忍不住想：究竟是谁更"像人"？谁更"像鬼"？</p>
<p>符丽卿虽然是鬼，但她善良、温柔、真诚，最初并无害人之心，始终以纯粹的情感陪伴乔生。乔生虽然是人，却在外界压力下抛弃了承诺与感情。故事通过这样鲜明的对比，让"鬼"与"人"的边界变得模糊，也让我们意识到：决定一个人是否值得爱的，不是身份，而是心。</p>
<p>放到现实里，这种情况其实一点也不陌生。现在虽然社会比过去开放了很多，但爱情依然会被各种声音干扰------父母反对、经济差距、社会观点、朋友劝告......许多原本坚固的感情，常常就是在这些看似"为你好"的话语中被动摇的。乔生的经历，可能就是现实里许多人的影子。</p>
<p>有时候我会想，如果乔生多一点直面真相的勇气，多一点坚持，是不是就能改变结局？也许符丽卿不会被赶走，也许他们真的能跨越生死，在一起一段时间。哪怕最终没有圆满，至少也不会像故事中那样留下如此深的遗憾。</p>
<p>符丽卿这个角色让我特别心疼。她在生前可能没体验过幸福，死后好不容易遇到乔生这样对她好的男子，却因为自己无法改变的"鬼"的身份被拒绝。她既不能解释，也不能反抗，只能默默接受这一切。这个形象其实带着浓厚的悲剧性，让人感受到一种无奈的爱情宿命------她的身份成了她最无法摆脱的枷锁。</p>
<p>这让我想到现实中被"标签化"的人。有人因为家境普通、因为长相一般、因为学历不高，就被外界轻易否定，连恋爱的资格都好像被剥夺了。但这些外在的条件，真的能决定一个人值得不值得被爱吗？在我看来，完全不能。爱一个人应该是因为她的心，而不是她的条件。</p>
<p>乔生的性格其实很典型。他在感情中有真心，却缺乏担当；有喜欢，却不够坚定；有勇气开始，却没有勇气继续。他的失败并不是因为不爱，而是因为他不敢为爱承担后果。这种"懂得爱，却不会爱"的无力感，在故事的结尾被放大到了极致。</p>
<p>在我看来，《牡丹灯记》不仅是一段人鬼恋，更是一面镜子。它照出了一个人的善良、胆怯、自私、犹豫，也让我们看到外界压力对爱情的破坏力。乔生的故事让我明白一个道理：当你没有勇气保护你爱的人时，你就是在亲手失去她。</p>
<p>故事的结局是悲伤的：本来相互喜欢的人，最终却被命运或人的软弱拆散。在我看来，乔生接受符咒隔绝符丽卿后，并未立刻醒悟这份感情的珍贵，直到一次醉酒忘形，违背道士的告诫重走相遇之路，才再次与符丽卿重逢。此时的他已无退路，最终被拉入棺中同葬。他或许到最后才明白，自己当初因恐惧放弃的，是多么纯粹的真心 ------可这份醒悟来得太晚，连挽回的机会都没有，只留下无法弥补的遗憾。</p>
<p>这种后悔也没用的结局，让我联想到现实中无数错过的爱情。很多人都是在失去后才意识到自己真正想要什么。可是感情从来不等人，错过了，就是错过了。</p>
<p>听完故事，我对瞿佑也有了新的理解。在明初那样保守的社会背景下，他敢写人鬼相恋，并且让读者对这段感情产生同情、产生共鸣，这确实很有突破性。他借"鬼怪"包装爱情，其实是为了更自由地表达自己的观点：真正的感情不该被身份和世俗束缚。</p>
<p>虽然故事里有驱鬼、术法等迷信元素，但这些只是噱头，真正的核心，是对爱情和人性的探讨。在那个时代，作者可能只能通过志怪的方式来暗示自己对封建束缚的不满，对真挚爱情的珍惜。</p>
<p>听完《牡丹灯记》，我也忍不住设想：如果我是乔生，我能不能坚持下去？面对所有人都说"这是危险的"的情况，我有没有勇气坚定地站在恋人这边？坦白说，我也不敢确定。但我知道，如果一个人连在关键时刻保护爱人的勇气都没有，那么这份感情就不够稳固，也经不起考验。</p>
<p>符丽卿给人的感受，是一个既温柔又孤独的灵魂，她的爱真诚到让人心酸。作者在描写她的时候，用了很多细腻的细节，让她的形象鲜活而可怜，让读者不自觉地站在她那边。可以说，她的存在是对"爱需要勇气"这句话最深刻的诠释。</p>
<p>从这个故事里可以看到，无论古今，人对感情的渴望都是相似的。人们希望被选择、被理解、被珍惜，也希望能和心爱的人在一起。古代的障碍是封建礼教，现代的是现实压力；障碍变了，可感情的阻力却并没有减少。</p>
<p>《牡丹灯记》给我最大的启示就是：珍惜眼前人，别让犹豫和恐惧毁掉一段真心。人鬼殊途的宿命或许难以抗衡，但选择能决定是否留下遗憾。如果你确定一个人值得你爱，那就勇敢一些，坚持一下------哪怕有外界压力，有现实困难，也至少为这份真心拼尽全力。就算结局不尽人意，你曾努力过、珍惜过，也不会像乔生那样，直到彻底失去才懂悔恨，最终留下终身无法弥补的遗憾。</p>
<p>总结来说，《剪灯新话》写的是鬼怪，讲的却是人心。瞿佑用奇幻的外壳，说的是真实的情感和人性的弱点。他赞美真挚的感情，也批判那些束缚人的旧规矩。他让读者意识到：身份、背景、世俗眼光，都不应该成为阻挡真爱的理由。</p>
<p>读完这篇小说后，我对爱情也有了更深的体会：爱一个人，不应该看她的身份、条件，而应该看她对你的心意和你们之间的感受。希望我们都能像符丽卿那样真诚地去爱，也希望我们在面对感情时，能比乔生更勇敢一点，不要让本该珍惜的人成为遗憾。</p>
]]></content:encoded></item><item><title>音乐鉴赏--在聆听中理解音乐的力量</title><link>https://idea.lanerc.me/posts/music-appreciation/idea/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/music-appreciation/idea/</guid><description>本文记录了我在音乐鉴赏课程中的学习体会，从单纯“听歌”到深入“理解”音乐的转变。通过分析爵士、古典、摇滚等不同风格，探讨音乐作为情感载体与文化桥梁的力量。真正的音乐欣赏需要理解其背后的文化与情感，这样才能帮助我们更好地认识自我与世界。</description><pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>在聆听中理解音乐的力量</h1>
<p>在本学期的音乐鉴赏课程中，我第一次系统而完整地接触到从古典到现代、从西方到东方的多种音乐形式。过去我对音乐的理解更多停留在日常听歌的层面，而这门课却让我发现：音乐从来不只是旋律的组合，更是文化的载体、情感的表达、思想的呈现、以及人与世界沟通的方式。特别是在观看了课程推荐的相关音乐作品与演出片段后，我对音乐的思考有了新的提升，也渐渐明白了"欣赏"与"聆听"的区别。</p>
<h2>一、从聆听到理解：音乐不只是"好听"</h2>
<p>课程初期，老师让我们接触爵士乐的经典作品。起初我会觉得这些音乐对我有些 "遥远"：节奏又复杂又特别，好多地方都和平时听的流行歌不一样，还有不少即兴的部分，一开始根本跟不上思路，旋律和伴奏的搭配也不像流行歌那么好懂。然而随着课堂的引导，我慢慢学会从节奏特点、演奏方式、音乐背后的故事这些方面去感受爵士乐。我逐渐意识到，爵士乐看似自由随性的表达背后，其实藏着演奏者的用心和真实情绪；它之所以能流传这么久，不仅仅是因为风格独特，更因为里面满是对生活的热爱，能让不同的人都感受到共鸣。音乐鉴赏这门课程教会我的第一个重要收获，就是要带着"理解"去听音乐，而不是只判断"好听或不好听"。</p>
<h2>二、音乐与情感的联系：从古典到现代的体验</h2>
<p>课程中让我印象最深的，是老师分享的指挥家提奥多库伦奇斯的演出视频。视频中的演奏方式极富张力，他把古典作品诠释得极具情绪冲击力。我过去以为古典音乐应该是"端庄、安静"的，但库伦奇斯的指挥让我第一次看到音乐可以如此狂放、激烈、甚至带着冲突感。他的诠释突破了我对古典音乐的固有印象，让我明白古典并不是"老"或"过时"，而是一种永远可以被重新理解的艺术。</p>
<p>这种体验也让我回头再听一些现代音乐作品，例如课程中推荐的大卫·吉尔摩演唱会视频。吉尔摩的音乐虽然属于摇滚范畴，但他的吉他音色有一种独特的"叙事感"，每一次的演奏都像在讲述心中最柔软的故事。他的音乐没有古典作品那样复杂的结构，却有极强的情绪力量。同样是"表达情感"，摇滚则更直接、更像发自内心的呐喊。</p>
<p>在这段时间的聆听后，我第一次意识到：不同风格的音乐并不是彼此割裂，而是共同构成了我们的情感谱系。音乐的形式虽有不同，但其目的都是表达情感，触动灵魂。</p>
<h2>三、音乐与时代：理解作品背后的文化与交叉</h2>
<p>课堂上我还了解到了音乐与文化的关系。在听完"传统古琴意向与跨文化创作" 的讲座后，我对音乐和时代、文化的联系有了新感受。古代文人抒发情感常借助于传统古琴，古琴充满了古典文化的韵味。而现今成红雨老师把古琴和德国音乐制作结合，海纳・格兰钦老师将爵士钢琴与古琴创意融合，这就说明音乐不是孤立的，它跟着时代发展、文化碰撞在不断变化。</p>
<p>这让我明白，想要真正感受音乐，得看看它背后的文化。就像古琴在古代是一种意境，现在和外国音乐风格碰撞后，又有了不一样的感觉。每一段琴音、每一种旋律组合，其实都藏着当时人们的生活态度、文化想法。所以音乐就像个 "文化桥梁"，既能带我们回溯传统，又能让我们看到不同文化交融出的新火花。</p>
<h2>四、个人感悟：音乐的最终指向</h2>
<p>通过本学期的学习，我逐渐意识到一个最重要的观点：音乐终究是关于我们自己。无论是古典作品，还是摇滚音乐，它们之所以能被一代又一代的人欣赏，是因为音乐承载了人的情感、命运、困惑、追问与期待。</p>
<p>在欣赏库伦奇斯的指挥时，我感受到的是一种突破与澎湃；在聆听吉尔摩的吉他独奏时，又体会到一种孤独与温柔并存的情绪。不同的音乐让我在不同的瞬间看见了自己，看见了内心那些难以表达的部分。</p>
<p>音乐鉴赏课程给我的最大收获，并不是让我记住多少作曲家或时期，而是让我明白：音乐真正的力量，是帮助我们更好地理解情感、理解世界、理解自己。</p>
<h2>五、结语</h2>
<p>这门课不仅拓宽了我对音乐的认知，更改变了我聆听音乐的方式。让我学会了带着思考去听、带着理解去感受，也开始愿意探索更多种类的音乐。未来我会继续保持这种开放的心态，因为音乐本身就是一个永远没有尽头的世界。</p>
]]></content:encoded></item><item><title>电路实验-应用Multisim软件工具设计电路验证网络定理</title><link>https://idea.lanerc.me/posts/experiment-of-circuit/circuit/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/experiment-of-circuit/circuit/</guid><description>今天给大家带来最近的电路实验，因为此次电路实验是全部自己在电脑仿真软件Multisim上做的，而且是按照老师给的模板填写的实验报告，所以很少有地方能体现自己的实验过程，给大家一个参考，同时我也记录一下自己的报告。</description><pubDate>Sun, 16 Nov 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>东南大学电工电子实验中心</h1>
<h2>实 验 报 告</h2>
<h3>课程名称： <u>电路实验</u></h3>
<h3>第 2 次实验</h3>
<h4>实验名称：<u>应用Multisim软件工具设计电路验证网络定理</u></h4>
<p>院 （系）：电子科学与工程学院 专业：电子科学与技术</p>
<p>姓 名： <u>zhz</u> 学 号： <u>06024436</u></p>
<p>实 验 室: <u>403室</u> 实验组别：</p>
<p>同组人员： 实验时间：<u>2025年11 月14日</u></p>
<p>评定成绩： 审阅教师：xxx</p>
<hr />
<h3>一、实验目的</h3>
<p>（1）通过实验加深对参考方向、基尔霍夫定理、叠加定理、戴维南定理的理解；
（2）Multisim 软件入门：元器件配置、电路连接、电路参数测试；
（3）通过学习对实验结果的分析对比，了解虚拟仿真与实物实验的差异。</p>
<hr />
<h3>二、实验原理</h3>
<ol>
<li><p>基尔霍夫定理：</p>
<ul>
<li>电流定理（KCL）:任意时刻，流进和流出电路中节点的电流的代数和等于零。</li>
<li>电压定理（KVL）:在任何一个闭合回路中，所有的电压升或降之和等于零。</li>
</ul>
</li>
<li><p>叠加定理：</p>
<ul>
<li>在线性电路中，任一支路的电流或电压等于电路中每一个独立源单独作用时在该支路所产生的电流或电压的代数和。</li>
</ul>
</li>
<li><p>戴维南定理：</p>
<ul>
<li>任何复杂的线性有源一端口网络都可以用一个电压源和一个等效电阻的串联来等效。电压源的电压端口的开路电压，而电阻等于端口的全部独立电源置零后的输入电阻。</li>
</ul>
</li>
<li><p>二极管特性：</p>
<ul>
<li>二极管的主要特性：单向导电性。当阳极电压高于阴极时电流通过，二极管导通；当阴极电压高于阳极时电流截止。</li>
<li>伏安特性：正向呈指数上升反向几乎为零，直到击穿点。</li>
</ul>
</li>
</ol>
<hr />
<h3>三、实验内容</h3>
<h4>1、基尔霍夫定理、叠加定理的验证</h4>
<h5>（1）按图1所示实验电路建立电路。用电压表和电流表测量各电阻两端电压和各支路电流。分析说明测量结果。</h5>
<p><img src="https://idea.lanerc.me/_astro/1.BMfP3Vny_mPAy0.webp" alt="图一实验电路" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/2._GjrqJgm_Wno7i.webp" alt="E1,E2同时作用仿真电路" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/3.CNv0hrbi_2rO7Oy.webp" alt="E1单独作用" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/4.BEVoRwnZ_1k8GiR.webp" alt="E2单独作用" loading="lazy" /></p>
<p><strong>表1 测量数据</strong></p>
<table>
<thead>
<tr>
<th>状态</th>
<th>U1（V）</th>
<th>U2（V）</th>
<th>U3（V）</th>
<th>I1（A）</th>
<th>I2（A）</th>
<th>I3（A）</th>
</tr>
</thead>
<tbody><tr>
<td>E1、E2同时作用</td>
<td>3.604</td>
<td>-1.618</td>
<td>6.357</td>
<td>0.018</td>
<td>3.173m</td>
<td>0.021</td>
</tr>
<tr>
<td>E1单独作用</td>
<td>5.123</td>
<td>4.842</td>
<td>4.836</td>
<td>0.026</td>
<td>-9.495m</td>
<td>0.016</td>
</tr>
<tr>
<td>E2单独作用</td>
<td>-1.519</td>
<td>-6.461</td>
<td>1.522</td>
<td>-7.596m</td>
<td>0.013</td>
<td>5.072m</td>
</tr>
<tr>
<td>叠加计算结果</td>
<td>3.604</td>
<td>-1.619</td>
<td>6.358</td>
<td>0.018</td>
<td>3.505m</td>
<td>0.021</td>
</tr>
</tbody></table>
<p><strong>实验结果分析：</strong></p>
<p>实验电路中因电流表电压表内阻的微小影响产生了微小的误差，三个仿真电路中KCL和KVL均成立，各条支路的叠加电压电流测量结果基本符合叠加定理，验证了叠加定理。</p>
<h5>（2）将300Ω电阻改成1N4009的二极管（正极连接到A点上），自行建立表格，记录测量数据，计算测量结果并分析说明。</h5>
<p><img src="https://idea.lanerc.me/_astro/5.CrHfXnRT_128m33.webp" alt="E1,E2同时作用仿真电路" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/6.9XvW8mfT_ZqDxGk.webp" alt="E1作用仿真电路" loading="lazy" />
<img src="https://idea.lanerc.me/_astro/7.8UoXMai9_1ExpYd.webp" alt="E2作用仿真电路" loading="lazy" /></p>
<p><strong>表2 测量数据</strong></p>
<table>
<thead>
<tr>
<th>状态</th>
<th>U1（V）</th>
<th>U2（V）</th>
<th>U3（V）</th>
<th>I1（A）</th>
<th>I2（A）</th>
<th>I3（A）</th>
</tr>
</thead>
<tbody><tr>
<td>E1、E2同时作用</td>
<td>8.962</td>
<td>-6.993</td>
<td>0.935</td>
<td>0.045</td>
<td>0.014</td>
<td>0.059</td>
</tr>
<tr>
<td>E1单独作用</td>
<td>9.044</td>
<td>0.909</td>
<td>0.867</td>
<td>0.045</td>
<td>-1.781m</td>
<td>0.043</td>
</tr>
<tr>
<td>E2单独作用</td>
<td>-0.707</td>
<td>-7.275</td>
<td>0.700</td>
<td>-3.535m</td>
<td>0.014</td>
<td>0.011</td>
</tr>
<tr>
<td>叠加计算结果</td>
<td>8.337</td>
<td>-6.366</td>
<td>1.567</td>
<td>0.041</td>
<td>0.012</td>
<td>0.054</td>
</tr>
</tbody></table>
<p><strong>实验结果分析：</strong></p>
<p>本实验在将R3更换为二极管后，在三个仿真电路中，各节点电压、电流符合基尔霍夫定律；叠加计算值与实际同时加电结果数值上误差保持在7%左右，U3的数值误差较大。二极管属于非线性元件，理论上叠加定理不成立，本实验中其在三种情况下均保持正向导通，使电路较好的拟合为线性电路，因此在本实验中数值上叠加定理基本成立。</p>
<h4>2、设计电路，验证戴维南定理</h4>
<h5>（1）开路电压测量仿真电路</h5>
<p>断开R3, 测量A、B端口电压为开路电压Uoc：
<img src="https://idea.lanerc.me/_astro/8.Bynby-XJ_Z1LvhIa.webp" alt="仿真电路" loading="lazy" /></p>
<p>测量得到开路电压Uoc=9.435 V</p>
<h5>（2）短路电流测量仿真电路</h5>
<p>短路R3, 测量A、B端口的短路电流：
<img src="https://idea.lanerc.me/_astro/9.CNeRbJNk_LiTmv.webp" alt="仿真电路" loading="lazy" /></p>
<p>测量得到短路电流为Isc=0.065 A</p>
<h5>（3）建立等效电路，验证戴维南定理。</h5>
<p><strong>表3 测量数据</strong></p>
<p><img src="https://idea.lanerc.me/_astro/10.BBAUxtDQ_1i5imv.webp" alt="等效仿真电路" loading="lazy" /></p>
<table>
<thead>
<tr>
<th>Uoc（V）</th>
<th>Isc（A）</th>
<th>Ro（Ω）计算值</th>
<th>I3（A）</th>
</tr>
</thead>
<tbody><tr>
<td>9.435</td>
<td>0.065</td>
<td>145.154</td>
<td>0.021</td>
</tr>
</tbody></table>
<p><strong>实验结果分析：</strong></p>
<p>本实验通过开路电压Uoc和短路电流Isc的测量，计算得戴维南等效电阻Ro≈145.154Ω，并构建了等效电路。将等效电路与原负载连接后测得的电流与原电路完全一致，验证了戴维南定理的正确性。实验误差较小，说明仿真连接正确、测量方法合理。</p>
<hr />
<h3>四、实验使用仪器设备（使用软件）</h3>
<p><strong>Multisim 14.3</strong></p>
<hr />
<h3>五、实验总结</h3>
<p><strong>实验误差分析：</strong></p>
<ol>
<li>实验中使用的电流表内阻设为 1Ω、电压表为 10MΩ。在实际测量中，电流表串联会改变支路电流大小，电压表并联会造成轻微分流，特别是在小电流（mA级）时，1Ω 内阻对电流影响明显。造成叠加结果与理论结果在 I2、I3上出现毫安级差异，因为短路支路中串入了 1Ω 的表内阻使戴维南短路电流Isc稍低于理论值。</li>
<li>在线性电阻网络中叠加定理电压、电流不完全重合的原因：小误差来自仪表内阻不完全理想。在二极管网络中，二极管为非线性元件，叠加定理理论上不成立。</li>
</ol>
<p><strong>实验中出现的问题及解决方法：</strong></p>
<ol>
<li>电流读数为负值：检查电表极性，修正电表方向，使大多数读数满足正值。</li>
<li>仪表无读数：发现电路中未连接公共地线，增补上地线。</li>
</ol>
<p><strong>思考题：</strong></p>
<p>分析实验过程中测量值出现负值的原因。</p>
<p>实验中出现电压或电流为负值的主要原因是测量参考方向与实际电路中电压、电流方向不一致。负号来自参考方向的差异，并不影响电压、电流大小本身的正确性。</p>
<p><strong>收获体会：</strong></p>
<p>通过这次实验，我对基尔霍夫定理、叠加定理和戴维南定理有了更深刻的理解。自己动手在Multisim中搭建电路、观察电压电流的变化，让我明白了参考方向、仪表内阻以及二极管非线性对测量结果的影响。在叠加和戴维南验证中，我体会到理论条件与实际仿真之间仍存在差异，需要结合元件状态来判断是否适用。实验过程中熟悉了Multisim的使用方法，提高了我分析电路的能力。总体来说，这次实验加深了我对基础电路理论的理解，也让我意识到细心操作和合理分析的重要性。</p>
<hr />
<h3>六、参考资料</h3>
<ol>
<li>东南大学电工电子实验中心，《电路实验教学计划（2025秋学期）（九龙湖）1》</li>
<li>邱关源，《电路第六版》（高等教育出版社）------ 电路模型与电路定律相关内容。</li>
</ol>
]]></content:encoded></item><item><title>免费动漫软件推荐--Animeko和Lanrec</title><link>https://idea.lanerc.me/posts/animeko-and-lanerc/animeko-and-lanerc/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/animeko-and-lanerc/animeko-and-lanerc/</guid><description>在如今的二次元世界里，一款好用的动漫观看软件是每位追番党的刚需。面对市面上琳琅满目的选择，今天要为大家推荐两款风格不同但都备受好评的免费动漫应用——Animeko与Lanerc，如果喜欢轻松追番的休闲观众，那么这两款总有一款适合你。</description><pubDate>Thu, 13 Nov 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<p>在如今的二次元世界里，一款好用的动漫观看软件是每位追番党的刚需。面对市面上琳琅满目的选择，今天要为大家推荐两款风格不同但都备受好评的免费动漫应用——<strong>Animeko</strong>与<strong>Lanerc</strong>，如果喜欢轻松追番的休闲观众，那么这两款总有一款适合你。</p>
<hr />
<h3>Animeko：开源、自由、无广告的追番神器</h3>
<p>如果你厌倦了广告弹窗、会员门槛和资源缺失的烦恼，那么 <strong>Animeko</strong> 绝对是你的理想之选。作为一款在 GitHub 上开源的跨平台追番软件，Animeko 支持 <strong>安卓、iOS、Windows、Mac、Linux</strong> 全平台使用，真正实现多设备无缝追番。
<em><strong>注意：iOS端不开放AppStore下载，所以基本面向其他平台开放。</strong></em></p>
<h4>核心亮点：</h4>
<ul>
<li><p><strong>完全免费 &amp; 无广告</strong><br />  软件本身不植入任何广告，界面简洁清爽，专注于提供纯净的观看体验。虽然部分视频源可能自带广告，但你可以自由切换至无广告源。</p>
</li>
<li><p><strong>多源聚合，资源丰富</strong><br />  内置蜜柑计划、动漫花园、BT 等多种数据源，支持在线播放与离线下载。无论是当季新番还是冷门老番，基本都能找到高清资源。</p>
</li>
<li><p><strong>弹幕互动 &amp; 云同步</strong><br />  支持加载多平台弹幕，增强观看趣味性。登录账号后，还能同步收藏列表与观看进度，换设备也不怕断档。</p>
</li>
<li><p><strong>高度自定义</strong><br />  可手动设置播放源、弹幕源、分辨率、字幕语言甚至指定字幕组，满足资深用户的个性化需求。</p>
</li>
<li><p><strong>离线缓存 &amp; 自动预载</strong><br />  支持提前缓存多集内容，通勤、旅行时也能畅快追番。开启自动缓存功能，系统会智能为你下载最新一集。</p>
</li>
</ul>
<blockquote>
<p>注意：Animeko 为开源项目，依赖社区维护，偶尔可能出现数据源失效的情况，建议保持关注更新。</p>
</blockquote>
<p>官网地址：<a href="https://myani.org/">Animeko</a> （即为下载地址）
适合人群：追求自由、技术向、多平台同步的深度用户。
<img src="https://idea.lanerc.me/_astro/1.DFMk9LN4_WLJgX.webp" alt="Animeko 客户端界面截图" loading="lazy" /></p>
<hr />
<h3>Lanerc：简洁流畅、社区活跃的追番新秀</h3>
<p>相比 Animeko 的极客风格，<strong>Lanerc</strong> 更像是为大众用户量身打造的“友好型”追番 App。它专注于提供稳定、合法、易用的动漫观看服务，适合不想折腾、只想安心看番的朋友。</p>
<p><em>更新内容：不定时出现流氓开屏广告，让你找不到退出按键。</em></p>
<h4>主要特色：</h4>
<ul>
<li><p><strong>海量正版资源</strong><br />  所有内容均来自合法授权渠道，涵盖日漫、国漫、韩漫及剧场版、OVA 等多种类型，更新及时，追新番毫无压力。</p>
</li>
<li><p><strong>高清画质 &amp; 流畅播放</strong><br />  提供多种清晰度选择（标清/高清/超清），根据网络状况智能切换，确保流畅不卡顿。</p>
</li>
<li><p><strong>智能推荐系统</strong><br />  基于你的观看历史和偏好，自动推荐相似风格的好番，帮你发现更多宝藏作品。</p>
</li>
<li><p><strong>多端同步 &amp; 离线下载</strong><br />  登录账号后，收藏、进度、下载记录全同步，手机、平板、网页端随意切换。支持离线缓存，无网环境也能追番。</p>
</li>
<li><p><strong>活跃社区互动</strong><br />  内置弹幕、评论、分享功能，还能参与话题讨论，与其他动漫爱好者交流心得，感受二次元的温暖社群氛围。</p>
</li>
<li><p><strong>入站问答机制</strong><br />  新用户需通过简单的“入站问答”才能正式使用，既增加了仪式感，也有效防止了滥用和爬虫。</p>
</li>
</ul>
<blockquote>
<p> 注意：Lanerc 目前主要面向安卓和移动端用户，PC 端体验相对有限。此外，开发商也迫于压力不定时投放广告，但浏览一次之后12小时以内不需要再看广告。</p>
</blockquote>
<p>软件发布页： tv.lanerc.app
官网地址：<a href="https://www.lanerc.com/">Lanerc</a>
适合人群：喜欢简洁界面、注重版权合规、享受社区氛围的新手或日常用户。
<img src="https://idea.lanerc.me/_astro/2.D8nvEiju_Z1zT9cI.webp" alt="Lanerc 客户端界面截图" loading="lazy" /></p>
<hr />
<h3>对比总结</h3>
<table>
<thead>
<tr>
<th>特性</th>
<th><strong>Animeko</strong></th>
<th><strong>Lanerc</strong></th>
</tr>
</thead>
<tbody><tr>
<td>是否免费</td>
<td>完全免费</td>
<td>免费（部分功能可能受限）</td>
</tr>
<tr>
<td>广告情况</td>
<td>无内置广告</td>
<td>可能有少量广告</td>
</tr>
<tr>
<td>资源来源</td>
<td>多源聚合（含BT）</td>
<td>正版授权</td>
</tr>
<tr>
<td>数据同步</td>
<td>Bangumi 云同步</td>
<td>自有账号体系</td>
</tr>
<tr>
<td>平台支持</td>
<td>全平台（含PC）</td>
<td>主要为移动端</td>
</tr>
<tr>
<td>自定义程度</td>
<td>高</td>
<td>中等</td>
</tr>
<tr>
<td>社区互动</td>
<td>弹幕+评论</td>
<td>弹幕+社区+话题</td>
</tr>
<tr>
<td>适合人群</td>
<td>技术党、自由派</td>
<td>新手、休闲用户</td>
</tr>
</tbody></table>
<hr />
<h3>结语</h3>
<p>如果你渴望<strong>自由、无拘束的追番体验</strong>，愿意花一点时间配置和探索，<strong>Animeko</strong> 是目前能找到的最强免费工具之一；而如果你更看重<strong>稳定性、合法性和易用性</strong>，希望打开即用、安心追番，那么 <strong>Lanerc</strong> 会是一个更贴心的选择。
愿你每一部想看的番，都能顺利加载，不负热爱，不负青春。</p>
]]></content:encoded></item><item><title>数电实验-组合逻辑电路实验报告</title><link>https://idea.lanerc.me/posts/digital-electronics/combinational-logic-circuit/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/digital-electronics/combinational-logic-circuit/</guid><description>好几天没有更新内容了，学业压力太大了，没有时间书写其他方面的内容，以后会慢慢更新。今天带来的是数电实验第一章：组合逻辑电路</description><pubDate>Fri, 07 Nov 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>实验一 组合逻辑电路</h1>
<p>姓名：zhz 
实验日期：2025年11月6日</p>
<h2>实验目的</h2>
<ol>
<li>认识数字集成电路，能识别各种类型的数字器件和封装</li>
<li>掌握小规模组合逻辑和逻辑函数的工程设计方法</li>
<li>掌握常用中规模组合逻辑器件的功能和使用方法</li>
<li>学习查找器件资料，通过器件手册了解器件</li>
<li>了解面包板的基本结构、掌握面包板连接电路的基本方法和要求</li>
<li>了解实验箱的基本结构，掌握实验箱电源、逻辑开关和LED电平指示的用法</li>
<li>学习基本的数字电路的故障检查和排除方法</li>
</ol>
<h2>实验内容1：数值判别电路</h2>
<h3>实验仪器</h3>
<ul>
<li>数字逻辑电路实验箱及其外设装置---供电、脉冲、边沿和时钟</li>
<li>集成芯片：74HC20（双4输入与非门）、74HC00（四2输入与非门）、74HC04（六反相器）</li>
<li>外围设备：逻辑电平开关、LED指示灯、导线若干</li>
</ul>
<p><img src="https://idea.lanerc.me/_astro/1.CM7sWIGj_ynaOa.webp" alt="数值判别电路实验所用的逻辑电平开关、LED 指示灯与导线" loading="lazy" /></p>
<h3>实验设计方案(a)</h3>
<h4>1. 真值表</h4>
<table>
<thead>
<tr>
<th>B3</th>
<th>B2</th>
<th>B1</th>
<th>B0</th>
<th>Y</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>X</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>X</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>X</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>X</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>X</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>X</td>
</tr>
</tbody></table>
<h4>2. 卡诺图</h4>
<table>
<thead>
<tr>
<th>B3B2\B1B0</th>
<th>00</th>
<th>01</th>
<th>11</th>
<th>10</th>
</tr>
</thead>
<tbody><tr>
<td>00</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>01</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>11</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>10</td>
<td>0</td>
<td>0</td>
<td>X</td>
<td>X</td>
</tr>
</tbody></table>
<h4>3. 逻辑化简</h4>
<p>逻辑表达式：<br />Y = B̅₃B₂ + B̅₃B₁B̅₀<br />= B̅₃(B₂ + B₁B̅₀)<br />= B̅₃(B₂ + B₁)(B₂ + B̅₀)</p>
<p>由于要求只使用与非门和非门，需要将上述表达式转换为与非-与非形式。</p>
<h4>4. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/2.CTmKxcBr_1DWMMB.webp" alt="数值判别电路方案(a)的逻辑电路图" loading="lazy" /></p>
<h4>5. 硬件连接图</h4>
<p><img src="https://idea.lanerc.me/_astro/3.BtlpCJnN_Z2wcdoq.webp" alt="数值判别电路方案(a)的硬件连接图" loading="lazy" /></p>
<h4>6. 实验过程</h4>
<p><img src="https://idea.lanerc.me/_astro/4.BuzCDll4_22iwal.webp" alt="数值判别电路方案(a)的实验过程照片" loading="lazy" /></p>
<p>搭建好电路并进行测试，按照真值表顺序从第一组测到第十组的过程中发现前7组结果正常，第8组理论应输出低电平，实际却输出高电平，继续测试发现后面几组测试结果均正确，经过故障排查发现电路地线接错地方，接到电源的负极输出端。将地线接GND之后重新测试一遍发现电路输出结果正常。</p>
<h4>7. 测试方案</h4>
<table>
<thead>
<tr>
<th>B3</th>
<th>B2</th>
<th>B1</th>
<th>B0</th>
<th>Y</th>
<th>测试结果</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
</tbody></table>
<h4>8. 实验分析</h4>
<ol>
<li>基于真值表绘制卡诺图并化简，得到逻辑表达式后，转换为与非-与非形式，仅使用与非门和非门完成电路设计</li>
<li>硬件连接采用74HC20和74HC00芯片，通过实验箱的逻辑电平开关输入信号，LED指示灯显示输出</li>
<li>测试遍历所有有效输入组合，输出结果与理论真值表完全一致，电路功能实现正常</li>
</ol>
<h3>实验设计方案（b）</h3>
<h4>1. 真值表</h4>
<table>
<thead>
<tr>
<th>B3</th>
<th>B2</th>
<th>B1</th>
<th>B0</th>
<th>Y</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
</tbody></table>
<h4>2. 卡诺图</h4>
<table>
<thead>
<tr>
<th>B3B2\B1B0</th>
<th>00</th>
<th>01</th>
<th>11</th>
<th>10</th>
</tr>
</thead>
<tbody><tr>
<td>00</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>01</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>11</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>10</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</tbody></table>
<h4>3. 逻辑化简</h4>
<p>逻辑表达式：<br />Y = B̅₃B₂B̅₁B̅₀ + B̅₃B₂B̅₁B₀ + B̅₃B₂B₁B̅₀ + B̅₃B̅₂B₁B₀<br />= B̅₃B₂(B̅₁B̅₀ + B̅₁B₀ + B₁B̅₀) + B̅₃B̅₂B₁B₀</p>
<h4>4. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/5.DMfpWXbg_1gBh20.webp" alt="数值判别电路方案(b)的逻辑电路图" loading="lazy" /></p>
<h4>5. 实验过程</h4>
<p>测试前对照逻辑电路图，再次确认74HC系列门电路的引脚定义例如74HC00的输入输出引脚、电源与接地引脚，并检查实验箱的逻辑电平开关、LED指示灯模块是否正常供电。整理所需导线，按信号流向（输入→芯片→输出）规划导线连接路径，避免导线交叉缠绕影响后续排查。</p>
<h4>6. 测试方案</h4>
<table>
<thead>
<tr>
<th>B3</th>
<th>B2</th>
<th>B1</th>
<th>B0</th>
<th>Y</th>
<th>测试结果</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
</tbody></table>
<h4>7. 实验小结</h4>
<p>依据"数值大于2且小于7"的需求构建真值表，无无关项，所有16种输入组合均有明确输出状态。通过卡诺图化简得到逻辑表达式，采用门电路搭建逻辑电路，输入输出连接方式与方案a部分一致。测试覆盖全部16种输入组合，LED显示结果与理论输出完全匹配，电路满足设计要求。</p>
<h2>实验内容2：3位二进制原码转补码电路</h2>
<h3>实验仪器</h3>
<ul>
<li>数字逻辑电路实验箱及其外设装置---供电、脉冲、边沿和时钟</li>
<li>集成芯片：74HC86（四2输入异或门）、74HC00（四2输入与非门）、74HC04（六反相器）、74HC151(8选一数据选择器)、74HC138(3线-8线译码器)</li>
<li>外围设备：逻辑电平开关、LED指示灯（3个）、导线若干</li>
</ul>
<h3>实验设计方案（a）</h3>
<h4>1. 真值表</h4>
<table>
<thead>
<tr>
<th>输入(原码)</th>
<th>输出(补码)</th>
</tr>
</thead>
<tbody><tr>
<td>A₂ A₁ A₀</td>
<td>Y₂ Y₁ Y₀</td>
</tr>
<tr>
<td>0 0 0</td>
<td>0 0 0</td>
</tr>
<tr>
<td>0 0 1</td>
<td>1 1 1</td>
</tr>
<tr>
<td>0 1 0</td>
<td>1 1 0</td>
</tr>
<tr>
<td>0 1 1</td>
<td>1 0 1</td>
</tr>
<tr>
<td>1 0 0</td>
<td>1 0 0</td>
</tr>
<tr>
<td>1 0 1</td>
<td>0 1 1</td>
</tr>
<tr>
<td>1 1 0</td>
<td>0 1 0</td>
</tr>
<tr>
<td>1 1 1</td>
<td>0 0 1</td>
</tr>
</tbody></table>
<h4>2. 卡诺图</h4>
<p>Y₂卡诺图：</p>
<table>
<thead>
<tr>
<th>A₂\A₁A₀</th>
<th>00</th>
<th>01</th>
<th>11</th>
<th>10</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</tbody></table>
<p>Y₁卡诺图：</p>
<table>
<thead>
<tr>
<th>A₂\A₁A₀</th>
<th>00</th>
<th>01</th>
<th>11</th>
<th>10</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
</tbody></table>
<p>Y₀卡诺图：</p>
<table>
<thead>
<tr>
<th>A₂\A₁A₀</th>
<th>00</th>
<th>01</th>
<th>11</th>
<th>10</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
</tbody></table>
<h4>3. 逻辑表达式</h4>
<p>Y₂ = A̅₂A₁ + A̅₂A₀ + A̅₂A₀A̅₁ = A₂ ⊕ (A̅₁A̅₀)<br />Y₁ = A₁ ⊕ A₀<br />Y₀ = A₀</p>
<h4>4. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/6.B229G9jC_Z1qM9GR.webp" alt="3 位二进制原码转补码电路方案(a)的逻辑电路图" loading="lazy" /></p>
<h4>5. 验证结果表格</h4>
<table>
<thead>
<tr>
<th>测试序号</th>
<th>输入A₂A₁A₀</th>
<th>理论输出Y₂Y₁Y₀</th>
<th>实际输出Y₂Y₁Y₀</th>
<th>结果</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>000</td>
<td>000</td>
<td>000</td>
<td>符合</td>
</tr>
<tr>
<td>2</td>
<td>001</td>
<td>111</td>
<td>111</td>
<td>符合</td>
</tr>
<tr>
<td>3</td>
<td>010</td>
<td>110</td>
<td>110</td>
<td>符合</td>
</tr>
<tr>
<td>4</td>
<td>011</td>
<td>101</td>
<td>101</td>
<td>符合</td>
</tr>
<tr>
<td>5</td>
<td>100</td>
<td>100</td>
<td>100</td>
<td>符合</td>
</tr>
<tr>
<td>6</td>
<td>101</td>
<td>011</td>
<td>011</td>
<td>符合</td>
</tr>
<tr>
<td>7</td>
<td>110</td>
<td>010</td>
<td>010</td>
<td>符合</td>
</tr>
<tr>
<td>8</td>
<td>111</td>
<td>001</td>
<td>001</td>
<td>符合</td>
</tr>
</tbody></table>
<h4>6. 实验分析</h4>
<p>硬件连接通过实验箱逻辑电平开关输入原码，3个LED指示灯分别显示补码的三位输出。测试遍历所有8种输入组合，实际输出与理论补码完全一致，所有测试结果均符合要求，电路功能准确实现。</p>
<h3>实验设计方案（b）</h3>
<h4>1. 逻辑表达式</h4>
<p>Y₀ = A₀<br />Y₁ = A₁ ⊕ A₀<br />Y₂ = Σm(1,2,3,4)</p>
<h4>2. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/7.DNvzfy2t_CG2D2.webp" alt="原码转补码电路方案(b)的逻辑电路图" loading="lazy" /></p>
<h4>3. 硬件连接图</h4>
<p><img src="https://idea.lanerc.me/_astro/8.WZEP8-Ep_Z2vc2Hx.webp" alt="原码转补码电路方案(b)的硬件连接图" loading="lazy" /></p>
<h4>4. 实验过程</h4>
<p>整理所需导线，按信号流向（输入→芯片→输出）规划导线连接路径，避免导线交叉缠绕影响后续排查。搭建电路时，先将74HC芯片插入实验箱的IC插座，确保芯片引脚与插座完全贴合，无虚接情况。连接电路后测试得出测试结果。</p>
<h4>5. 验证结果表格</h4>
<table>
<thead>
<tr>
<th>测试序号</th>
<th>输入A₂A₁A₀</th>
<th>理论输出Y₂Y₁Y₀</th>
<th>实际输出Y₂Y₁Y₀</th>
<th>结果</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>000</td>
<td>000</td>
<td>000</td>
<td>符合</td>
</tr>
<tr>
<td>2</td>
<td>001</td>
<td>111</td>
<td>111</td>
<td>符合</td>
</tr>
<tr>
<td>3</td>
<td>010</td>
<td>110</td>
<td>110</td>
<td>符合</td>
</tr>
<tr>
<td>4</td>
<td>011</td>
<td>101</td>
<td>101</td>
<td>符合</td>
</tr>
<tr>
<td>5</td>
<td>100</td>
<td>100</td>
<td>100</td>
<td>符合</td>
</tr>
<tr>
<td>6</td>
<td>101</td>
<td>011</td>
<td>011</td>
<td>符合</td>
</tr>
<tr>
<td>7</td>
<td>110</td>
<td>010</td>
<td>010</td>
<td>符合</td>
</tr>
<tr>
<td>8</td>
<td>111</td>
<td>001</td>
<td>001</td>
<td>符合</td>
</tr>
</tbody></table>
<h4>6. 实验分析</h4>
<p>本实验题目中Y1的输出可用与非门来搭建，相比较两种方法都很省芯片省跳线。和老师沟通之后得知数据选择器一般和与非门来搭配使用，以后的搭建过程中如无特殊要求我会优先选择与非门的使用。</p>
<h3>实验设计方案（c）</h3>
<h4>1. 逻辑表达式</h4>
<p>Y₀ = A₀<br />Y₁ = A₁ ⊕ A₀ = (A₁A̅₀ + A̅₁A₀)<br />Y₂ = A̅₂A₁ + A̅₂A₀ + A̅₂A₀A̅₁ = (A̅₂A₁ + A̅₂A₀A̅₁)</p>
<h4>2. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/9.D5ocDPja_28VGiR.webp" alt="原码转补码电路方案(c)的逻辑电路图" loading="lazy" /></p>
<h4>3. 硬件连接图</h4>
<p><img src="https://idea.lanerc.me/_astro/8.WZEP8-Ep_Z2vc2Hx.webp" alt="原码转补码电路方案(c)的硬件连接图" loading="lazy" /></p>
<h4>4. 实验过程</h4>
<p>按照逻辑电路图搭建好电路之后，按照3位二进制数真值表的顺序依次调节逻辑电平开关，设置输入组合。每设置一组输入，观察LED指示灯的亮灭状态，并立即记录结果。</p>
<h4>5. 验证结果表格</h4>
<table>
<thead>
<tr>
<th>测试序号</th>
<th>输入A₂A₁A₀</th>
<th>理论输出Y₂Y₁Y₀</th>
<th>实际输出Y₂Y₁Y₀</th>
<th>结果</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>000</td>
<td>000</td>
<td>000</td>
<td>符合</td>
</tr>
<tr>
<td>2</td>
<td>001</td>
<td>111</td>
<td>111</td>
<td>符合</td>
</tr>
<tr>
<td>3</td>
<td>010</td>
<td>110</td>
<td>110</td>
<td>符合</td>
</tr>
<tr>
<td>4</td>
<td>011</td>
<td>101</td>
<td>101</td>
<td>符合</td>
</tr>
<tr>
<td>5</td>
<td>100</td>
<td>100</td>
<td>100</td>
<td>符合</td>
</tr>
<tr>
<td>6</td>
<td>101</td>
<td>011</td>
<td>011</td>
<td>符合</td>
</tr>
<tr>
<td>7</td>
<td>110</td>
<td>010</td>
<td>010</td>
<td>符合</td>
</tr>
<tr>
<td>8</td>
<td>111</td>
<td>001</td>
<td>001</td>
<td>符合</td>
</tr>
</tbody></table>
<h4>6. 实验小结</h4>
<p>本实验使用三种方法设计三位源码转补码的电路，通过三种电路的设计，我深刻理解到电路设计的灵活性与科学性，在设计电路的过程中，应善于从不同角度看待问题，从而选择更简洁更方便的方法，三种设计方案中，我学会了很多74系列芯片的使用方法，也从不同角度理解了电路的灵活性，对我以后的设计有很大的帮助。</p>
<h2>实验内容3：血型配对电路</h2>
<h3>实验器材</h3>
<ul>
<li>数据选择器（74HC151）1片</li>
<li>逻辑电平开关（4个，对应输入D、C、B、A）</li>
<li>LED指示灯（1个，对应输出Y）</li>
<li>实验面包板、导线若干</li>
</ul>
<p><img src="https://idea.lanerc.me/_astro/11.CHarPUZ2_1wvKEo.webp" alt="血型配对电路实验所用的器材" loading="lazy" /></p>
<h3>实验设计方案</h3>
<h4>1. 真值表</h4>
<table>
<thead>
<tr>
<th>D</th>
<th>C</th>
<th>B</th>
<th>A</th>
<th>Y</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
</tbody></table>
<h4>2. 卡诺图</h4>
<table>
<thead>
<tr>
<th>DC\BA</th>
<th>00</th>
<th>01</th>
<th>11</th>
<th>10</th>
</tr>
</thead>
<tbody><tr>
<td>00</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>01</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>11</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>10</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
</tbody></table>
<h4>3. 逻辑化简</h4>
<p>逻辑表达式：<br />Y = D̅C̅ + D̅BA + DCBA + D̅C̅B̅A̅</p>
<h4>4. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/13.C1fnmL9L_12iPlo.webp" alt="血型配对电路的逻辑电路图" loading="lazy" /></p>
<h4>5. 硬件连接图</h4>
<p><img src="https://idea.lanerc.me/_astro/14.DvIPswlg_Z1JMWw8.webp" alt="血型配对电路的硬件连接图" loading="lazy" /></p>
<h4>6. 实验过程</h4>
<ol>
<li><strong>电源连接</strong>：将芯片的Vcc和GND分别连接到直流电源的对应端，为芯片供电</li>
<li><strong>芯片放置</strong>：将74HC151（数据选择器）插入面包板，确保引脚与电源、地正确连接</li>
<li><strong>输入电路连接</strong>：将4个逻辑电平开关分别连接到数据选择器的地址端（D→A₂、C→A₁、B→A₀）和数据端（A），作为输入信号源</li>
<li><strong>逻辑门连接</strong>：根据化简后的逻辑，用与非门构建辅助逻辑电路，连接到数据选择器的输入引脚（如D₀~D₇）</li>
<li><strong>输出电路连接</strong>：将数据选择器的输出端Y连接到LED指示灯</li>
</ol>
<h4>7. 测试方案</h4>
<table>
<thead>
<tr>
<th>D</th>
<th>C</th>
<th>B</th>
<th>A</th>
<th>Y</th>
<th>测试结果</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
</tbody></table>
<h4>8. 实验分析</h4>
<p>调试方案：当输入为O型输血给任意血型（D=0、C=0，B、A任意）时，LED应点亮；当输入为A型输血给A型、AB型（D=0、C=1，B=0、A=1或B=1、A=1）时，LED应点亮；当输入为B型输血给B型、AB型（D=1、C=0，B=1、A=0或B=1、A=1）时，LED应点亮；当输入为AB型输血给AB型（D=1、C=1，B=1、A=1）时，LED应点亮；其他非法组合时，LED应熄灭。</p>
<p>结果分析：根据结果表格，对应真值表发现电路测试结果正确。</p>
<h2>实验内容4：保险箱数字密码锁（选做）</h2>
<h3>实验器材</h3>
<ul>
<li>74HC00芯片(2片)、74HC20（1片）</li>
<li>逻辑电平开关（4个，对应输入A3、A2、A1、A0）</li>
<li>LED指示灯（1个，对应输出Y）</li>
<li>实验面包板、导线若干</li>
</ul>
<h3>实验设计方案</h3>
<h4>1. 真值表</h4>
<table>
<thead>
<tr>
<th>E</th>
<th>A3</th>
<th>A2</th>
<th>A1</th>
<th>A0</th>
<th>Z1</th>
<th>Z2</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
</tbody></table>
<h4>2. 逻辑表达式</h4>
<p>Z1 = E·A3·A̅₂·A1·A0<br />Z2 = E·(A̅₃ + A₂ + A̅₁ + A̅₀)</p>
<h4>3. 逻辑电路图</h4>
<p><img src="https://idea.lanerc.me/_astro/15.DJdrZyNn_ZfdB7u.webp" alt="保险箱数字密码锁电路的逻辑电路图" loading="lazy" /></p>
<h4>4. 硬件连接图</h4>
<p><img src="https://idea.lanerc.me/_astro/16.DXM0TuoT_1I189q.webp" alt="保险箱数字密码锁电路的硬件连接图" loading="lazy" /></p>
<h4>5. 实验过程</h4>
<p>使用4个输入信号，通过实验箱上的逻辑电平开关实现；1个输出端连接到实验箱上的LED指示灯。按照真值表要求，拨动逻辑电平开关以改变输入信号的值，遍历所有输入组合，观察并记录输出信号的值。</p>
<h4>6. 测试结果</h4>
<table>
<thead>
<tr>
<th>E</th>
<th>A3</th>
<th>A2</th>
<th>A1</th>
<th>A0</th>
<th>Z1</th>
<th>Z2</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
</tbody></table>
<h4>7. 结果分析</h4>
<p>测试所有输入组合，结果应与真值表一致。当E=1且密码正确时，Z1输出1；当E=1且密码错误时，Z2输出1；当E=0时，Z1和Z2均输出0。电路功能符合要求，且使用了最少数量的与非门。</p>
<h2>实验小结</h2>
<h3>实验仪器环节</h3>
<p>对数字电路实验常用仪器设备形成了清晰认知，熟悉了74HC20（双4输入与非门）、74HC00（四2输入与非门）、74HC86（四2输入异或门）、74HC151（8输入数据选择器）和74HC138（3线-8线译码器）引脚功能与适用场景，掌握了面包板、逻辑电平开关、LED指示灯的操作规范，能够根据实验需求选择并连接仪器，为硬件电路搭建筑牢了实践根基。</p>
<h3>实验记录环节</h3>
<p>基本学会了规范且细致地记录实验步骤、原始数据、实验过程及故障排查信息。在数值判别电路和补码转换电路的实验记录中，逐步养成了按流程操作、逐点记录数据的习惯，提升了实验操作的条理性。同时，在面对实验故障时，掌握了从硬件连接、芯片引脚到导线接触等多维度排查并解决问题的方法，锻炼了发现、分析和解决问题的能力，增强了实验过程中的应变与动手能力。</p>
<h3>实验分析环节</h3>
<p>掌握了数字电路实验结果分析比对的方法，通过将实测输出与理论真值表、逻辑推导结果逐一验证，深入理解了逻辑函数化简、门电路选型与电路功能实现的内在关联，提升了对数字电路逻辑关系的分析与验证能力，也切实体会到理论知识在实践中的有效性，强化了"理论指导实践，实践验证理论"的认知。</p>
<h3>实验小结环节</h3>
<p>对数字电路的完整设计流程有了系统性把握。如从数值判别电路的两种方案设计，到补码转换电路的功能实现，每个环节的实践都让我对数字电路设计的思路、方法及优化策略（如利用无关项简化逻辑）有了更深刻的理解。同时，在总结实验完成情况、讨论设计方案与结果的过程中，明确了自身在数字电路实践中的成长与待提升点，如电路设计有待提升，电路搭建有待提高，排查故障经验需要继续积累等等，为后续学习积累了宝贵的经验与思考。</p>
<h2>参考资料</h2>
<ol>
<li>器件数据手册：74HC00、74HC04、74HC20、74HC86、74HC151、74HC138 <a href="https://pan.seu.edu.cn/#/link/834BCFC09CED7A754BCCC6943CB385D6">软件使用和器件数据手册.rar</a></li>
<li>EPI-LITE304数字电路 <a href="https://pan.seu.edu.cn/#/link/891FD63EFD4D8D21517E39E247D490D2?path=">东南大学文档云</a></li>
<li>两个基础实验（EPI-m204）<a href="https://pan.seu.edu.cn/#/link/891FD63EFD4D8D21517E39E247D490D2?path=">东南大学文档云</a></li>
<li>EPI-EWB204+快速上手 <a href="https://pan.seu.edu.cn/#/link/891FD63EFD4D8D21517E39E247D490D2?path=">东南大学文档云</a>
*word版本文件地址：通过网盘分享的文件：实验一组合逻辑电路实验报告.pdf.docx
链接: <a href="https://pan.baidu.com/s/1q8wvtFLdw0oDjZJTxisA7Q">https://pan.baidu.com/s/1q8wvtFLdw0oDjZJTxisA7Q</a> 提取码: eybn</li>
</ol>
<p><em><strong>注：以上逻辑表达式为deepseek识图识别，个别出现错误，请注意甄别！</strong></em></p>
]]></content:encoded></item><item><title>大学物理实验--霍尔效应实验报告</title><link>https://idea.lanerc.me/posts/hall-effect/hall-effect-report/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/hall-effect/hall-effect-report/</guid><description>好几天没有更新内容了，真的不是我不想更新，实际上脑袋中有好几个很好的项目想法，但是学业压力太大了，没有时间书写，以后会慢慢更新。最近大物实验要求提交电子报告，今天晚上写完了来分享给大家，同时把他记录在我的个人网站中。</description><pubDate>Fri, 31 Oct 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h1>霍尔效应的研究与应用</h1>
<p>指导教师：xxx</p>
<p>姓名：zhz<br />学号：06024436<br />桌号：26<br />日期：2025年10月27日</p>
<blockquote>
<p>实验报告格式要求：中文字体<strong>宋体</strong>、英文字体<strong>Times New Roman</strong>、字号小四、行间距1.5倍；图表应有题注及编号。</p>
</blockquote>
<h2>实验报告内容包括：</h2>
<ol>
<li>实验简介（实验背景、原理、实验方法等）</li>
<li>实验仪器</li>
<li>数据与分析（数据表格、数据作图、必要的数据处理过程、结果分析）</li>
<li>实验小结</li>
<li>附录（将课堂上的原始数据拍照附于此处，原始数据上需有教师签字）</li>
</ol>
<hr />
<h1>实验简介</h1>
<h2>1、实验背景</h2>
<p>霍尔效应是指当载流导体或半导体置于磁场中并通以电流时，在垂直于电流和磁场方向上会产生电势差的现象。该电势差称为霍尔电压。这一现象最早由E. H. Hall于1879年发现。霍尔效应在半导体研究中具有重要意义，可用于测定材料的导电类型、载流子浓度及迁移率等特性。</p>
<h2>2、实验原理和测量方法</h2>
<h3>（1）霍尔电压的产生</h3>
<p>把一块宽为b，厚为d的半导体放在磁感应强度为B磁场中,并在半导体中通以电流I，如图所示，在这块半导体横向侧面AA′间会出现一定的电势差UH，这个现象叫做霍尔效应，UH称为霍尔电压。</p>
<p>实验表明，霍尔电压UH的大小正比于磁感应强度的大小B以及电流I，在UH、B、I三者相互垂直时有：</p>
<p>UH=KHBI</p>
<p>式中KH称为该霍尔元件的灵敏度，与载流子浓度n、霍尔片厚度d相关（KH=1/nqd）。</p>
<p><img src="https://idea.lanerc.me/_astro/1.BRxl8EL9_ZVGSHG.webp" alt="霍尔电压产生原理示意图" loading="lazy" />
图1</p>
<h3>（2）霍尔电压的灵敏度</h3>
<p>霍尔元件的灵敏度KH= 1/(nqd)，与载流子浓度和样品厚度成反比。半导体的载流子浓度远低于金属，因此使用薄型半导体霍尔元件能显著增强霍尔效应。</p>
<h3>（3）对称测量法求霍尔电压</h3>
<p>实验中可能出现不等位电势差和热电、热磁副效应（如厄廷好森效应、能斯脱效应、里纪-勒杜克效应）。通过"对称测量法"，即反转磁场或电流方向取平均，可有效消除这些干扰，提高测量精度。具体方法是通过改变IS和B的方向测4次电压（+IM、+IS，+IM、-IS，-IM、-IS，-IM、+IS，IM为励磁电流）,分别记为U1、U2、U3、U4，综合考虑四种效应的影响：</p>
<p>UAA'=UH +UO+UE +UN+URL</p>
<p>通过四次测量可消除UO、UN、URL的影响：</p>
<p>UH = (-U1 + U2 - U3 + U4)/4</p>
<p>若UE很小，可近似：</p>
<p>UH≈ (-U1 + U2 - U3 + U4)/4</p>
<h3>（4）电导率与载流子参数计算</h3>
<p>电导率σ：由电极间的电压UAC和IS计算：</p>
<p>σ=ISL/UACS（L为A、C间距，S=bd为霍尔片横截面积，b为宽度）</p>
<p>霍尔系数RH：RH=KHd</p>
<p>载流子浓度n: n=1/eRH（e=1.602×10^−19^C）</p>
<p>通过测量霍尔系数和电导率，可以计算出迁移率。载流子迁移率μ与电导率σ的关系为</p>
<p>σ = neμ</p>
<h2>实验内容</h2>
<h3>（1）确定霍尔片的载流子类型</h3>
<p>根据霍尔片上的连接方式、电流源的流向、电磁铁的绕向以及电压表的连接方向，然后依据霍尔电压的正负来判断n型霍尔片和p型霍尔片。</p>
<h3>（2）测量p型霍尔片的灵敏度</h3>
<p>保持工作电流 Is = 2.00 mA，励磁电流 IM取值 0.200 A ~ 0.700 A，用对称测量法测量 p 型霍尔片的霍尔电压，绘制并分析UH --- IM曲线，用图解法求灵敏度KH值。</p>
<h3>（3）测量 p型半导体的电导率，计算霍尔系数、载流子浓度及载流子迁移率</h3>
<p>在零磁场条件下，通以合适的工作电流 Is（Is≤0.20 mA）测量 UAC，结合中霍尔片的相关参数，计算本实验中用于制作 p 型霍尔片的半导体材料的电导率σ．计算该半导体的霍尔系数 RH、载流子浓度 n 和载流子迁移率μ。</p>
<p><img src="https://idea.lanerc.me/_astro/4.DK5VYA3__Zw2qpY.webp" alt="p 型霍尔片电导率测量与参数计算的数据界面" loading="lazy" /></p>
<p>图2</p>
<h3>（4）测量 n型半导体的霍尔系数、载流子浓度及载流子迁移率</h3>
<p>按照以上的步骤，选择合适的工作电流和励磁电流，测量 n 型半导体的霍尔系数 RH、载流子浓度 n 和载流子迁移率 μ，并和 p 型半导体进行比较。</p>
<h3>（5）利用霍尔效应测量磁场</h3>
<p>系统可配合SPARKvue APP进行数字化采集与实时曲线绘制，支持导出 CSV 或 SPKL 文件格式，以便进一步数据分析。</p>
<p>采用数字化方式测量单线圈、不同距离下双线圈轴线上磁场分布情况(时间充足时也可探究更多不同线圈位置下磁场分布情况)，请保证支架处在0 cm时，霍尔探头刚好在线圈中心位置。将采集到的数据导出后进行处理，尝试用matlab或origin等软件在同一坐标系下作出单线圈、不同距离下双线圈的磁场强度位置图。</p>
<h1>实验仪器</h1>
<p><img src="https://idea.lanerc.me/_astro/2.BnYtp1ta_CgWWy.webp" alt="霍尔效应实验仪器全貌" loading="lazy" /></p>
<p>图3</p>
<h3>1、电磁铁</h3>
<p>用于产生实验所需的磁场。电磁铁的励磁电流IM由测试仪提供，铁芯气隙中心区域的磁感应强度 B 与IM在一定范围内呈线性关系，可引入电磁铁常数 C，即</p>
<p>B=CIM</p>
<p>不同实验仪的电磁铁常数略有差异，具体数值标示在线圈外壳上。</p>
<h3>2、霍尔片与支架</h3>
<p>实验中分别使用p型与n型半导体霍尔片，两者几何尺寸相同。霍尔片通常采用薄型半导体材料，以获得较大的霍尔电压信号，其尺寸为：</p>
<p>宽度 b = 4.00 mm，厚度 d = 0.30 mm，电极间距 l = 2.00 mm。</p>
<p><img src="https://idea.lanerc.me/_astro/3.DLUroASo_1L3H3S.webp" alt="霍尔片与支架的照片" loading="lazy" /></p>
<p>图4</p>
<h3>3、开关与接线装置</h3>
<p>该系统包含一个五刀双掷开关与三个双刀双掷开关。</p>
<p>五刀双掷开关：用于选择接入电路的霍尔片（p型或n型）。</p>
<p>K₁：K1向上扳时，恒流源输出的电流由D端流进，向下扳时，则由G端流进。</p>
<p>K₂：控制励磁电流方向，K2向上扳时，IM的流向与线圈相同，反之相反。线圈的绕向标示在电磁铁上。</p>
<p>K₃：切换电压测量模式，K3向上扳时，毫伏表测量UAA'，向下扳时测量UAC。</p>
<p>该设计能够快速切换测量参数，实现"对称测量法"以消除副效应带来的误差。</p>
<h3>4、霍尔效应测试仪</h3>
<p>该装置为实验核心设备，用于提供电源、测量与数据输出。其主要部分包括：</p>
<p>电源开关:用于开启或关闭整机；</p>
<p>数字接口：连接计算机或数据采集系统；</p>
<p>电压表：实时显示霍尔电压或电导电压；</p>
<p>工作电流旋钮：为霍尔元件提供恒定电流；</p>
<p>励磁电流旋钮：为线圈提供励磁电流，顺时针调大、逆时针调小；</p>
<p>注意：切换电流方向或插拔导线前，须将旋钮调至零位，以防突变电流损坏元件。</p>
<h3>5、测量与辅助装置</h3>
<p>实验装置配备精密导轨，可调整霍尔片在磁场中的具体位置，确保测量区域磁场均匀。电压采用毫伏表测量，以保证对微小电压信号的高精度读取。此外，系统可配合 SPARKvue APP 进行数字化采集与实时曲线绘制，支持导出 CSV 或 SPKL 文件格式，以便进一步数据分析。</p>
<p>整个霍尔效应实验仪器结构完善，功能集成度高。开关系统与数字化采集技术的结合，不仅提高了实验精度，也为霍尔效应研究提供了便捷的操作平台。</p>
<h1>数据与分析</h1>
<h2>1. 载流子类型判断</h2>
<p>实验中，控制工作电流流向与磁场方向一定，左侧霍尔片测得的 UAA'&gt; 0，说明载流子为正电荷（空穴），属于p型半导体；右侧霍尔片测得的 UAA'&lt; 0，说明载流子为负电荷（电子），属于n型半导体。</p>
<p>该结果与理论一致，验证了霍尔电压符号与载流子类型的对应关系。</p>
<h2>2、测量p型霍尔片的灵敏度</h2>
<h3>法一：使用霍尔电压和磁场大小的关系</h3>
<p><strong>表1 用对称测量法测p型霍尔片的霍尔电压</strong></p>
<p>工作电流 Is = 2.00 mA；电磁铁常数 C = 465mT/A；室温 t = 23.3°C</p>
<table>
<thead>
<tr>
<th>IM/A</th>
<th>UAA'/mV (+IM、+IS)</th>
<th>UAA'/mV (-IM、+IS)</th>
<th>UAA'/mV (+IM、-IS)</th>
<th>UAA'/mV (-IS，-IM)</th>
<th>UH/mV</th>
</tr>
</thead>
<tbody><tr>
<td>0.200</td>
<td>0.78</td>
<td>-0.47</td>
<td>-0.68</td>
<td>0.56</td>
<td>0.622</td>
</tr>
<tr>
<td>0.300</td>
<td>1.10</td>
<td>-0.78</td>
<td>-0.99</td>
<td>0.87</td>
<td>0.935</td>
</tr>
<tr>
<td>0.400</td>
<td>1.41</td>
<td>-1.08</td>
<td>-1.29</td>
<td>1.19</td>
<td>1.243</td>
</tr>
<tr>
<td>0.500</td>
<td>1.71</td>
<td>-1.40</td>
<td>-1.61</td>
<td>1.50</td>
<td>1.555</td>
</tr>
<tr>
<td>0.600</td>
<td>2.02</td>
<td>-1.70</td>
<td>-1.92</td>
<td>1.81</td>
<td>1.863</td>
</tr>
<tr>
<td>0.700</td>
<td>2.33</td>
<td>-2.02</td>
<td>-2.22</td>
<td>2.11</td>
<td>2.170</td>
</tr>
</tbody></table>
<p>注：测量时，IM 应单向调节，减小磁滞效应的影响。</p>
<p><img src="https://idea.lanerc.me/_astro/5.C9LL-PbZ_Z19vmxg.webp" alt="霍尔电压随磁场变化的测量数据界面" loading="lazy" /></p>
<p>数据分析1</p>
<p>根据图像得知：所测量得到的霍尔电压灵敏度KH=3.23 <strong>V</strong>/($A \cdot T$)</p>
<h3>法二：使用霍尔电压和工作电流的关系</h3>
<p><strong>表2 用对称测量法测p型霍尔片的霍尔电压</strong></p>
<p>IM=0.7A；Is从1.00A到2.00A变化；电磁铁常数 C = 465mT/A；室温 t = 23.3°C</p>
<table>
<thead>
<tr>
<th>Is/mA</th>
<th>UAA'/mV (+IM、+IS)</th>
<th>UAA'/mV (-IM、+IS)</th>
<th>UAA'/mV (+IM、-IS)</th>
<th>UAA'/mV (-IS，-IM)</th>
<th>UH/mV</th>
</tr>
</thead>
<tbody><tr>
<td>1.00</td>
<td>1.21</td>
<td>-1.09</td>
<td>1.11</td>
<td>-0.99</td>
<td>1.100</td>
</tr>
<tr>
<td>1.20</td>
<td>1.44</td>
<td>-1.32</td>
<td>1.31</td>
<td>-1.19</td>
<td>1.315</td>
</tr>
<tr>
<td>1.40</td>
<td>1.67</td>
<td>-1.54</td>
<td>1.52</td>
<td>-1.40</td>
<td>1.533</td>
</tr>
<tr>
<td>1.60</td>
<td>1.90</td>
<td>-1.78</td>
<td>1.73</td>
<td>-1.61</td>
<td>1.755</td>
</tr>
<tr>
<td>1.80</td>
<td>2.13</td>
<td>-1.99</td>
<td>1.93</td>
<td>-1.80</td>
<td>1.963</td>
</tr>
<tr>
<td>2.00</td>
<td>2.34</td>
<td>-2.22</td>
<td>2.14</td>
<td>-2.01</td>
<td>2.178</td>
</tr>
</tbody></table>
<p><img src="https://idea.lanerc.me/_astro/6.iOZ-caMk_2hTQJe.webp" alt="霍尔电压随工作电流变化的测量数据记录" loading="lazy" /></p>
<p>数据分析2</p>
<p>根据图像得知：所测量得到的霍尔电压灵敏度KH= 3.35 <strong>V</strong>/($A \cdot T$)</p>
<h3>分析与比较：</h3>
<p>两种方法均属于对称测量，但方法二（四组电流方向对称）在系统误差消除上更具优势，在霍尔效应测量中抑制系统误差效果更佳显著；方法一的"数据对称"（拟合UH-IM）虽能体现线性关系，但受磁场线性度和Is稳定性影响更大，误差相对偏高。</p>
<h2>3.测量p型半导体的电导率，计算霍尔系数、载流子浓度及载流子迁移率</h2>
<p><strong>表3 测量p型半导体的电导率</strong></p>
<p>IM=0;室温 t = 23.3°C</p>
<table>
<thead>
<tr>
<th>Is/mA</th>
<th>0</th>
<th>0.05</th>
<th>0.10</th>
<th>0.15</th>
<th>0.20</th>
</tr>
</thead>
<tbody><tr>
<td>UAC/mV</td>
<td>0.06</td>
<td>2.96</td>
<td>5.99</td>
<td>8.86</td>
<td>12.43</td>
</tr>
</tbody></table>
<p><img src="https://idea.lanerc.me/_astro/7.DIIDCrha_xG6wx.webp" alt="p 型半导体电导率测量数据" loading="lazy" /></p>
<p>数据分析3</p>
<p>根据以上分析总结如下：</p>
<p>P型半导体霍尔片电导率为26.82 S/m</p>
<p>霍尔系数RH=3.23×10^-4^ m^3^/C</p>
<p>载流子浓度n=6.44×10^21^ m^-3^</p>
<p>载流子迁移率μ=2.600×10^-2^ <strong>m^2^</strong>/($V \cdot S$)</p>
<h2>4.测量n型半导体的霍尔系数、载流子浓度及载流子迁移速度</h2>
<p><strong>表4 用对称测量法测n型霍尔片的霍尔电压</strong></p>
<p>IM=0.7A；Is从1.00A到2.00A变化；电磁铁常数 C = 465mT/A；室温 t = 23.3°C</p>
<table>
<thead>
<tr>
<th>Is/mA</th>
<th>UAA'/mV (+IM、+IS)</th>
<th>UAA'/mV (-IM、+IS)</th>
<th>UAA'/mV (+IM、-IS)</th>
<th>UAA'/mV (-IS，-IM)</th>
<th>UH/mV</th>
</tr>
</thead>
<tbody><tr>
<td>1.00</td>
<td>-3.73</td>
<td>3.85</td>
<td>-3.35</td>
<td>3.49</td>
<td>-3.605</td>
</tr>
<tr>
<td>1.20</td>
<td>-4.45</td>
<td>4.59</td>
<td>-4.01</td>
<td>4.15</td>
<td>-4.300</td>
</tr>
<tr>
<td>1.40</td>
<td>-5.18</td>
<td>5.31</td>
<td>-4.68</td>
<td>4.80</td>
<td>-4.993</td>
</tr>
<tr>
<td>1.60</td>
<td>-5.95</td>
<td>6.08</td>
<td>-5.37</td>
<td>5.51</td>
<td>-5.728</td>
</tr>
<tr>
<td>1.80</td>
<td>-6.68</td>
<td>6.80</td>
<td>-6.01</td>
<td>6.14</td>
<td>-6.408</td>
</tr>
<tr>
<td>2.00</td>
<td>-7.14</td>
<td>7.55</td>
<td>-6.69</td>
<td>6.82</td>
<td>-7.118</td>
</tr>
</tbody></table>
<p><img src="https://idea.lanerc.me/_astro/8.BjNVXkqX_2tgBzu.webp" alt="n 型半导体霍尔系数测量数据" loading="lazy" /></p>
<p>数据分析4</p>
<p>由图像可知：n型半导体霍尔片的霍尔电压灵敏度为-10.93 <strong>V</strong>/($A \cdot T$)</p>
<p><strong>表5 测量n型半导体的电导率</strong></p>
<p>IM=0;室温 t = 23.3°C</p>
<table>
<thead>
<tr>
<th>Is/mA</th>
<th>0</th>
<th>0.05</th>
<th>0.10</th>
<th>0.15</th>
<th>0.20</th>
</tr>
</thead>
<tbody><tr>
<td>UAC/mV</td>
<td>0.06</td>
<td>3.10</td>
<td>5.80</td>
<td>8.78</td>
<td>12.11</td>
</tr>
</tbody></table>
<p><img src="https://idea.lanerc.me/_astro/9.BTfNwSLr_Z1tmDKX.webp" alt="n 型半导体电导率测量数据" loading="lazy" /></p>
<p>数据分析5</p>
<p>根据以上分析总结如下：</p>
<p>n型半导体霍尔片电导率为27.50 S/m</p>
<p>霍尔系数RH=-3.279×10^-4^ m^3^/C</p>
<p>载流子浓度n=1.904×10^21^ m^-3^</p>
<p>载流子迁移率μ=0.902 <strong>m^2^</strong>/($V \cdot S$)</p>
<h2>思考问题：为什么测量之前要先测一组Is置零的情况？</h2>
<p>在测量 n 型半导体电导率时，测"置零组Is=0时的UAC）"的核心目的是消除零位误差，具体原因如下：当 Is=0时，理论上半导体中无工作电流，对应的电压UAC应严格为 0。但实际中，由于以下因素会产生 "零位电压"：</p>
<p>（1）霍尔片不等势误差：霍尔片的电极制作不可能完全对称，无电流、无磁场下电极间也会因接触电阻、几何不对称存在微小电压。</p>
<p>（2）仪器零点漂移：电压表、电流源等仪器本身存在固有偏移，导致 "零输入" 时仍有输出读数。</p>
<p>所以在后续计算电导率时，需将每个Is对应的UAC减去置零组的UAC，得到修正后的电压UAC'= UAC - 0.06mV)，以此消除零位误差对线性关系和电导率计算的干扰。</p>
<h2>5.利用霍尔效应测磁场</h2>
<p>工作电流Is=5mA;励磁电流IM=0.5A;霍尔元件灵敏度KH=2316 <strong>V</strong>/($A \cdot T$)。</p>
<p>改变线圈之间的长度为R/2、R、2R，软件读取函数如下图：</p>
<p><img src="https://idea.lanerc.me/_astro/10.Txa-2Seq_1R3e6C.webp" alt="改变线圈间距后软件读取的磁场测量结果" loading="lazy" /></p>
<p>图5</p>
<h1>四、实验小结</h1>
<p>本实验我通过对霍尔效应的系统研究，掌握了霍尔电压的测量方法、载流子类型的判断依据，以及半导体材料电导率、霍尔系数、载流子浓度和迁移率的计算方法。</p>
<h2>实验结果表明：</h2>
<ol>
<li>通过霍尔电压的正负成功判断出p型与n型半导体，符合理论预期。</li>
<li>采用对称测量法有效消除了不等位电势和热磁副效应的影响，提高了测量精度。</li>
<li>测得p型霍尔片的灵敏度约为3.23～3.35 V/(A·T)，n型霍尔片的灵敏度约为10.93 V/(A·T)，两者差异反映了载流子类型与浓度对霍尔效应的影响。</li>
<li>p型与n型半导体的载流子迁移率分别为0.026 m²/(V·s)和0.902 m²/(V·s)，n型迁移率显著高于p型，说明电子为主要载流子时具有更高的运动能力。</li>
<li>载流子浓度与迁移率的数值在常见半导体参杂迁移率范围内合理；所测得的霍尔电压存在正负号，表示空穴/电流方向与所定义正方向之间的关系。</li>
</ol>
<h2>实验中存在的主要误差来源包括：</h2>
<ol>
<li>霍尔灵敏度与电压测量中的不确定度；</li>
<li>电磁铁磁场的非线性与磁滞效应；</li>
<li>环境温度波动对半导体性能的影响。</li>
</ol>
<h2>为提升实验精度，我的反思与改进：</h2>
<ol>
<li>在测量前充分预热仪器，减少零点漂移；</li>
<li>多次测量取平均值，尤其在切换电流与磁场方向时；</li>
<li>对温度敏感的参数进行实时记录与修正。</li>
</ol>
<p>本次实验深化了我对霍尔效应物理机制的理解，也锻炼了综合运用图解法与数值法处理实验数据的能力。</p>
<h1>五、附录</h1>
<p><img src="https://idea.lanerc.me/_astro/11.DbebTdb5_RTJ5p.webp" alt="实验数据附录截图" loading="lazy" /></p>
<p><img src="https://idea.lanerc.me/_astro/12.DlwibSDj_2fHBba.webp" alt="实验数据附录截图（续）" loading="lazy" /></p>
<p>原版文件地址：通过网盘分享的文件：物理实验报告（电子版）.docx
链接: <a href="https://pan.baidu.com/s/1MW_uBSQ9oqL6YHXCbgP7ow">https://pan.baidu.com/s/1MW_uBSQ9oqL6YHXCbgP7ow</a> 提取码: t3vy</p>
]]></content:encoded></item><item><title>如何使用cloudflare workes 功能搭建代理节点</title><link>https://idea.lanerc.me/posts/cloudflare-workers/cloudflare-workers/</link><guid isPermaLink="true">https://idea.lanerc.me/posts/cloudflare-workers/cloudflare-workers/</guid><description>内容来自YouTube大佬：seven科技生活。作为一名技术小白，一步步跟着他做也成功搭建出自己的节点，并且能解锁x，chatgpt和gemini，能秒开高帧视频，使用体验也是不错的。</description><pubDate>Sat, 25 Oct 2025 00:00:00 GMT</pubDate><content:encoded><![CDATA[<h3>准备工作</h3>
<p>好了，前面说了这么多，下面说说需要准备的东西吧。</p>
<p>首先，你需要准备一个GitHub账号登陆在网页上面，方便操作。最好有一个cloudflare账号，没有也没关系，登陆进去使用邮箱注册一个就好。</p>
<p>之后需要把你自己的域名托管在cf上，后续我会出一个申请免费域名并托管到cf上的教程。</p>
<p>这里附上链接：
github：
<a href="https://github.com/">https://github.com</a></p>
<p>cloudflare:
<a href="https://dash.cloudflare.com/">https://dash.cloudflare.com/</a></p>
<p>然后，如果你电脑上没有代理，你需要在你的edge扩展里面下载并运行ilink,用于加速GitHub（如果你有watt tooltik，可以使用它来加速，效果会更好。但是强烈建议要有一个能加速浏览器的代理，例如ilink,保证你自己好。）</p>
<p>废话不多说准备开干！</p>
<p>第一步就是进入到cloudflare账号界面：
<img src="https://idea.lanerc.me/_astro/b.DPK93fRH_Z1LOm44.webp" alt="Cloudflare 控制台首页" loading="lazy" />
图上可以看到啊我现在有三个域名，其实都是免费申请的，这里只需要任意选择一个就好，当作备用。</p>
<p>之后展开<strong>computer&amp;AI</strong>选项找到<strong>workers&amp;pages</strong>，点进去：
<img src="https://idea.lanerc.me/_astro/a.BHbH55ls_1YzCph.webp" alt="在控制台展开 Computer &amp; AI 并找到 Workers &amp; Pages" loading="lazy" />
点击右上角的<strong>创建新项目</strong>，之后点击最下面的<strong>workers</strong>栏<strong>start with hello world</strong>。
稍等片刻进入设计页面:</p>
<p><img src="https://idea.lanerc.me/_astro/c.BrofdJMO_2dzXs5.webp" alt="Workers 项目创建后的设计页面" loading="lazy" />
点击右上角的<strong>Edit code</strong>白色方块，这个时候我们要进入甬哥的项目，项目地址我放在下面：
<a>https://github.com/yonggekkk/Cloudflare-vless-trojan</a></p>
<p><img src="https://idea.lanerc.me/_astro/d.Du5e1rTO_F9v7B.webp" alt="yonggekkk/Cloudflare-vless-trojan 仓库页面" loading="lazy" /></p>
<p>选择我圈出来的文件夹，这个时候我们可以看到四个代码，其中有几个已经失效，代码说明我放在下面：
<img src="https://idea.lanerc.me/_astro/e.CnnWRh1k_2lb15J.webp" alt="在仓库中选中 Worker 代码文件的界面" loading="lazy" /></p>
<p>我们选择套壳混淆，进去选择copy，这个时候回到cloudflare代码编辑部份，删掉原来的代码，将我们刚复制的部分粘贴到上面。
点击deploy,成功会出现以下图象。
<img src="https://idea.lanerc.me/_astro/f.C-scBI0M_QCfPu.webp" alt="点击部署成功后显示的界面" loading="lazy" /></p>
<p>这时候我们要更改一下uuid，可以直接浏览器搜索uuid生成器，复制。</p>
<p><img src="https://idea.lanerc.me/_astro/g.BnsRlAq__Z2pfVTn.webp" alt="UUID 生成器生成新 UUID 的页面" loading="lazy" /></p>
<p>找到变量与密码这一部分，点击添加，第一栏写uuid,第二栏粘贴上刚复制的uuid。
<img src="https://idea.lanerc.me/_astro/h.Bufw1Cb5_1u9eVG.webp" alt="在环境变量与密码中添加 UUID 的界面" loading="lazy" /></p>
<p>下面呢我们就开始添加域名，便于我们找到部署的节点链接页面，其实你也可以在<strong>Domains &amp; Routes</strong> 一栏点击cf自动给你生成的地址进入节点部署链接页面。（进入需要代理）
但是我还是建议自己部署一个域名。
<img src="https://idea.lanerc.me/_astro/i.CRAxTWDx_1kbES4.webp" alt="为 Worker 绑定自有域名的界面" loading="lazy" /></p>
<p>找到<strong>Domains &amp; Routes</strong> 一栏点击add，添加自己的域名，这里可以再往下面写一级，即在域名前面加上"www." 之类的。
下面我们找到uuid，按照以下格式进入上方搜索框：</p>
<p>”www. 自己的域名/uuid“ 的形式回车，就能看到部署页面啦！</p>
<p>推荐使用clash订阅链接，速度超快，看视频毫无压力！</p>
<p>好了，这个内容就写到这里，如果有相关方面的疑问可以联系我。
欢迎大家批评指正！</p>
]]></content:encoded></item></channel></rss>