<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[蝶梦浮世]]></title><description><![CDATA[愿世界如你我所愿♪]]></description><link>https://devuki.com</link><image><url>https://montrong-1300089193.cos.ap-beijing.myqcloud.com/montrong/2026/02/20260222055225371.svg</url><title>蝶梦浮世</title><link>https://devuki.com</link></image><generator>Yohaku (https://github.com/Innei/Yohaku)</generator><lastBuildDate>Thu, 02 Jul 2026 02:56:14 GMT</lastBuildDate><atom:link href="https://devuki.com/feed" rel="self" type="application/rss+xml"/><pubDate>Thu, 02 Jul 2026 02:56:14 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[关于 MixSpace 更新和 Yohaku 主题适配的常见问题]]></title><description><![CDATA[<p>往原址览之：<a href="https://devuki.com/posts/research/mixspace-update-yohaku-theme-compatibility-issues">https://devuki.com/posts/research/mixspace-update-yohaku-theme-compatibility-issues</a></p>]]></description><link>https://devuki.com/posts/research/mixspace-update-yohaku-theme-compatibility-issues</link><guid isPermaLink="true">https://devuki.com/posts/research/mixspace-update-yohaku-theme-compatibility-issues</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Tue, 26 May 2026 12:07:29 GMT</pubDate></item><item><title><![CDATA[关于永恒的思绪]]></title><description><![CDATA[<p>往原址览之：<a href="https://devuki.com/notes/1">https://devuki.com/notes/1</a></p>]]></description><link>https://devuki.com/notes/1</link><guid isPermaLink="true">https://devuki.com/notes/1</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Mon, 25 May 2026 23:54:58 GMT</pubDate></item><item><title><![CDATA[爱洛斯星见闻｜灵境联合政府]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cos.ap-beijing.myqcloud.com/montrong-1300089193/crystals/2026/05/a5xentroxjanwfs1z1.jpg"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/posts/aeternalys-chronicles/wiki-ulg">https://devuki.com/posts/aeternalys-chronicles/wiki-ulg</a></blockquote><div><p><img height="1250" src="https://cos.ap-beijing.myqcloud.com/montrong-1300089193/crystals/2026/05/a5xentroxjanwfs1z1.jpg" width="2000"/></p><h1 id="">灵境联合政府</h1><blockquote><p>为世界一切的和平。</p></blockquote>
<p>灵境联合政府是全灵境最大的国家集团，拥有 340 个成员国。其中有五个核心成员国为灵境联合政府全球安全组织最高委员会理事国，并另有 32 个定期轮换和推选进入的灵境联合政府全球安全组织理事国。</p><p>灵境联合政府下设有数个分支组织，以维护和推动世界向前。其中主要机关和部分重要组织如下：</p><ul><li><strong>灵境大会</strong>：联合政府的主要审议、决策和代表机构，由爱洛斯星 340 个成员国组成，每个国家拥有一票。负责讨论宪章范围内的任何问题，批准预算，选举全球安全组织的一般理事国等。
<ul><li>英文名：United Lintrin General Assembly，ULGA。</li></ul></li><li><strong>灵境联合政府全球安全组织</strong>：维护世界和平稳定的机关。拥有核心武装力量「联合政府武装部队」，和由全球国家筛选组建的「联合政府维护全球和平部队」，前后者的武装力量比例控制在 2:5 左右。
<ul><li>英文名：United Lintrin Global Security Organization，ULGSO。</li></ul></li><li><strong>灵境国际法庭</strong>：联合政府的主要司法机关。负责审理国家间的法律争端，并就灵境大会、ULGSO 等授权的法律问题提供咨询意见。
<ul><li>英文名：United Lintrin International Court，ULIC。</li></ul></li><li><strong>灵境联合政府行政厅</strong>：联合政府的行政机关。由数以万计的国际职员组成，负责执行其他机关的决定，管理维和行动、调解冲突、组织国际会议等日常工作。
<ul><li>英文名：United Lintrin Administration，ULA。</li></ul></li><li><strong>全球裂隙现象和异能者协会</strong>：自裂隙灾害降临后设立的组织，负责监测、研究全球的裂隙灾害现象。该组织同时管理着全球异能者，所有执行异能任务的人都需要拥有异能者协会的证件。
<ul><li>英文名：Association for Extranormal and Global Incursion Surveillance，A.E.G.I.S.。</li></ul></li><li><strong>联合政府全球开发计划署</strong>：爱洛斯星最大的全球发展网络，在约 276 个国家和地区开展工作，致力于消除贫困、减少不平等、加强民主治理和在裂隙灾害时代下建设抗灾能力。
<ul><li>英文名：United Lintrin Global Development Programme，ULGDP。</li></ul></li><li><strong>联合政府裂隙现象管理局</strong>：灵境联合政府管理和协助管理全球裂隙现象、裂隙空间的最高行政与特种武装部门，总部位于联合政府群岛的「中央裂隙」附近。对于无政府地区和公海、天空中的裂隙现象和裂隙空间，联合政府裂隙现象管理局拥有最高行政管理和裁定权；对于处于各国家境内的裂隙现象和裂隙空间，联合政府裂隙现象管理局有义务协助、督查相关国家进行有效管理和控制，并在裂隙出现失控的大部分时候，联合政府裂隙现象管理局有权介入相关国家进行武装协助。
<ul><li>英文名：United Lintrin The Riven Administration，U.L.T.R.A.。</li></ul></li></ul><h2 id="">组织架构</h2><ul><li><strong>领袖</strong>：████</li><li><strong>核心成员国</strong>：天明联邦共和国，████，<a href="苍原民主共和国">苍原民主共和国</a>，███，████████████████。</li></ul><h2 id="">目标与理念</h2><ul><li><strong>公开目标</strong>：联合全世界所有国家，求同存异，维护世界和平稳定。</li></ul><h2 id="">历史</h2><ul><li><strong>成立时间</strong>：<code>繁荣纪元 1910 年 10 月 1 日</code></li><li><strong>重大事件</strong>：████</li></ul><p><em>待被发现的异世界见闻「？？？」…</em></p><hr/><h2 id="">关联条目</h2><p><a href="https://devuki.com/posts/aeternalys-chronicles/wiki-airos">https://devuki.com/posts/aeternalys-chronicles/wiki-airos</a></p></div><p style="text-align:right"><a href="https://devuki.com/posts/aeternalys-chronicles/wiki-ulg#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/posts/aeternalys-chronicles/wiki-ulg</link><guid isPermaLink="true">https://devuki.com/posts/aeternalys-chronicles/wiki-ulg</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Sat, 23 May 2026 11:08:48 GMT</pubDate></item><item><title><![CDATA[恒辉纪闻｜爱洛斯星]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cos.ap-beijing.myqcloud.com/montrong-1300089193/crystals/2026/05/kn40hfesaecmb70n6t.jpg"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/posts/aeternalys-chronicles/wiki-airos">https://devuki.com/posts/aeternalys-chronicles/wiki-airos</a></blockquote><div><p><img height="1250" src="https://cos.ap-beijing.myqcloud.com/montrong-1300089193/crystals/2026/05/kn40hfesaecmb70n6t.jpg" width="2000"/></p><h1 id="">爱洛斯星</h1><blockquote><p>一颗位于宇宙一隅的宜居星球。故事的主要发生地。</p></blockquote>
<h2 id="">物理与法则</h2><ul><li><strong>所属星系</strong>：恒辉宇宙南四十二号星际空间死星际域超星系团流光星系第三旋臂薇尔诺丝系第四行星。</li><li><strong>重力/大气</strong>：目前演化为了氮氧混合气体为主的大气。星球诞生之初时为二氧化硫、二氧化碳和氩气构成，并混合有大量宇宙射线、尘埃、辐射粒子。</li><li><strong>运行轨道</strong>：薇尔诺丝系第四行星轨道。/</li><li><strong>超自然力量源泉</strong>：一般恒辉宇宙相变能量体系。</li></ul><h2 id="">全球地理</h2><ul><li><strong>板块构成</strong>：</li></ul><table><thead><tr><th> 板块名称  </th><th> 包含范围                                               </th></tr></thead><tbody><tr><td> 中央板块  </td><td> 中北大陆（天明洲大部分地区、苍原洲）及周围海域和岛屿。                        </td></tr><tr><td> 冰封板块  </td><td> 包含天明洲极北、天元港、冰封海域所在的板块，近乎完全由海洋地壳构成。                 </td></tr><tr><td> 珍珠洋板块 </td><td> 中央板块西侧、珍珠洋所在的板块。是灵境世界面积最大的海洋板块。                    </td></tr><tr><td> 星元洲板块 </td><td> 由星空之神西米娅从珍珠洋板块中切割下来的板块，包含星元洲及周边海域。                 </td></tr><tr><td> 上风洋板块 </td><td> 中央板块东侧的板块，包含上风洋、启新洲群陆海域（Archipelago of Neolumina）。 </td></tr><tr><td> 东南板块  </td><td> 包含启新洲大陆及部分海域、溟海洲北部分海域。                             </td></tr><tr><td> 溟海板块  </td><td> 由溟海洲及周围群陆、岛屿和海洋构成的板块。                              </td></tr></tbody></table><ul><li><strong>特殊地貌</strong>：参见有关该主题的《地理志》。</li></ul><h2 id="">人文地理</h2><p>参见有关该主题的《地理志》各洲人文地理见闻录。</p><h3 id="">编年历法</h3><table><thead><tr><th> 历法    </th><th> 描述                             </th></tr></thead><tbody><tr><td> 灵境通用历 </td><td> 诞生于灵境通用文化，目前被广泛用于灵境各国家和地区。     </td></tr><tr><td> 灵境新历  </td><td> 启新洲文明推动使用的历法，采用三相恒星纪年法。        </td></tr></tbody></table>
<h3 id="">主流文化、文字</h3><p>灵境通用文化是灵境的主流文化。自天明洲发源的类天明文化，被通称为灵境通用文化。与之相对的，是主要流动于灵境东南地区的灵境新文化。由于启新洲和溟海洲与其它洲相距都非常远，拥有更独立的文化演化空间，也因此成为灵境第二大主流文化。</p><h3 id="">货币体系</h3><h4 id="-thalur">汐灵元 Thalur</h4><p>货币代码：<mark class="rounded-md"><span class="px-1">CLT</span></mark></p><p>天明联邦共和国联邦储备银行面向全球发行的通用信用货币，在全球 312 个国家和地区流通。汐灵元也是灵境世界通用的语言，谁人都能理解贵金属所代表的是什么。汐灵元是灵境世界购买力最高的货币，一克纯金的价值在过去十年间平均相当于 2.3174 汐灵元。也因此，为了照顾全灵境绝大多数国家和地区，汐灵元的最小面额来到了小数点后四位数。</p><p>汐灵元的纸币面值分别为 0.0001Ⓣ、0.0005Ⓣ、0.001Ⓣ、0.005Ⓣ、0.01Ⓣ、0.05Ⓣ、0.1Ⓣ、0.2Ⓣ、0.5Ⓣ、1Ⓣ、2Ⓣ、5Ⓣ、10Ⓣ、50Ⓣ、100Ⓣ、500Ⓣ 共十六种，其中 0.5Ⓣ 是灵境世界绝大多数国家和地区最常用的货币面值，而 500T 面值的汐灵元除了极少数在流通之外，仅在天明联邦共和国中央银行做大面额存放用。</p><h4 id="-unibase">原点币 Unibase</h4><p>货币代码：<mark class="rounded-md"><span class="px-1">UNB</span></mark></p><p>由十三国联盟货币基金组织（The Apex Trideca Monetary Fund, ATMF）与东境银行（Eastern-Lintrin Bank, ELB）联合发行的跨主权信用货币，在启新洲、苍原洲部分地区和溟海洲部分地区，共 57 个国家和地区间流通。一克纯金的价值在过去十年间平均相当于 613.73508200 原点币。</p><p>原点币是以「联盟共识网络加密货币算法」为中心构建的计算货币价值体系。此外，为了彰显启新洲（Neolumina）「革新、理性、自由」的文明认同，东境银行和十三国联盟货币基金组织在制定新货币时全票通过了这个货币名称：原点币（Unibase）。基于Uni-（统一性） + Base（基准）的构词，体现「跨文明共同价值原点」的哲学定位。</p><p>原点币几乎不发行纸质货币，人们主要通过在「原点联盟」成员银行办理借记卡或信用卡，并通过随身携带的银行卡、手机银行、数字原点完成交易。虽然原点币纸质货币的最小面值只有 1U，但通过数字支付的方式可以实现最多 8 位小数的货币交易。</p><h2 id="">编年史梗概</h2><p><em>待被发现的异世界见闻「？？？」…</em></p><h3 id="">重大历史事件</h3><p><em>待被发现的异世界见闻「？？？」…</em></p></div><p style="text-align:right"><a href="https://devuki.com/posts/aeternalys-chronicles/wiki-airos#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/posts/aeternalys-chronicles/wiki-airos</link><guid isPermaLink="true">https://devuki.com/posts/aeternalys-chronicles/wiki-airos</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Sat, 23 May 2026 10:50:28 GMT</pubDate></item><item><title><![CDATA[朋友圈中的浮世绘]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/notes/4">https://devuki.com/notes/4</a></blockquote><div><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>90% 是游戏，10% 是浮光掠影的遇见。</p><p>在朋友圈的列表里，惟我的朋友圈是突兀的抽卡、深渊、游戏角色美照和生日信；或是一点点的吃和行，而那些展现现实生活的画片中，只有空虚的风景、佳肴和配文，却不见哪怕一人，仿佛世间的一切热闹都离我远去。</p></div><p style="text-align:right"><a href="https://devuki.com/notes/4#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/notes/4</link><guid isPermaLink="true">https://devuki.com/notes/4</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Mon, 04 May 2026 14:30:00 GMT</pubDate></item><item><title><![CDATA[数字纪游篇]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/notes/3">https://devuki.com/notes/3</a></blockquote><div><p>我最早接触的是 Windows XP。那时的我还不知道电脑可以打游戏，我的“游戏”是系统自带的画图软件，以及后来在父亲教导下打开的 Microsoft Office 2007。早在一年级，我就学会了在 Word 里敲字、设置页码、更新索引目录，然后把它们用打印机变成实实在在的纸张。随后，我又无师自通了用 Excel 做课程表，在 PPT 里给元素添加花哨的动画。</p><p>偶然一次整理错题，我学会了用扫描仪把书页导进电脑，用刚学会的基础版 Adobe Photoshop 拉高对比度，抹掉错题本上的错误答案，让背景回归纯白。在这个时期，我还邂逅了金山画王。</p><p>当时的中文互联网正处于野蛮生长的时代。用着 360、猎豹和搜狗浏览器，我无需登录就能自由访问许多网站，最爱的是在谷歌地球里俯瞰城市肌理。为了看电影，我学会了去种子网站找资源并用迅雷下载；听歌则用着刚推出的酷狗音乐，享受着全网免费下载的红利。但也正因如此，盗版、流氓软件和病毒肆虐，让我在毫无防备的年纪，早早结识了 360 安全卫士等杀毒软件，在与病毒的斗智斗勇中练就了最初的网络安全意识。</p><p>到了二三年级，我的系统升级到了 Windows 7。Office 2010 成为了新宠，我开始折腾 Excel 的拖拽序列、VBA 基础和更复杂的 PPT 模板，同时 WPS Office 也走进了我的视野。影音方面，QQ 影音、暴风影音和爱奇艺成了标配，我也顺势注册了人生中第一个微信账号。。那时候感觉能简单的上个网、看点动画片、玩玩 Office 就很快乐了。</p><p>这个阶段，我还短暂邂逅了 OS X 10.7 Lion。虽然只用了两次，但为了完成学校的「视频作业」，我第一次用上了 iMovie，也种下了对 Mac 生态的初步印象。</p><p>彼时我还没接触 Bilibili，主要用的是爱奇艺和优酷。这两个网站很多时候有很长的视频广告，但同时它们的搜索结果也会显示一些来自站外的视频，其中也包括 bilibili。那时的 Bilibili 还是一股清流。优酷和爱奇艺充斥着冗长的广告，而 B 站播放器加载时那只写着“高能正在来袭”的小电视，成了我心中的净土。</p><p>2016 年，Windows 10 发布的消息喧嚣尘上。我被那种扁平化设计和动态磁贴深深吸引，简直视其为「梦中情系统」。可惜我用着父亲退下来的老电脑，带不动 Win 10，我只能退而求其次，换成了次一级的 Windows 8.1，Office 也同步升级到了 2013。同年，我注册了 QQ。也是在这个时期，我顺着 PS 的藤蔓摸到了 Au 和 Ai，学会了破解 Adobe 全家桶，还一度痴迷于桌面美化——透明任务栏、Dock 栏、动态壁纸，我硬是把 Windows 折腾出各种花样。</p><p>因为性能限制，我一度与吃配置的 Premiere 失之交臂，转而掌握了爱剪辑等轻量化工具。我还第一次尝试了凡科建站建立了我的第一个网站，虽然在两个月后我便不再管它；在没有服务器和域名的窘境下，体验了一把做站长的乐趣。</p><p>2018 年是转折性的一年。我的电脑从 Thinkpad 换成了 2011 款的 MacBook Pro。虽然是台老机器，但 macOS Sierra 带来的图形操作体验让我迅速倒戈。我发现 iWork 在简单文字工作时的易用性，远超功能冗杂的 Office 和 WPS。</p><p>疫情来袭的 2020 年 8 月，我换上了一台全新的小米笔记本，迎来了工具库的大换血：浏览器全面转向 Google Chrome 和彼时还很干净的 Microsoft Edge；压缩软件换成 BandZIP；在学校学了 3Ds Max，自学了 FL Studio 和 VS Code，也终于用上了心心念念的 PR 和 AE。</p><p>不过，这段时期最疯狂的壮举，莫过于“黑苹果”。</p><p>由于 Windows 端没有 Sketch，我起初尝试用 Adobe XD 做原型设计和矢量图绘制，但它的难用和糟糕的稳定性让我忍无可忍。一怒之下，我开始折腾黑苹果，并在 2021 年初成功在这台小米笔记本上跑通了支持「接力」的 macOS Big Sur。</p><p>折腾的潘多拉魔盒一旦打开就无法关上。2022 年，我购买了云服务器，初遇 CentOS 7 和宝塔面板。在笔记本上，我从双系统一路折腾到三系统，安装过 Ubuntu 和 deepinOS，但由于软件和设备生态的惯性，日常主力的依然是那套黑苹果。与此同时，随着视频制作需求增加，我开始使用剪映，并掌握了 OBS Studio 的推流操作。</p><p>时代的浪潮滚滚向前。2023 年，当大模型掀起革命时，受限于 ChatGPT 的注册门槛，我转向了百度的文心一言，初步体验了 AI 的力量。2024 年 10 月，高考结束，我踏入了大学校园，也终于拥有了一台搭载 Apple 芯片的全新 MacBook Pro。工具不再是限制想象力的瓶颈，我顺畅地用上了 Xcode、Final Cut Pro，以及 WebStorm、IDEA 等一众 JetBrains 系的重型开发工具。</p><p>在文字创作上，我也完成了从重型排版到纯粹表达的蜕变。不再执着于 Word 的复杂排版，我将阵地转移到了 Typora、Lattics、Obsidian 和 Ulysses。它们专注于文字表达与知识的沉淀，正如现在的我一样。</p><p>2025 年春，是我第二次接触到大模型 AI 的时候，并且很快体验到了相对更成熟的 AIGC 模型能力。在接下来直至现在的时间里，Grok、ChatGPT、Gemini 成为了我最重要的生产力工具。</p><p>回望这十多年，从在画图板里涂鸦的小孩，到熟练穿梭于终端和 IDE 的大学生，这些更迭的系统与软件，不仅仅是工具，更是我一路成长的数字见证。</p></div><p style="text-align:right"><a href="https://devuki.com/notes/3#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/notes/3</link><guid isPermaLink="true">https://devuki.com/notes/3</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Sun, 19 Apr 2026 06:24:48 GMT</pubDate></item><item><title><![CDATA[大语言模型时代，思考应如何存在？]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/notes/2">https://devuki.com/notes/2</a></blockquote><div><p>这两天沉浸于给自己的项目敲代码和学习新编程语言之中，睡觉的时间很晚。这天下午，当我熟练地打开 Safari 和 Visual Studio Code，准备解决问题和添加新功能的时候，我的光标在 Safari 的地址栏停住了。这一刻，我在犹豫：是要先在官方技术文档和社区论坛找寻解决方案和策略，还是如往常一样，熟练地打开 Gemini、ChatGPT 或其它智能体，通过简单的几句话提交需求，然后坐等她们反馈解决方案呢？</p><p>这或许是一个值得我们去思考的问题。这种犹豫，本质上是我们在“效率”与“深度”之间的拉扯。</p><p>在过去两年多的时间里，生成式机器学习技术的不断发展确实把我们宠坏了。看着长串的代码在几秒钟内跃然屏上，那种多巴胺分泌的快感让人欲罢不能。但在这短暂的停顿中，我突然意识到：<strong>对于智能体的使用方法，应该由我们面对代码时的身份来决定。</strong></p><p><strong>当处于「学习者」时，思考可以被快进，但绝不能被跳过。</strong> 学习一门新语言或新框架，就像是建立底层认知的地基。如果一遇到报错就丢给智能体，我们得到的是一个可能「跑得通的结果」，却错失了翻阅官方文档、理解设计哲学、甚至在试错中建立代码直觉的机会。知识只会从我们的表面飘过，或短暂地停留，而后扬长而去。她们可以是一位帮你解释生涩概念的超级导师，但绝不能成为替你咀嚼知识的代劳者。在学习中跳过思考的下场，往往是在离开她们后，面对一片空白屏幕的手足无措。</p><p><strong>然而，当你切换到「开发者」的实战模式时，态度就该截然不同了：去拥抱「新生」吧。</strong> 在实际的项目推进中，我们最大的敌人是重复造轮子和繁琐的体力劳动。写正则、配置环境、生成测试用例、甚至写一些业务逻辑的样板代码……在这些环节上死磕并不会带来技术上的顿悟，只会消耗你宝贵的精力。这时候，熟练地向智能体提交需求，让她们帮你扫清这些障碍，我们才能把核心精力聚焦在架构设计、业务逻辑和创新功能上。</p><p>决定我们能走多远的，永远不是智能体能协助我们做些什么，而是我们脑海中对问题的「知能」。</p></div><p style="text-align:right"><a href="https://devuki.com/notes/2#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/notes/2</link><guid isPermaLink="true">https://devuki.com/notes/2</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Sun, 12 Apr 2026 14:15:07 GMT</pubDate></item><item><title><![CDATA[记一次部署 Yohaku 作为个人空间]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/posts/research/yohaku-deploy">https://devuki.com/posts/research/yohaku-deploy</a></blockquote><div><p>这两天访问到 <a href="https://innei.in">静かな森</a> 时注意到其主题 <strong>Yohaku</strong> 非常符合我的个人审美，相较于我原来功能更全面但不精细的 <a href="https://montrong.cn">Astral Reverie</a> 说，Yohaku 在文字创作的深度上更适合<strong>生活记录、个人空间</strong>，其记录的体现形式也覆盖了个人的琐事、学习、灵感的需求。由于属于本人首次接触现代前端项目，在此之前以 PHP 及原生 CSS 和 JS 为主要的我在部署 Yohaku 时遇到了许多大大小小的问题，故在此做文章以记录，供以后参考。</p><p>由于本人已有带有公网 IPv4 地址的云服务器，因此本篇文章主要介绍<strong>在 Linux 云服务器环境下（带宝塔面板）进行部署</strong>。基于 Vercel 部署的方案本文并未涉及，如有需要请参考互联网的其他文章。</p>
<hr/><h1 id="">引用</h1><p>相关项目仓库：</p><p><a href="https://github.com/Innei/Yohaku">https://github.com/Innei/Yohaku</a></p><p>本文章引用的相关文档、技术说明和指南：</p><p><a href="https://mx-space.js.org">https://mx-space.js.org</a></p><p><a href="https://github.com/innei-dev/shiroi-deploy-action">https://github.com/innei-dev/shiroi-deploy-action</a></p><p><a href="https://github.com/innei-dev/Yohaku">https://github.com/innei-dev/Yohaku</a></p><blockquote class="markdown-alert-important"><header>IMPORTANT</header>
<p>Yohaku 项目为<strong>闭源项目</strong>，因此 Innei 在 GitHub 的 Yohaku 仓库为私有属性仓库，如果需要访问该仓库，需要通过 GitHub Sponsor 赞助开发者。</p></blockquote>
<p><a href="https://github.com/sponsors/Innei">https://github.com/sponsors/Innei</a></p>
<hr/><h1 id="">环境部署和需要</h1><p>Yohaku 项目的本体位于 GitHub 上，需要首先进行编译构建后部署到服务器；由于 Node.js 项目在编译时对设备性能开销较大，因此选择采用 GitHub Action 工作流的形式呈现。</p><h2 id="-dns">域名注册和配置 DNS</h2><p>目前主流的域名注册渠道有国内的腾讯云、阿里云、百度云，外国的 Cloudflare、GoDaddy 和 DynaDot。在这里我个人推荐使用 Cloudflare 进行注册，或者你也可以选择你喜欢的域名服务商，这一点并无区别。</p><p>注册域名后，进入你的域名服务商的「DNS 解析」管理处（注意：腾讯云的域名管理在 DNSPod 进行），分别添加以下 A 解析记录，解析地址填写你的服务器的 <code>公网 IP</code>：</p><ul><li>@</li><li>api</li></ul><blockquote class="markdown-alert-note"><header>NOTE</header>
<p>解析记录指你的域名的三级、四级或更高域名；例如对 <code>example.com</code> 进行 A 解析到地址 <code>1.1.1.1</code>，记录为 api 时，DNS 服务器会将 <code>api.example.com</code> 解析到 <code>1.1.1.1</code>。需要注意，@ 指代域名的 root，记录 @ 代表的就是其本身。</p></blockquote>
<h2 id="">服务器环境和账号注册</h2><p>首先我们需要准备一个具备公网上网的服务器，并拥有一个独立域名。以腾讯云为例，一般一个云服务器的价格在每月 CNY 30 - CNY 70 之间，一个域名的价格最低只需要每年 CNY 10。这些资源对于建立网站来说并不贵，甚至可以说非常划算。除了这两项硬件要求，我们还需要以下软件上的硬性要求：</p><ul><li><input readOnly="" type="checkbox" checked=""/> 一个 GitHub 账户（<a href="https://github.com">可前往此处注册</a>）</li><li><input readOnly="" type="checkbox" checked=""/> 在服务器部署以下运行环境
<ul><li><input readOnly="" type="checkbox" checked=""/> Docker</li><li><input readOnly="" type="checkbox" checked=""/> Node.js 20.11 或更新版本（特别提示：此软件<strong>无法在较旧服务器搭载的 CentOS 7 环境中运行</strong>）</li><li><input readOnly="" type="checkbox" checked=""/> pnpm</li><li><input readOnly="" type="checkbox" checked=""/> pm2</li><li><input readOnly="" type="checkbox" checked=""/> sharp</li></ul></li></ul><p>此外，基于 Yohaku 具有的各种功能实现，推荐有以下软件：</p><ul><li><input readOnly="" type="checkbox"/> Clerk 账号</li><li><input readOnly="" type="checkbox"/> TMDB 账号</li></ul><p>对于服务器的 Node.js 环境配置，你可以参考下面这些代码：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
# 验证
node -v

npm install -g pnpm
# 验证
pnpm -v

npm install -g pm2
# 验证
pm2 -v

cd &amp;&amp; mkdir -p mx-space/core &amp;&amp; cd $_

pnpm add sharp
</code></pre>
<p>如果你使用宝塔面板 Node.js 管理器安装的 Node.js，并且因此在终端无法找到 Node.js，你可以参考管理器显示的安装路径，并将其添加到你的 PATH。</p><p>对于服务器的 Docker 环境配置，腾讯云的宝塔应用服务器一般会配备好 Docker，1Panel 面板同样会自带 Docker。你可以通过在终端输入 <code>docker -v</code> 以确定你是否安装了 Docker。如果终端回馈了一个版本号，即代表该服务器安装了 Docker。</p><p>如有需要，你可以在参考下面这个安装 Docker 的终端指令：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 如果你的服务器在国内，建议使用阿里云的安装脚本
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

# 在国外，可以直接使用官方脚本安装
curl -fsSL https://get.docker.com | bash -s docker

# 查询版本以验证安装
docker -v
</code></pre>
<hr/><h1 id="">后端服务配置</h1><h2 id="-mixspace">部署 MixSpace</h2><blockquote class="markdown-alert-tip"><header>TIP</header>
<p>对于这部分内容，你可以从官方文档获取更详细的解释：
<a href="https://mx-space.js.org/docs/core/docker">https://mx-space.js.org/docs/core/docker</a></p></blockquote>
<p>Yohaku 项目是一个前后端分离的项目，其依托于 MixSpace 后端存在。因此我们首先需要部署 MixSpace，以更简易操作的 Docker 为例，首先拉取用于部署后端的 <code>docker-compose.yml</code> ：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">cd &amp;&amp; mkdir -p mx-space/core &amp;&amp; cd $_
 
# 拉取 docker-compose.yml 文件
wget https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
</code></pre>
<p>在 <code>docker-compose.yml</code> 里 <code>environment</code> 字段填入以下必要的信息：</p><pre class="language-yml lang-yml"><code class="language-yml lang-yml">- JWT_SECRET=
- ALLOWED_ORIGINS=
</code></pre>
<p>对于这两个属性字段，有以下解释：</p><ul><li><strong><code>JWT 密钥</code></strong>：需要填写长度不小于 16 个字符，不大于 32 个字符的字符串，用于加密用户的 JWT，务必保存好自己的密钥，不要泄露给他人。</li><li><strong><code>被允许的域名</code></strong>：需要填写被允许的域名，将你之前在 DNS 配置的解析域名填入此处，用英文逗号，分隔。需要注意，填入的域名为完整且无前缀的域名。例如：<code>api.example.com,example.com</code>；而不是这样： <code>https://api.example.com</code> 或只填入 <code>api</code> 甚至 <code>@</code>。</li></ul><p>启动 Core：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">docker compose up -d
</code></pre>
<h2 id="">配置反向代理</h2><p>此处以宝塔面板为例，打开宝塔面板，进入 <code>网站</code>，新建一个网站，域名填写为 <code>api.你的域名</code>，其余不动并点击创建。此时尝试访问你的域名，如果显示为「网站创建成功啦」字样，即代表你的配置没有问题。</p><p>在你新建的网站项目右侧点击 <code>设置</code>，在弹窗的左侧找到 <code>SSL</code> 配置一个证书（例如 <code>Let&#x27;s Encrypt</code> 免费证书）并开启 HTTPS。</p><p>随后重复上述步骤，新建另一个域名为 <code>你的域名</code> 的网站。</p><p>在你的后台网站 <code>设置</code> 中，在 <code>反向代理</code> 栏目下点击 <code>添加反代</code>，<code>目标</code> 填写 <code>http://127.0.0.1:2333</code>，发送域名填写 <code>$host</code>，点击确定。</p><p>在你的前台网站 <code>设置</code> 中，在 <code>反向代理</code> 栏目下点击 <code>添加反代</code>，<code>目标</code> 填写 <code>http://127.0.0.1:2323</code>，发送域名填写 <code>$host</code>，点击确定。</p><p>随后前往 <code>https://api.你的域名/proxy/qaqdmin</code> 配置后端服务器。</p>
<h2 id="">意外处理</h2><p>如果遇到可能的各种意外，我推荐你询问 AI Agent。</p><p>新时代新风气，我们遇到了一个人工智能蓬勃发展的时代，所以在你遇到了问题的时候请<strong>先询问</strong>各种 AI 助手程序，它们会帮助你解决大部分疑问。</p><p>我在这里仅列出一个我遇到的问题，即我原先在服务器配置了 Cloudreve，因此 Docker 中已经存在名为 redis 的容器，此时需要在 <code>docker-compose.yml</code> 中将相关容器换一个名字部署即可。</p>
<h2 id="-mixspace">更新 MixSpace</h2><p>在大版本号相同的情况下（例如 <code>11.0.6 -&gt; 11.6.1</code> 或 <code>11.0.6 -&gt; 11.0.8</code>，只要第一个小数点前的数字没有改变，那么都属于大版本号相同），进行 MixSpace 的更新十分简单：</p><ul><li>进入 MixSpace Core 部署目录；</li><li>直接 <code>pull</code> 拉取新版本；</li><li>上线新版本。</li></ul><pre class="language-bash lang-bash"><code class="language-bash lang-bash">cd ./mx-space/core
docker compose pull app
docker compose up -d app
</code></pre>
<p>观察到 <code>Started</code> 字样后，打开你的后台页面，并进行更新检查：</p><ul><li><input readOnly="" type="checkbox"/> 文章列表正常显示；</li><li><input readOnly="" type="checkbox"/> 文章内关联的评论和内容显示正常；</li><li><input readOnly="" type="checkbox"/> 后台登录正常；</li><li><input readOnly="" type="checkbox"/> 发送一篇文章，并删除它，测试文章是否能被正常发布和删除。</li></ul><hr/><h1 id="-yahaku-">前端 Yahaku 部署</h1><p>我采用了 @Innei 提供的 GitHub Actions 进行预构建形式进行部署。</p><blockquote class="markdown-alert-tip"><header>TIP</header>
<p>对于这部分内容，如果你有一定经验，可以参考开发者的官方文档：</p><p><a href="https://github.com/innei-dev/shiroi-deploy-action">https://github.com/innei-dev/shiroi-deploy-action</a></p></blockquote>
<h2 id="fork-">Fork 部署工作流仓库</h2><p>首先，需要从作者的仓库 Fork 一份 deploy 到你的 GitHub 账户。</p><blockquote class="markdown-alert-note"><header>NOTE</header>
<p>所谓「Fork（分叉）」在 GitHub 里的意思就是<strong>“合法抄作业”</strong>。
作者写好了一个“自动部署工作流”的模板仓库，此时你需要根据你的服务器和域名需要对这个工作流进行一些参数微调，但你不能直接改他的代码，所以你需要点一下 Fork 按钮，<strong>把他的整个仓库原封不动地复制到你自己的 GitHub 账号下</strong>。这样这个仓库就是你的了，你想怎么折腾都行。</p></blockquote>
<ol start="1"><li>登录你的 GitHub 账号。</li><li>打开原作者的这个工作流仓库地址： <a href="https://github.com/innei-dev/yohaku-deploy-action">yohaku-deploy-action</a></li><li>视线移到屏幕的<strong>右上角</strong>，找到一个叫 <strong>Fork</strong> 的按钮（旁边通常有个小数字），点它！</li><li>页面会跳出一个 &quot;Create a new fork&quot; 的确认界面。你啥都不用改，直接滑到最下面点击绿色的 <strong>Create fork</strong> 按钮。</li><li>等个两三秒，页面刷新后，你会发现左上角的仓库名字变成了 <code>你的用户名/yohaku-deploy-action</code>。</li></ol><h2 id="-ghpat">获取 GH_PAT</h2><p>虽然同为 GitHub 下的功能，但 GitHub Actions 本身并没有权限查看账户名下私有仓库的代码。因此需要配置一个账户的 API 密钥（即 <strong>Personal Access Token (PAT)</strong>），以供 GitHub Actions 访问仓库。</p><ol start="1"><li><p>在 GitHub 任意页面的右上角，点击你的<strong>个人头像</strong>，在下拉菜单里选择最下面的 <strong>Settings（设置）</strong>。</p></li><li><p>在左边那一长溜菜单里，滑到最底下，点击 <strong>Developer settings（开发者设置）</strong>。</p></li><li><p>在左边菜单选 <strong>Personal access tokens</strong> -&gt; 然后选 <strong>Tokens (classic)</strong>。</p></li><li><p>在页面右上角，点击 <strong>Generate new token</strong> -&gt; 选 <strong>Generate new token (classic)</strong>。（这时候可能会让你输一下 GitHub 密码验证身份）。</p></li><li><p>到了新建钥匙的页面：</p><ul><li><strong>Note（备注）：</strong> 随便填，比如写 <code>Deploy-Shiro</code>。</li><li><strong>Expiration（有效期）：</strong> 选 <code>No expiration</code>（永不过期），免得以后又要重新搞。</li><li><strong>Select scopes（权限范围）：</strong> 找到 <strong><code>repo</code></strong> 这一项，把旁边的大方框<strong>打上勾</strong>（代表这把钥匙可以访问你的私有仓库）。</li></ul></li><li><p>滑到最下面，点击绿色的 <strong>Generate token</strong>。</p></li></ol><blockquote class="markdown-alert-important"><header>IMPORTANT</header>
<p>页面会显示一串很长很长的乱码（<code>ghp_</code> 开头的），<strong>立刻马上把它复制下来，存到你的本地记事本里！</strong> 这串密码只显示一次，刷新页面就再也看不到了。</p></blockquote>
<h2 id="-secrets">配置 Secrets</h2><p>接下来将账户的 API 密钥以及其他必要信息填入 Deploy 仓库的配置信息中：</p><ol start="1"><li>回到第一步 Fork 出来的那个仓库主页**（<code>你的用户名/yohaku-deploy-action</code>）。</li><li>点击仓库右上方的 <strong>Settings（设置）</strong> 标签页。</li><li>在左侧菜单里找，依次点击：<strong>Secrets and variables</strong> -&gt; <strong>Actions</strong>。</li><li>点击页面绿色的按钮 <strong>New repository secret</strong>。</li><li>到了填写页面：
<ul><li><strong>Name（名字）：</strong> 严格填写 <code>GH_PAT</code> （全大写，必须长这样）。</li><li><strong>Secret（内容）：</strong> 把你刚才在第二步保存在记事本里的那一长串 <code>ghp_</code> 钥匙粘贴进去。</li></ul></li><li>点击 <strong>Add secret</strong>。</li></ol><p>继续点击 <strong>New repository secret</strong>，把下面这些都加上：</p><ul><li><code>HOST</code>：填你服务器的 IP（比如 <code>1.1.1.1</code>）</li><li><code>USER</code>：填 <code>root</code> 或其它你的用户名</li><li><code>PASSWORD</code>：填你服务器的 root 密码（如果不安全，可以用 <code>KEY</code> 填 SSH 密钥，二选一填就行，填密码比较适合新手）</li><li><code>PORT</code>：填 <code>22</code>（如果你的 SSH 没改过端口就是 22）</li><li><code>BASE_URL</code>：填 <code>https://你的域名</code></li><li><code>NEXT_PUBLIC_API_URL</code>：填 <code>https://api.你的域名/api/v3</code></li><li><code>NEXT_PUBLIC_GATEWAY_URL</code>：填 <code>https://api.你的域名</code></li></ul><blockquote class="markdown-alert-note"><header>NOTE</header>
<p>注意确保宝塔面板和你的服务商的云服务器仪表盘防火墙暴露了 <code>22</code> 端口。</p></blockquote>
<h2 id="-env-">配置 .env 环境变量文件</h2><p>在你的服务器 <code>/~</code> 目录下新建一个名为 <code>shiro</code> 的文件夹，然后新建一个名为 <code>.env</code> 的文件：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">cd &amp;&amp; mkdir -p shiro &amp;&amp; cd $_ &amp;&amp; touch .env
</code></pre>
<p>在 <code>.env</code> 中填入以下内容，并在空白处填入对应的值：</p><blockquote class="markdown-alert-tip"><header>TIP</header>
<p>虽然按照开发者官方的说法，应该令 <code>NEXT_PUBLIC_GATEWAY_URL=${BASE_URL}</code>、<code>NEXT_PUBLIC_API_URL={BASE_URL}/api/v3</code>。</p><p>但 Next.js 有时候对 <code>${BASE_URL}</code> 这种动态拼接的写法解析会犯傻。为了不给它报错的机会，我建议直接把完整的网址写死。</p></blockquote>
<pre class="language-env lang-env"><code class="language-env lang-env">BASE_URL=

NEXT_PUBLIC_API_URL=
NEXT_PUBLIC_GATEWAY_URL=

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=

NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/

TMDB_API_KEY=

GH_TOKEN=
</code></pre>
<h3 id="1-">1. 基础网址部分（直接写死更稳妥）</h3><pre class="language-env lang-env"><code class="language-env lang-env"># 你的网站主域名
BASE_URL=https://你的域名

# 后端 API 地址（直接写完整网址）
NEXT_PUBLIC_API_URL=https://api.你的域名/api/v3

# 网关地址
NEXT_PUBLIC_GATEWAY_URL=https://api.你的域名
</code></pre>
<h3 id="2-clerk-">2. Clerk 身份验证（网站的后台登录）</h3><p>这是一个用来做登录服务的第三方服务。</p><ul><li>去 <a href="https://clerk.com/">Clerk 官网</a> 注册个账号，新建一个应用。</li><li>然后在它的控制台里找到这两个 Key 填进来：</li></ul><pre class="language-env lang-env"><code class="language-env lang-env">NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxx (填你在Clerk获取的公钥)
CLERK_SECRET_KEY=sk_test_xxxxxxxxxxx (填你在Clerk获取的私钥)

# 下面这四个是登录跳转的路由，保持原样不用动它！
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
</code></pre>
<h3 id="3--api">3. 其他杂项 API</h3><pre class="language-env lang-env"><code class="language-env lang-env">TMDB_API_KEY=

GH_TOKEN=ghp_xxxxxxxxxxxxxxxxx
</code></pre>
<ul><li><code>TMDB_API_KEY</code> ：TMDB 是一个电影数据库。Yohaku 博客里支持展示电影卡片。如果你暂时不想搞，可以留空（留空可能电影页面没数据，但不影响网站整体运行）。如果想搞，去 themoviedb.org 申请个 API 填进来。</li><li><code>GH_TOKEN</code> ：GitHub 动态展示的 Token。你可以直接把上一步申请的那串 ghp_ 开头的“万能钥匙”填在这里。</li></ul><h2 id="github-actions">GitHub Actions</h2><p>接下来前往仓库的 Action 页面，由 GitHub Actions 对该项目进行预构建。</p><ol start="1"><li>点击顶部的 <strong>Actions</strong> 标签页。</li><li>如果看到一个提示说 「I understand my workflows, go ahead and enable them」，就点击绿色的按钮同意启用。</li><li>在左侧菜单点击工作流名字 <strong>Build and Deploy</strong>。</li><li>在右边找到一个写着 <strong>Run workflow</strong> 的按钮，点它，然后再点弹出的绿色 <strong>Run workflow</strong>。</li></ol><p>如果不存在 Run workflow 按钮，则点进 <code>.github/workflows/</code> 文件夹，打开 <code>deploy.yml</code>，点击右上角编辑（笔）按钮，随后点击 <strong>Commit changes</strong>。</p><blockquote class="markdown-alert-note"><header>NOTE</header>
<p>当点击保存（Commit）时，系统就会认为你更新了代码（触发 push），随后自行开始 Build and Deploy。</p></blockquote>
<h2 id="">意外处理</h2><p>如果在使用 GitHub Action 构建 Yohaku 时存在错误，并且日志表现为：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">0s
Run sh ./ci-release-build.sh
  sh ./ci-release-build.sh
  shell: /usr/bin/bash -e {0}
  env:
    HASH_FILE: build_hash
    PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
    BASE_URL: ***
    NEXT_PUBLIC_API_URL: ***
    NEXT_PUBLIC_GATEWAY_URL: ***
No projects matched the filters in &quot;/home/runner/work/shiroi-deploy-action/shiroi-deploy-action&quot;
./ci-release-build.sh: 8: cd: can&#x27;t cd to apps/web/.next
Error: Process completed with exit code 2.
</code></pre>
<p>则可尝试对 <code>deploy.yml</code> 做以下修改：</p><blockquote class="markdown-alert-caution"><header>CAUTION</header>
<p>此方法为个人依据错误分析，并结合 AI Agent 建议进行的修订，可能存在某些暂未发现的 BUG。如果你也遇到了类似的问题，可以尝试联系作者，或者在 GitHub 的 Issue 下提交问题。</p></blockquote>
<pre class="language-yml lang-yml"><code class="language-yml lang-yml">name: Build and Deploy

on:
  push:
    branches:
      - main
  # schedule:
  #   - cron: &#x27;0 3 * * *&#x27;

  repository_dispatch:
    types: [trigger-workflow]

permissions: write-all
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  HASH_FILE: build_hash
  SOURCE_REPO: innei-dev/Yohaku
  BUILD_COMMAND: pnpm --filter @yohaku/web build:ci
  STANDALONE_SUBPATH: standalone/apps/web

jobs:
  prepare:
    name: Prepare
    runs-on: ubuntu-latest
    if: ${{ github.event.head_commit.message != &#x27;Update hash file&#x27; }}

    outputs:
      hash_content: ${{ steps.read_hash.outputs.hash_content }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Read HASH_FILE content
        id: read_hash
        run: |
          content=$(cat ${{ env.HASH_FILE }}) || true
          echo &quot;hash_content=$content&quot; &gt;&gt; &quot;$GITHUB_OUTPUT&quot;
  check:
    name: Check Should Rebuild
    runs-on: ubuntu-latest
    needs: prepare
    outputs:
      canceled: ${{ steps.use_content.outputs.canceled }}

    steps:
      - uses: actions/checkout@v4
        with:
          repository: innei-dev/Yohaku
          token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
          fetch-depth: 0
          lfs: true
          submodules: recursive

      - name: Use content from prev job and compare
        id: use_content
        env:
          FILE_HASH: ${{ needs.prepare.outputs.hash_content }}
        run: |
          file_hash=$FILE_HASH
          current_hash=$(git rev-parse --short HEAD)
          echo &quot;File Hash: $file_hash&quot;
          echo &quot;Current Git Hash: $current_hash&quot;
          if [ &quot;$file_hash&quot; == &quot;$current_hash&quot; ]; then
            echo &quot;Hashes match. Stopping workflow.&quot;
            echo &quot;canceled=true&quot; &gt;&gt; $GITHUB_OUTPUT
          else
            echo &quot;Hashes do not match. Continuing workflow.&quot;
          fi

  build:
    name: Build artifact
    runs-on: ubuntu-latest
    needs: check
    if: ${{needs.check.outputs.canceled != &#x27;true&#x27;}}

    strategy:
      matrix:
        node-version: [lts/*]
    outputs:
      sha_short: ${{ steps.store.outputs.sha_short }}
      branch: ${{ steps.store.outputs.branch }}
    steps:
      - uses: actions/checkout@v4
        with:
          repository: ${{ env.SOURCE_REPO }}
          token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
          fetch-depth: 0
          lfs: true
          submodules: recursive

      - name: Checkout LFS objects
        run: git lfs checkout
      - uses: pnpm/action-setup@v2

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: &#x27;pnpm&#x27;
      - uses: jongwooo/next-cache@v1
      - name: Install dependencies
        run: pnpm install
      - name: Build project
        env:
          BASE_URL: ${{ secrets.BASE_URL }}
          NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
          NEXT_PUBLIC_GATEWAY_URL: ${{ secrets.NEXT_PUBLIC_GATEWAY_URL }}
        run: |
          ${{ env.BUILD_COMMAND }}
          cd apps/web/.next
          rm -rf cache
          cp -r ../public ./standalone/public
          mv ./static ./standalone/apps/web/.next/static
          cd ./standalone
          echo &#x27;;process.title = &quot;Yohaku (NextJS)&quot;&#x27; &gt;&gt; server.js
          cd &quot;$GITHUB_WORKSPACE&quot;
          mkdir -p assets
          rm -f assets/release.zip
          (cd apps/web/.next &amp;&amp; zip --symlinks -r &quot;$GITHUB_WORKSPACE/assets/release.zip&quot; ./* -x &quot;dev/*&quot; -x &quot;cache/*&quot;)

      # - uses: actions/upload-artifact@v4
      #   with:
      #     name: dist
      #     path: assets/release.zip
      #     retention-days: 7
      - name: Cache Build Artifacts
        id: cache-primes
        uses: actions/cache/save@v4
        with:
          path: assets
          key: ${{ github.run_number }}-release

      - name: Store artifact commit version
        shell: bash
        id: store
        run: |
          sha_short=$(git rev-parse --short HEAD)
          branch_name=$(git rev-parse --abbrev-ref HEAD)
          echo &quot;sha_short=$sha_short&quot; &gt;&gt; &quot;$GITHUB_OUTPUT&quot;
          echo &quot;branch=$branch_name&quot; &gt;&gt; &quot;$GITHUB_OUTPUT&quot;

  deploy:
    name: Deploy artifact
    runs-on: ubuntu-latest
    needs: build
    steps:
      # - name: Download artifact
      #   uses: actions/download-artifact@v4
      #   with:
      #     name: dist

      - name: Restore cached Build Artifacts
        id: cache-primes-restore
        uses: actions/cache/restore@v4
        with:
          path: |
            assets
          key: ${{ github.run_number }}-release
      - name: Move assets to root
        run: mv assets/release.zip release.zip

      - name: Create PM2 config file
        run: |
          cat &gt; ecosystem.config.js &lt;&lt; &#x27;EOF&#x27;
          module.exports = {
            apps: [
              {
                name: &#x27;Shiroi&#x27;,
                script: &#x27;./server.js&#x27;,
                cwd: __dirname,
                exec_mode: &#x27;fork&#x27;,
                instances: 1,
                autorestart: true,
                watch: false,
                max_memory_restart: &#x27;180M&#x27;,
                env: {
                  NODE_ENV: &#x27;production&#x27;,
                  HOSTNAME: &#x27;0.0.0.0&#x27;,
                  PORT: process.env.PORT || 2323,
                },
                log_date_format: &#x27;YYYY-MM-DD HH:mm:ss&#x27;,
                merge_logs: true,
              },
            ],
          };
          EOF

      - name: copy file via ssh password
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          password: ${{ secrets.PASSWORD }}
          key: ${{ secrets.KEY }}
          port: ${{ secrets.PORT }}
          source: &#x27;release.zip&#x27;
          target: &#x27;/tmp/yohaku&#x27;

      - name: copy PM2 config via ssh password
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          password: ${{ secrets.PASSWORD }}
          key: ${{ secrets.KEY }}
          port: ${{ secrets.PORT }}
          source: &#x27;ecosystem.config.js&#x27;
          target: &#x27;/tmp/yohaku&#x27;

      - name: Exec deploy script with SSH
        uses: appleboy/ssh-action@master

        with:
          command_timeout: 5m
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          password: ${{ secrets.PASSWORD }}
          key: ${{ secrets.KEY }}
          port: ${{ secrets.PORT }}
          script: |
            set -e
            source $HOME/.bashrc
            basedir=$HOME/yohaku
            workdir=$basedir/${{ github.run_number }}
            mkdir -p $workdir
            mkdir -p $basedir/.cache
            mv /tmp/yohaku/release.zip $workdir/release.zip
            install -m 644 /tmp/yohaku/ecosystem.config.js $basedir/ecosystem.config.js
            cd $workdir
            unzip -qq -o $workdir/release.zip
            rm -r /tmp/yohaku
            rm -rf $workdir/${{ env.STANDALONE_SUBPATH }}/.env
            ln -s $HOME/yohaku/.env $workdir/${{ env.STANDALONE_SUBPATH }}/.env
            export NEXT_SHARP_PATH=$(npm root -g)/sharp
            # https://github.com/Unitech/pm2/issues/3054
            # symlink workdir node entry file to basedir
            ln -sf $workdir/${{ env.STANDALONE_SUBPATH }}/server.js $basedir/server.js
            mkdir -p $workdir/${{ env.STANDALONE_SUBPATH }}/.next
            rm -rf $workdir/${{ env.STANDALONE_SUBPATH }}/.next/cache
            ln -sf $basedir/.cache $workdir/${{ env.STANDALONE_SUBPATH }}/.next/cache
            cd $basedir
            if pm2 describe Shiroi &gt;/dev/null 2&gt;&amp;1; then
              pm2 reload ecosystem.config.js --update-env
            else
              pm2 start ecosystem.config.js --update-env
            fi
            rm $workdir/release.zip
            pm2 save
            echo &quot;Deployed successfully&quot;

      - name: After deploy script
        run: |
          hash=${{ needs.build.outputs.sha_short }}
          # curl -X &quot;POST&quot; &quot;https://mx.innei.in/api/v2/fn/shiro/new-version-hook&quot; -H &#x27;Content-Type: application/json&#x27; -d &quot;{\&quot;hash\&quot;: \&quot;$hash\&quot;, \&quot;key\&quot;: \&quot;\&quot;}&quot;
          ${{ secrets.AFTER_DEPLOY_SCRIPT }}
  store:
    name: Store artifact commit version
    runs-on: ubuntu-latest
    needs: [deploy, build]
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
          fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
      # Get the commit version from the build job
      - name: Use outputs from build
        env:
          SHA_SHORT: ${{ needs.build.outputs.sha_short }}
          BRANCH: ${{ needs.build.outputs.branch }}
        run: |
          echo &quot;SHA Short from build: $SHA_SHORT&quot;
          echo &quot;Branch from build: $BRANCH&quot;
      - name: Write hash to file
        env:
          SHA_SHORT: ${{ needs.build.outputs.sha_short }}

        run: echo $SHA_SHORT &gt; ${{ env.HASH_FILE }}
      - name: Commit files
        run: |
          git config --local user.email &quot;41898282+github-actions[bot]@users.noreply.github.com&quot;
          git config --local user.name &quot;github-actions[bot]&quot;
          git add ${{ env.HASH_FILE }}
          git commit -a -m &quot;Update hash file&quot;
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }}
</code></pre>
<h2 id="-mixspace-">在 MixSpace 配置</h2><blockquote class="markdown-alert-note"><header>NOTE</header>
<p>与此部分内容有关的官方文档：</p><p><a href="https://mx-space.js.org/docs/themes/shiro/deploy">https://mx-space.js.org/docs/themes/shiro/deploy</a></p></blockquote>
<p>进入 Mix Space 后台，进入「配置与云函数」页面，点击右上角的新增按钮，在编辑页面中，填入以下设置：</p><ul><li>名称：<code>shiro</code></li><li>引用：<code>theme</code></li><li>数据类型：<code>JSON</code></li><li>数据（此处以官方示例数据为模板）：</li></ul><pre class="language-json lang-json"><code class="language-json lang-json">{
  &quot;footer&quot;: {
    &quot;otherInfo&quot;: {
      &quot;date&quot;: &quot;2020-{{now}}&quot;,
      &quot;icp&quot;: {
        &quot;text&quot;: &quot;萌 ICP 备 20236136 号&quot;,
        &quot;link&quot;: &quot;https://icp.gov.moe/?keyword=20236136&quot;
      }
    },
    &quot;linkSections&quot;: [
      {
        &quot;name&quot;: &quot;关于&quot;,
        &quot;links&quot;: [
          {
            &quot;name&quot;: &quot;关于本站&quot;,
            &quot;href&quot;: &quot;/about-site&quot;
          },
          {
            &quot;name&quot;: &quot;关于我&quot;,
            &quot;href&quot;: &quot;/about&quot;
          },
          {
            &quot;name&quot;: &quot;关于此项目&quot;,
            &quot;href&quot;: &quot;https://github.com/innei/Shiro&quot;,
            &quot;external&quot;: true
          }
        ]
      },
      {
        &quot;name&quot;: &quot;更多&quot;,
        &quot;links&quot;: [
          {
            &quot;name&quot;: &quot;时间线&quot;,
            &quot;href&quot;: &quot;/timeline&quot;
          },
          {
            &quot;name&quot;: &quot;友链&quot;,
            &quot;href&quot;: &quot;/friends&quot;
          },
          {
            &quot;name&quot;: &quot;监控&quot;,
            &quot;href&quot;: &quot;https://status.innei.in/status/main&quot;,
            &quot;external&quot;: true
          }
        ]
      },
      {
        &quot;name&quot;: &quot;联系&quot;,
        &quot;links&quot;: [
          {
            &quot;name&quot;: &quot;写留言&quot;,
            &quot;href&quot;: &quot;/message&quot;
          },
          {
            &quot;name&quot;: &quot;发邮件&quot;,
            &quot;href&quot;: &quot;mailto:i@innei.ren&quot;,
            &quot;external&quot;: true
          },
          {
            &quot;name&quot;: &quot;GitHub&quot;,
            &quot;href&quot;: &quot;https://github.com/innei&quot;,
            &quot;external&quot;: true
          }
        ]
      }
    ]
  },
  &quot;config&quot;: {
    &quot;color&quot;: {
      &quot;light&quot;: [
        &quot;#33A6B8&quot;,
        &quot;#FF6666&quot;,
        &quot;#26A69A&quot;,
        &quot;#fb7287&quot;,
        &quot;#69a6cc&quot;,
        &quot;#F11A7B&quot;,
        &quot;#78C1F3&quot;,
        &quot;#FF6666&quot;,
        &quot;#7ACDF6&quot;
      ],
      &quot;dark&quot;: [
        &quot;#F596AA&quot;,
        &quot;#A0A7D4&quot;,
        &quot;#ff7b7b&quot;,
        &quot;#99D8CF&quot;,
        &quot;#838BC6&quot;,
        &quot;#FFE5AD&quot;,
        &quot;#9BE8D8&quot;,
        &quot;#A1CCD1&quot;,
        &quot;#EAAEBA&quot;
      ]
    },
 
    &quot;bg&quot;: [
      &quot;/static/images/F0q8mwwaIAEtird.jpeg&quot;,
      &quot;/static/images/IMG_2111.jpeg.webp.jpg&quot;
    ],
    &quot;custom&quot;: {
      &quot;css&quot;: [],
      &quot;styles&quot;: [],
      &quot;js&quot;: [],
      &quot;scripts&quot;: []
    },
    &quot;site&quot;: {
      &quot;favicon&quot;: &quot;/innei.svg&quot;,
      &quot;faviconDark&quot;: &quot;/innei-dark.svg&quot;
    },
    &quot;hero&quot;: {
      &quot;title&quot;: {
        &quot;template&quot;: [
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;Hi, I&#x27;m &quot;,
            &quot;class&quot;: &quot;font-light text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;Innei&quot;,
            &quot;class&quot;: &quot;font-medium mx-2 text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;👋。&quot;,
            &quot;class&quot;: &quot;font-light text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;br&quot;
          },
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;A NodeJS Full Stack &quot;,
            &quot;class&quot;: &quot;font-light text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;code&quot;,
            &quot;text&quot;: &quot;&lt;Developer /&gt;&quot;,
            &quot;class&quot;: &quot;font-medium mx-2 text-3xl rounded p-1 bg-gray-200 dark:bg-gray-800/0 hover:dark:bg-gray-800/100 bg-opacity-0 hover:bg-opacity-100 transition-background duration-200&quot;
          },
          {
            &quot;type&quot;: &quot;span&quot;,
            &quot;class&quot;: &quot;inline-block w-[1px] h-8 -bottom-2 relative bg-gray-800/80 dark:bg-gray-200/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 group-hover:animation-blink&quot;
          }
        ]
      },
      &quot;description&quot;: &quot;An independent developer coding with love.&quot;
    },
    &quot;module&quot;: {
      &quot;activity&quot;: {
        &quot;enable&quot;: true,
        &quot;endpoint&quot;: &quot;/fn/ps/update&quot;
      },
      &quot;donate&quot;: {
        &quot;enable&quot;: true,
        &quot;link&quot;: &quot;https://afdian.net/@Innei&quot;,
        &quot;qrcode&quot;: [
          &quot;/static/images/20191211132347.png&quot;,
          &quot;/static/images/0424213144.png&quot;
        ]
      },
      &quot;bilibili&quot;: {
        &quot;liveId&quot;: 1434499
      }
    }
  }
}
</code></pre>
<p>点击按钮保存配置。</p><h1 id="">最后</h1><p>本次部署 Yohaku 的过程，本质上是一次对现代 CI/CD 工作流的实战演练。从宝塔面板的环境纠偏，到 GitHub Actions 的深度调试，每解决一个 <code>Error</code> 都是对自身知识体系的重构。</p><p>部署成功只是第一步，真正的乐趣在于后续的创作或定制。如果你在参考本文过程中遇到了新的“玄学问题”，欢迎在评论区留言交流，或者直接向作者 Innei 请教。希望这篇文章能在你搭建个人空间时提供关键帮助。</p></div><p style="text-align:right"><a href="https://devuki.com/posts/research/yohaku-deploy#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/posts/research/yohaku-deploy</link><guid isPermaLink="true">https://devuki.com/posts/research/yohaku-deploy</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Fri, 10 Apr 2026 19:32:27 GMT</pubDate></item><item><title><![CDATA[这是一个测试文章]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://devuki.com/posts/default/the-test-page">https://devuki.com/posts/default/the-test-page</a></blockquote><div><p>这是一个测试文章，用来测试一些功能性问题。</p><h1 id="-markdown-">🚀 Markdown 格式压力测试</h1><h2 id="-">一、 基础文本样式</h2><p>你可以让文字变得 <strong>加粗</strong>，或者使用 <em>斜体</em> 来增加一点点文艺范儿。当然，如果你想表达“这行字我后悔了”，直接用 <del>删除线</del> 划掉就好。</p><blockquote><p><strong>小贴士</strong>：适当的留白和引用可以让你的文档看起来更有质感，而不是像一堆乱码。</p></blockquote>
<hr/><h2 id="-">二、 逻辑组织（列表）</h2><h3 id="1-">1. 任务清单</h3><ul><li><input readOnly="" type="checkbox" checked=""/> 完成 Markdown 模板编写</li><li><input readOnly="" type="checkbox"/> 调戏一下 AI 助手</li><li><input readOnly="" type="checkbox"/> 喝一杯拿铁咖啡</li></ul><h3 id="2-">2. 有序与无序列表</h3><ul><li><strong>水果类</strong>
<ol start="1"><li>苹果（一天一个，医生远离我）</li><li>芒果（小心过敏哦）</li></ol></li><li><strong>技能类</strong>
<ul><li>Python 编程</li><li><del>魔法少女变身</del>（划掉）</li></ul></li></ul><hr/><h2 id="-">三、 技术与数据展示</h2><h3 id="1--python-">1. 代码块（以 Python 为例）</h3><pre class="language-python lang-python"><code class="language-python lang-python">def hello_world():
    message = &quot;Hello, Markdown!&quot;
    print(message)
    return True
</code></pre>
<h3 id="2-">2. 简单表格</h3><table><thead><tr><th style="text-align:left"> 属性 </th><th style="text-align:left"> 描述 </th><th style="text-align:center"> 状态 </th></tr></thead><tbody><tr><td style="text-align:left"> 易读性 </td><td style="text-align:left"> 极高 </td><td style="text-align:center"> ✅ </td></tr><tr><td style="text-align:left"> 复杂度 </td><td style="text-align:left"> 低 </td><td style="text-align:center"> 🌟 </td></tr><tr><td style="text-align:left"> 幽默感 </td><td style="text-align:left"> 适量 </td><td style="text-align:center"> <code>这是一个实例.php</code> </td></tr></tbody></table><hr/><h2 id="-">四、 数学公式与链接</h2><p>如果需要处理复杂的数学逻辑，LaTeX 也是不在话下的。比如这个勾股定理：</p><p>$$</p><p>a^2 + b^2 = c^2</p><p>$$</p><h2 id="-">五 、折叠摘要块</h2><details><summary>摘要</summary><p>这是一个折叠区域</p></details><p>想了解更多？欢迎访问 <a href="https://www.google.com">Google 搜索</a>。</p></div><p style="text-align:right"><a href="https://devuki.com/posts/default/the-test-page#comments">览毕，何不一言？</a></p></div>]]></description><link>https://devuki.com/posts/default/the-test-page</link><guid isPermaLink="true">https://devuki.com/posts/default/the-test-page</guid><dc:creator><![CDATA[Devuki]]></dc:creator><pubDate>Thu, 22 Mar 2018 14:33:21 GMT</pubDate></item></channel></rss>