<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Carm&apos;s Home</title>
    <link>https://www.carm.cc</link>
    <description>Carm&apos;s Home。卡姆的个人主页，展示我的技术栈、项目经验和设计作品。</description>
    <language>zh</language>
    <lastBuildDate>Tue, 20 Oct 2026 20:03:11 GMT</lastBuildDate>
    <atom:link href="https://www.carm.cc/feed/index.xml" rel="self" type="application/rss+xml"/>
    <generator>homesite RSS generator</generator>
    <webMaster>carm@carm.cc</webMaster>
    <copyright>2014-2026 © CarmJos, All rights reserved.</copyright>

    <item>
      <title>江新旧笺</title>
      <link>https://pages.carm.cc/article/2026/letter-stories</link>
      <guid isPermaLink="true">https://pages.carm.cc/article/2026/letter-stories</guid>
      <pubDate>Mon, 19 Oct 2026 23:00:00 GMT</pubDate>
      <description><![CDATA[旧教学楼将拆，我重读与夏卿卿在新中往来的信笺，想起一段始于青春、终于沉默的心事，以及多年后仍留在纸上的余温。]]></description>
      <content:encoded><![CDATA[<div class="admonition note"><p class="admonition-title">作者声明</p><p>本文场景、出场人物与具体内容均为虚构，如有雷同，纯属巧合。</p></div><p>新中旧教学楼要拆的消息，附在几张照片后面，字很少。</p><p>照片里，脚手架沿着外墙一层层搭上去，走廊的绿栏杆缺了一段。我认出三楼靠西的那扇窗：玻璃少了一块，另一块上还留着白色的水痕。从前轮到我值日，我站在椅子上擦它，湿抹布来回擦过几遍，看着已经干净了，等水一干，那些浅浅的印子又浮出来。</p><p>如今窗后的教室空着。等屋顶也被拆去，雨便会落进我当年坐过的地方。</p><p>我把照片放大，看了很久，才起身去拿书架深处的纸盒。</p><p>纸盒原是蓝色的，随我搬过几次家，如今褪得很淡。四角补着透明胶带，有一角已经翘起来，沾着灰。每到一个新住处，我总先替它找个不容易受潮的地方。里面是她的来信，还有我留下的去信底稿。信封的封舌起了毛，几片褐红色的封蜡散在盒底。</p><p>我将最上面的一张放到灯下。折过的地方已薄得有些透光，字却仍清楚。写下它们时用力太重，有几个笔画，隔着纸背也能摸到。</p><h2 id="秋天迟来的学生"><a href="#秋天迟来的学生" class="headerlink" title="秋天迟来的学生"></a>秋天迟来的学生</h2><p>我回到宏谭镇时，桂花已快开尽。</p><p>宏谭在西南边陲，山一重重围着，镇前有条河，入冬以后水浅，露出河心灰白的石头。去县城的班车每天只有几趟，清晨停在桥头，司机开着门，等拎菜篮的老人慢慢走过来。老街沿河伸出去，修表铺、药店、邮局，隔不了几步便是一家。下雨时，每间铺子的雨棚都有自己的漏处，住久了的人经过，知道在哪儿稍稍偏一下肩。</p><p>江新中学在镇东的缓坡上，人们都叫它“新中”。旧教学楼背靠着山，楼下几株桂树挨着洗拖把的水池。花落了，细小的黄点贴在湿地上，有些顺水走了，有些留在砖缝里。下午，山影已经盖住操场，三楼的窗仍能留一阵太阳。</p><p>返校那天，我沿走廊走得很慢。里面的人正低头写字，偶尔有谁咳嗽，声音隔着门传出来，比脚步声还清楚。到了拐角，一片叶子黏在鞋尖，我弯腰去拂，书包却从肩上滑下，碰翻了墙边的水桶。水在地上铺开。我蹲下来扶好桶，把带子重新拉上肩，一时竟不愿站起来。</p><p>以前熟悉的人大多已经毕业离开了。</p><p>我个子高，被安排在教室后半部。周围的人都不熟，椅子又有一条腿稍短，挪一下便响。我整天留意着这点声响，每次挪动身子，都先把手撑在桌沿。</p><p>夏卿卿坐在靠窗的那一列。</p><p>起初，我常看见她用尺子压试卷。她将尺子横过来，拇指顺着纸边一抹，卷起的角便服帖了。有时窗外的光挪到她手上，她就把卷子往里收一点，继续写。那时候，看别人做这些细小而笃定的事，我也会羡慕很久。她偶尔抬头，撞见我的目光。我立刻低下去，装作找笔。笔其实就在手里，被我握得发热。</p><p>后来，我想到了那件一直没送出去的裙子。它原是为家中一个妹妹准备的，叠在柜子里，浅色的裙摆一铺开，便占去半张床。我将它取出来，抚平折痕，心里已经备好许多理由：夏卿卿像她，衣服应当合适，搁着又可惜。想着想着，竟觉得这是一件再自然不过的事。</p><p>可真要开口时，我仍不敢。</p><p>中午放学铃响，她在前面收书，我把装好的袋子提起来，又放下。一直等到教室空了大半，我才草草用便签写了两行英文。那两句话短得几乎不必修改，我却读了许多遍，连一个寻常的词，都渐渐看得不认得了。</p><figure class="hexo-letter" data-paper="sticky" style="--hlp-paper:#fff29b;--hlp-ink:#26221e;--hlp-tilt:-0.8deg;--hlp-font-size:1.5rem;--hlp-indent:0em;--hlp-font-family:&#39;hlp-font-qianhe&#39;;--hlp-font-weight:400" data-letter-label="便签 · 陆"><button type="button" class="hexo-letter__fold" hidden aria-label="打开便签 · 陆" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__unindented">I have a gift for you.  </p><p>我有一份礼物要送给你。</p><p class="hexo-letter__unindented">Without any purpose but to find a suitable owner for the suit.  </p><p>别无他意，只是想为这套衣服找到一位合适的主人。</p></blockquote></div></figure><p>午饭回来，我就看到书下也压着一个便签，写道</p><figure class="hexo-letter" data-paper="sticky" style="--hlp-paper:#fff29b;--hlp-ink:#244b87;--hlp-tilt:0.8deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="便签 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开便签 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__unindented">Thank you for your warm heart.  </p><p><em>感谢你的好意。</em></p><p class="hexo-letter__unindented">But I can&#39;t understand why you give me such a &quot;gift&quot;. It&#39;s incorrect for someone who unfamiliar with me to do good on me. Everyone should keep a distance that can provide safe-sense for each other. Although you&#39;re not bad or do things in purpose, I have no reason to accept your present naturally. </p><p><em>但我实在不明白，你为何要送我这样的“礼物”。对于并不熟悉我的人而言，对我施以善意并不妥当。人与人之间应当保持一定的距离，以给予彼此安全感。虽然你并无恶意，也并非有意为之，但我实在没有理由理所当然地接受你的这份馈赠。</em></p><p class="hexo-letter__unindented">Thus I&#39;m sorry to decline it.  </p><p><em>因此，很抱歉，我只能拒绝。</em></p></blockquote></div></figure><p>读完便签，我心里骤然冷了一半；但仍不死心，又拿了一张纸，想把送裙子的缘由说清楚。</p><figure class="hexo-letter" data-paper="sticky" style="--hlp-paper:#fff29b;--hlp-ink:#26221e;--hlp-tilt:-0.6deg;--hlp-font-size:1.5rem;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-qianhe&#39;;--hlp-font-weight:400" data-letter-label="便签 · 陆"><button type="button" class="hexo-letter__fold" hidden aria-label="打开便签 · 陆" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__unindented">Thank you for being honest with me. I&#39;m sorry my gesture made you uncomfortable.</p><p><em>谢谢你对我坦诚相告。很抱歉，我的举动让你感到不舒服了。</em></p><p class="hexo-letter__unindented">I wanted you to have it because you remind me of her, and I thought it would suit you elegantly. There was nothing more to it, and I expected nothing in return.You may be perfectly fine without it. But without you, it would once again lose the person it was meant for.</p><p><em>我把它送给你，是因为你让我想起了她，而且我觉得它戴在你身上一定会非常优雅。除此之外别无他意，我也没指望过什么回报。</em><em>或许没有这件礼物，你依然能过得很好；但如果少了你，它就又一次失去了它原本的主人。</em></p><p class="hexo-letter__unindented">That is why I offered it—not a reason you have to accept it. You owe me nothing, and I will respect whatever you decide.</p><p><em>这就是我送出它的初衷 — 但这并非你必须接受它的理由。你不欠我什么，无论你做出什么决定，我都会尊重。</em></p></blockquote></div></figure><p>放学前，我有幸的收到了她的回复：</p><figure class="hexo-letter" data-paper="sticky" style="--hlp-paper:#fff29b;--hlp-ink:#244b87;--hlp-tilt:0.6deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="便签 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开便签 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__unindented"><strong>Re:</strong><br>All right, it&#39;s my honor.  </p><p><em>好吧，这是我的荣幸。</em></p><p class="hexo-letter__unindented">But what I should declare is I&#39;m not a girl who behave elegantly, just an ordinary, dull and somehow bad-tempered man.<br>Therefore, you might regret have given it to me in recent furture.  </p><p><em>不过我得先声明：我可不是什么举止优雅的女孩，而只是个平凡、无趣，甚至脾气还有点糟糕的人。所以，没准儿过不了多久，你就会后悔把它交给我了。</em></p><p class="hexo-letter__unindented">Taylor Swift:&quot;Cause I&#39;m a nightmare dressed like a daydream.&quot;<br>(字面意思，不要多想)</p></blockquote></div></figure><p>她终于收下了。我将袋子递过去的情形，后来记得已经不很真切，只记得空下来的手，一路都不知道往哪里放。</p><p><strong>当然，我一直没有见她穿过那件裙子。</strong></p><p>接下来的日子，她仍旧在课前翻书，课后收卷子。困了就趴下睡一会儿，铃声一响，抬起压红了的脸，皱着眉找笔。有一次，笔滚到两排桌椅之间，我的椅子刚响了一声，她已经弯腰捡起来了。</p><p>我又坐回去，把一页没有看完的书翻了过去。</p><h2 id="一张照片"><a href="#一张照片" class="headerlink" title="一张照片"></a>一张照片</h2><p>秋天快过去的时候，我总把相机带在身上。</p><p>山里的雾散得慢，晴天到了上午，河对岸的屋顶才一片片亮起来。有人把洗好的衣服挑到竹竿上，水从裤脚滴下去，墙根便深一块、浅一块。我常站在窗前等，等鸟离开电线，等云影走过山坡，等一件很小的东西恰好出现在光里。</p><p>有一天，我将镜头转向了教室里面。</p><p>她没有看我。快门轻轻一响，恰好有人翻书，把那点声响盖过去了。我低头看屏幕，画面中的一切都显得安静，连远处一张歪着的课桌，也像是应该在那里。</p><p>我独自高兴了一会儿，心想着把这张照片送到她手上；随即也有些不安，担心这样又破坏了什么所谓的“距离感”。</p><p>于是我写下“道歉”，附上照片。发送前，又将她的名字后面补了“同学”两个字，觉得这样郑重一些。那时我能想到的周全，大多就是如此。</p><figure class="hexo-letter" data-paper="kraft" style="--hlp-paper:#d6b98b;--hlp-ink:#26221e;--hlp-tilt:-0.2deg;--hlp-font-size:1.5rem;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-qianhe&#39;;--hlp-font-weight:400" data-letter-label="照片附言 · 陆"><button type="button" class="hexo-letter__fold" hidden aria-label="打开照片附言 · 陆" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>夏卿卿同学：</strong> </p><p>我必须向你道歉：在没有征得你同意的情况下擅自拍下了你的照片。  </p><p>然而美好的画面往往在不自知、不经意间产生。正如这一张照片般自然而然甜美，无限散发着青春的美好与芬芳。</p><p>倘若你并不喜欢这张相片，还请原谅我的莽撞，我会悉数删除。但若你也觉得不错，我便将原画传给你，好让自己在未来的某一日回顾当年的时光。  </p><div style="text-align: right; text-indent: 0;"><strong>陆</strong></div></blockquote></div></figure><p>也是当天，我就收到了她的答复</p><figure class="hexo-letter" data-paper="kraft" style="--hlp-paper:#d6b98b;--hlp-ink:#26221e;--hlp-tilt:0.2deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="关于照片的答复 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开关于照片的答复 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>陆薪筠：</strong>  </p><p>谢谢你的Photos，但是听到别人给自己偷拍了照片还是会给人带来恐慌和不必要的困扰的。所以希望你在我不知情或不允许的时候不要抓拍了。</p><p>Maybe 暮秋时节澄澈的天空或生活里的一花一木更能让你丰盈四季的美好，是更易逝难擢的。  </p><p>四季尚有更替，  </p><p>但时光一去难忆。  </p><p>若是错过了，  </p><p>就在难想见到了。  </p><p>诚然窗外金桂动人，  </p><p>却不抵 <strong>流光一逝</strong> 。  </p><div style="text-align: right; text-indent: 0;"><strong>— X77</strong></div></blockquote></div></figure><p>我先记住了她写天空和花木的那几行。放学经过楼下的桂树，还停下来，看了看枝间所剩无几的花。可再打开回复，开头那几句仍在原处，绕不过去。</p><p>我把相机收回袋子。拉链有些涩，在半途卡住，我低着头拉了两下，才拉拢。夏卿卿还在收拾课本。我走出教室，没有留下来等。</p><p>回到住处，我删掉相机里的照片，又取出存储卡，找到了原片。确认框出现时，我的手停了一会儿，最终还是没有按下删除键。后面一张河岸的照片移了上来，水面很亮，我却已经看不进去了。</p><p>后来，我仍拍过许多东西：旧水管上将落未落的一滴水，雨停以前颜色很深的山，门卫室灯下斜靠着的一把扫帚。走到她那一排座位附近时，相机留在袋里。我能听见肩带上的小扣随着脚步，轻轻碰着拉链。</p><p>纸盒里，与这份誊录挨在一起的，还有一张更小的纸。</p><p>那阵子，我常带自己做的吃食去学校。休学时，我在厨房里学会了一些事：面团要等，糖融到浅金色时火须调小；偶尔做成一回，整间屋子都有暖的气味。回到新中，我仍想借这些本领，让自己不至于在人群里全无用处。</p><p>分给别人的，我可以随手一递。给她的那一份，我却常在出门前拆开重包，挑一个不容易碎的放在最上面。</p><p>有一回，我将纸袋放进她桌侧的书袋，想这样便不会引人注意。后来拿到那张小纸条，我先看见的，是开头那句谢谢。</p><figure class="hexo-letter" data-paper="sticky" style="--hlp-paper:#fff29b;--hlp-ink:#244b87;--hlp-tilt:-0.8deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="零食纸条 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开零食纸条 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>陆薪筠：</strong>  </p><p>谢谢你的零食。  </p><p>“无功不受禄”。任何人都不难毫无理由地频繁地接受别人的零食。感谢你的善意，但这也诚然令人惶恐。有时好意也会成为别人的负担。  </p><div style="text-align: right; text-indent: 0;"><strong>— X77</strong></div></blockquote></div></figure><p>我把纸条摊在掌心。字不多，纸却已经被我折过两次，展开时总有一角翘着。</p><p>午休，我去操场边坐了一会儿，吃掉原本留着、还想再带给她的一份。糖已经凉透，比在厨房时硬了些，咬下去，碎屑落进袋底。我将纸袋抬高，想把最后一点倒出来，弄了半天，袖口也沾上了。</p><p>围墙外有人推车经过，车轮碾着碎石，响了一阵，便远了。操场那么空，我在那儿坐到预备铃响。</p><h2 id="借来的勇气"><a href="#借来的勇气" class="headerlink" title="借来的勇气"></a>借来的勇气</h2><p>十一月，我恰巧读到一篇短篇小说<a href="https://www.douban.com/note/704756865/?_i=2458442h4dovAy">《破碎故事之心》</a>。越读越觉得神奇，故事里的人物、情节、语言，都像是从我身边的生活里抽出来的。我取出纸，写了几行，觉得每一句都太重，便撕掉了。第二次写，我先告诉她自己读过什么。借着那个故事，有些不敢当面说的话，似乎终于可以开口。</p><figure class="hexo-letter" data-paper="kraft" style="--hlp-paper:#d6b98b;--hlp-ink:#26221e;--hlp-tilt:0.25deg;--hlp-font-size:1.5rem;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-qianhe&#39;;--hlp-font-weight:400" data-letter-label="11 月 8 日 · 陆"><button type="button" class="hexo-letter__fold" hidden aria-label="打开11 月 8 日 · 陆" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>夏卿卿：</strong>  </p><p>《破碎故事之心》写的非常棒。或许优秀的作家总能将俗套的世界用美妙的故事呈现，让人读后总能联想到身边的事 — 甚至是眼前的事情 — 如同小说般充满戏剧性。我觉得羞愧 — 愧于我先前所言所说，或许故事的开端显得那么自然而毫无目的，但剧情的发展就犹如凌晨三点不断拍打沙滩的海浪，想要推进却又迅速退回；我亦觉得羞涩 — 羞于我想要所言所写，不光光是看到几封可能写给莱斯特小姐的信让我对自己的内容开始不自信，更是想到那一封封不同的回信 — 当然也有不回信 — 让我忍不住去怀疑我所写是否真的有意义。于是我撕毁了它，丢掉了它。既然已在纸上的形如埃利奥特先生梦魇般的错误答案，那就提笔再做一封罢。  </p><p>我多次注意到你 — 当然你也多次注意到我正在看着你，你的行为真好像我远在长沙已在上大学的表妹，甚至样貌上也有几分神似。但能预测到的是，你应当不会像她一样每天以“呆瓜”称呼我，以“滚”命令我 — 当然这只是日常玩笑。于是我尝试给你送点好吃的，同时也等待着你的小纸条，来斥责我的“好意”。然而我思来想去，盯着“惶恐”二字久久不得一解。我常以为自己不过是一直体形硕大而人畜无害的困倦团团，怎么在眼下看来竟成了吃人的怪兽般让人“惶恐”了呢。但其实我深知，一个“不太好接近”的女孩怎么可能欣然接受不明所以的赠礼呢。何况周围人杂，难免引得他人误会，此般行径便更应当“痛斥”了吧！  </p><p>然而我一向愚钝笨拙，不知如何开口，或是起笔。这应该就是如同霍根施拉格“夺包”般的可笑举动。或许我应当问问你喜欢听些什么音乐，有没有兴趣唱歌，或是其他你感兴趣而我又恰巧能能帮助你些什么的事情。但是我没有机会，也没有合适的、能让你接受的理由去问。我胆怯了。我只知道自己只是一个爱听听音乐，写写代码，做做美食，拍拍照片的普通团团，没有华丽的能吸引人的外表，亦没有能让他人信赖的内涵。对此我常感到孤独与无奈 — 当然，这是题外话了。  </p><p>我似乎真如同霍根施拉格先生一般，“从没有人说过我好看”，也“不指望你会回信”。与原本的那封信大不相同，我“只想让你知道实情”。然而我却知道你绝对与莱斯特小姐大有不同。不过都无妨，或许天下佳话皆有因，或许天下美事皆无果。  </p><p>看到这里，你大可以丢掉这篇不知所言的书信了。它应该毫无意义 — 起码在我的设想里。  </p><div style="text-align: right; text-indent: 0;"><strong>11月8日</strong><br><strong>陆</strong></div></blockquote></div></figure><p>从这封信起，我渐渐养成了留底稿的习惯。誊清时删掉的句子、还没改好的字，留在手里，倒比送出去的那一份更长久。</p><p>装进信封以前，我还给她裁了几张同样的纸，四角对齐，夹在信后。那句“不指望你会回信”明明是自己写的，放进回信用纸时，我却一点也没有迟疑。</p><p>接下来的四天，我忽然很会听教室里的细小声响。她拉开笔袋，我抬一下头；她折起一张纸，我便把眼前的书往后翻一页，仿佛自己并未注意。到了晚上，又后悔白天太留意她，猜想那些笨拙的掩饰是不是全被看见了。有时我已经把书包收好，听见后面仍有人说话，便又取出一本书，装作还有什么没看完。直到那一排桌子空下来，我才起身。</p><h2 id="木香未开"><a href="#木香未开" class="headerlink" title="木香未开"></a>木香未开</h2><p>十一月十二日，信在我的课本下面。</p><p>抽出书时，它被带出来一点，我先看见那道斜折的纸角。伸手去拿，手指却从纸边滑了过去。我把书放回桌上，重新取了一次，才把那几页薄纸拿稳。</p><p>窗边有人叫她一起去交作业。她抱起一摞本子，走到门口；我等她走出去，才低下头。</p><p>第一行便是她替我的那点掩饰起的名字。</p><figure class="hexo-letter" data-paper="plain" style="--hlp-paper:#fffdf8;--hlp-ink:#26221e;--hlp-tilt:-0.25deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="11 月 12 日 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开11 月 12 日 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p><strong>设想之内的骗局</strong>  </p><p>好吧，请与我用略带讽刺的语言写完这个小标题。试问，倘若你设想之内不会有我的回复，那又何来我正在提笔而上“精美”的纸张呢？或许我不该这样写，而是回复一些诸如“谢谢你为我准备好的纸张，我正好想回信”一类的话。然而只怕是善良的莱斯特小姐（记不清名字了）也要不免在背后吐槽起来了。  </p><p><strong>拒绝理想化</strong>  </p><p>我很荣幸可以找到与自己相像的人，但或许你只是看到了我想展现给别人的一面，而不是我最真实的一面（可能这些早就在你的想象中脑补好了）。我很抱歉带给你的误扰，但我作为一个平平无奇的高中生，确实没什么亮点，更没有什么安静、高雅、优美的贵族品质。至于你印象中的我，大底是你想象出的理想化人格。我可以打别人、骂别人，甚至说别人坏话，只是在一般情况下不这么做而已。 </p><p><strong>关于兴趣</strong>  </p><p>你对我的兴趣爱好感到好奇令人有些“受宠若惊”。不过告诉朋友也没什么大不了的。下面浅浅谈一下。  </p><p>Taylor Swift 是我从小崇拜的歌手，对她的热爱是从小时候听的《Love Story》开始的。《Daylight》、《exile》等也很好听（极度推荐这几首）。有时也听韩国（女团）的歌。  </p><p>花花草草我也很喜欢，木香花真的棒，我家养了两盆，甩香。和其他孩子一样，我也like养小动物，就像我妈养饲我一样。  </p><p>近期特别喜欢冰雪奇缘里的snowman雪宝，可爱、幽默而有爱。当然还有斯特（小驯鹿）。  </p><p>其他就没什么了。  </p><p>我回信很慢，别介意。  </p><div style="text-align: right; text-indent: 0;"><strong>夏卿卿</strong><br><strong>11月12日</strong></div></blockquote></div></figure><p>我笑了一下，嘴角还没落下去，就下意识地望向窗边。她的座位空着，桌上压着一张做了一半的卷子。</p><p>这封信我读了三遍。头两遍找能使自己高兴的字，读到“朋友”，便停一会儿；第三遍，才慢慢读到她会打人、骂人，也会说别人的坏话。那几句话将我心里那个总是安静坐着的影子挪开了一点。再看窗边的空椅子，忽然觉得自己知道的实在很少。</p><p>我把信收好，没多久，又拿出来。</p><p>一到家，我就搜了搜她所说的木香花。照片从上往下一点点显出来。花开得细碎，白的、浅黄的，挤在一根枝上。我用手指把它放大，看过叶子，又去看花期。十一月的屏幕上已经满枝是花，窗外的风却正吹得人缩起脖子。</p><p>我想过买一株，商品页开着，迟迟没有往下点。信上说她家里已经养了两盆。我关掉页面，重新读了一遍那句不很郑重的“甩香”。</p><p>那晚，我听了听她写在信上的歌。手机伏在枕边，光调得很暗，耳机线从被角垂下去。楼下有人洗衣服，接水声从歌曲的间隙里进来。我有几次差点睡着，又在换歌时醒过来，伸手摸一摸手机，看清歌名。</p><p>第二天，在教室门外，她抱着书从人群中挤出来，书角轻轻碰了一下我的袖子。她侧身，我也侧身；让到同一边以后，两个人又各自挪开半步。那一小段路总算让出来了，她便抱着书过去。</p><p>我回到座位，抚了抚袖口，取出纸。其实有许多寻常的话可以说，我却还是从她信上提到的小动物写起。</p><h2 id="信纸背面"><a href="#信纸背面" class="headerlink" title="信纸背面"></a>信纸背面</h2><p>她写了几首歌、两盆花和喜欢的小动物。我也翻出歌单，想着把自己的事告诉她。写着写着，一页纸又添了一页。</p><p>写到小七，笔慢了下来。我记得它小时候伏在门槛上，整个身子晒热了，摸起来像刚从太阳下收回的一件厚衣服。可要说它如今的模样，我却写不出来。我去翻相册，翻网盘，却关于它的照片也少得很。笔搁在纸上，积出一个很深的墨点。我换了张纸，接着写下去。</p><p>这封信的底稿，末尾还留着两段。我誊清时没有将它们抄进去，只在前面标了“弃用”。那时我已经写得太多，又还想让她觉得，自己是个可以轻松相处的人。</p><figure class="hexo-letter" data-paper="kraft" style="--hlp-paper:#d6b98b;--hlp-ink:#26221e;--hlp-tilt:0.25deg;--hlp-font-size:1.5rem;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-qianhe&#39;;--hlp-font-weight:400" data-letter-label="11 月 13 日 · 陆先生"><button type="button" class="hexo-letter__fold" hidden aria-label="打开11 月 13 日 · 陆先生" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>夏卿卿小姐：</strong>  </p><p>启信佳。  </p><p>如今我也感受到霍根施拉格先生收到莱斯特小姐回信时那般欢喜雀跃了。虽说“并不期待能有回信”，但实际上却是尝试欺骗自己，去躲避那可能到来的失望罢！正如你所言，哪怕是美丽善良的莱斯特小姐，也可以轻松察觉到这其中的“骗局”。如此看来，再杂乱混沌的文字也藏不住我的小心思。  </p><p>我自诩这些文字是“平淡高中生活中微微泛起的可爱波澜”，但不知对你而言是否只是“无趣的打搅”；我自认为小巧的纸张似乎更适合你些，但不知你是否更爱笔尖划过牛皮纸时那独特的声响......许许多多皆来自我自以为是的猜想。倘若有任何不如你意，还请一一告知；若是能再指导些许便更好。  </p><p>我还不知道你是不是一个爱笑的姑娘，但我总觉得你的笑容闪着光。应该是我了解甚少，亦或是还没有什么机会能与你交流，你在我心目中的形象确实更多构造于我所能观察到的 — 即你所想表现出的。尚且不知能否在你的文字之下，见到你丰富多彩的灿烂形象。</p><p>我仔细翻了翻我所喜爱的音乐列表，发现我以往的成长历程尽藏其中。早些时候 — 大概是初中时，我常常显得不那么合群。那时的我酷爱电子设备，而身边人却沉醉于冒险与卡牌。每日回家的路途上，唯有电子音乐低沉或明悦的鼓点能伴我左右。那时的我自感孤独，但也大概明白或许是环境使然，幼稚的孩童总归更关注触手可得的愉快。往后一年，我开始爱上了含人声的曲子，也常常在某时某地的某一个场景，理解某首歌中歌词的含义。而在中考前夕，我尝试做的几个项目，全部宣告失败，无一例外。至此我开始进入自我否决与自我放弃的状态。那些时日里，耳机里流淌的不再是轻快美妙《Flower Dance》，亦不是纯粹激昂《Masked Heroes》，取而代之的是引人伤感的《Losing interest》《Drunk and confused》。内容大多是一句或几句话的重复，一遍又一遍洗刷着我为数不多的情绪。我开始不爱去学校，变得沉默、寡言，鲜与人分享自己的观点，亦或是我好像失去了自己的观点。我陷入了一个“必定失败”的自我认知，于是我便在如此悲观中步入了高中时代。至此之后的故事则更加波澜，你若感兴趣，我再好好述说给你。当然，你也可以去瞧瞧我的列表，看看心思缜密的你能不能也从中看出些什么。  </p><p>我颇爱小生命 — 节肢动物除外。自我记事以来，养过大小宠物数只。记忆里最清晰的，是大概小学时开始养起的一只拉布拉多犬。父亲偷偷买下它回家，为此还遭了母亲一顿骂。然而几句后，她已然给这只刚来家里的小狗取了名：小七。正与当时热映的《神犬小七》中的主角同名。它确实是一直活泼而健壮的犬，特殊的血统使它小小年纪便强过周边绝大多数的野狗，金色而富有光泽的毛发让它看起来如同王子般散发着特殊魅力，令人甚为喜爱。但不久，我便转学离开了原本生活的小镇，亦难得见到他了。听父亲说，它已被送到爷爷奶奶家照顾，每日吃着剩菜和骨头 — 虽说不如狗粮营养均衡，但它似乎更爱这些人类的食物。而爷爷又爱他太过，食物总给的极多。没过多久，它健壮的身材就失了形，但仍是镇上那英气的存在。再后来，奶奶身体状态不佳，常住院，不回家。它只能被送去新人家。听闻是做了服装厂的看门犬，聪慧识人，威风不减，只是伙食不如以前。倘若它还健在，现在应该已是中年了。不知道它是不是还喜欢蹦跳？不晓得它是否还英姿飒爽？如今只能后悔没能多留下几张相片好做念想。若是还有机会能养一只宠物，那我绝不再忍受让它离开身边的苦痛，也定要用镜头记录下它用一生陪伴我的时光。  </p><p>我新购了笔墨，想着能写些好看的模样能赠你。然而事与愿违 — 我越想一气呵成的写出一套文字，行笔就愈加丑陋变形、难以言喻。美好的期许还需要点时间实现，随信附上两句今天的字，好请你验验未来我的书写是否有所长进。  </p><p>行文杂乱，不知所言。书短意长，还望允我慢自陈叙。  </p><p>祝生活愉快。  </p><div style="text-align: right; text-indent: 0;"><strong>11月13日</strong><br><strong>陆先生</strong></div></blockquote></div></figure><p>信写完了，我仍在桌前坐了很久。</p><p>我把一滴蜡落在信封折角，手抬得迟了，蜡便多出一些。印章压下去，边缘溢出一个不匀的圈。我俯下身看，想修齐，又怕碰坏，只好等它一点点凉透。</p><p>等的时候，我想到她要怎样拆开它，会不会觉得麻烦；又想，只要拿到信，总归要拆的。这个小小的念头，使我在灯下无端高兴了一阵。</p><p>纸、贴画、封蜡，还有试写的字，慢慢占去书桌大半位置。对面人家的窗一扇扇暗下来，我这里还亮着。将一处折好，再将另一处压平，一夜便可以这样过去。白天没能说成的话，在夜里似乎都有办法安顿。</p><p>几天以后，教室换座位。我的桌子离窗更远，夏卿卿移到前面。过道窄，她试了两次，又用膝盖抵住桌脚，将那张沉重的桌子挪过去。我已经拿起书包，想着腾出手去帮她；等书包放好，她也坐下了。</p><p>我将桌上的书叠整齐。先前那扇窗被另一排人挡住，往后再抬头，只能看见她椅背上搭着的外套。</p><h2 id="雨从山里来"><a href="#雨从山里来" class="headerlink" title="雨从山里来"></a>雨从山里来</h2><p>宏谭的冬天，是跟着一场雨来的。</p><p>雨接连下了几日，山顶不见了，晾在屋檐下的衣服总有一点潮。清晨到学校，伞上的水滴了一路，脚印从楼梯一直深到教室门口。大家挤在走廊上等开门，把冷手缩进袖子。</p><p>夏卿卿站在前面，摘下眼镜，擦掉镜片上的水珠。我想问她冷不冷，话在嘴边停着。想好怎样问以后，又觉得这话无须问：她也正将手往袖里收。</p><p>门锁响了，前面的人开始往里走。我跟着人群迈过门槛，给她让开一点地方。</p><p>十一月二十二日，回信到了。</p><p>我还以为自己会像上一次那样，一见她的字就先笑起来。打开信时，窗玻璃正被雨水慢慢淋花，教室里很安静，前排有人轻轻咬着笔帽。</p><figure class="hexo-letter" data-paper="plain" style="--hlp-paper:#fffdf8;--hlp-ink:#26221e;--hlp-tilt:-0.25deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="11 月 22 日 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开11 月 22 日 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>陆XY:</strong>  </p><p>Accordingly, 我是个极懒的人，所以回信慢是在正常不过的。在这，我本不喜欢玩弄墨宝废大周折回信，或许线上回消息是更便捷的。  </p><p>对于那只拉布拉多，我只能为他惋惜。我相信一个爱犬的人是不绝不会把“至宝“转手他人的，至少绝大多数人是这样的。总之，被抛弃的小狗就像被丢弃的孩子，既不能好好的陪伴他，又为什么领他回家呢？意满兴尽则弃之？  </p><p>见谅，我没有多少兴趣去观法别人的经历或兴趣，除非某个人真正勾起了我少有的灵感和动力（愚拙的人都是这样的），否则我绝不会做这些“无聊”的事。你或许并不知道我是个无情冷漠的人，绝对不是你想象中的善良聪慧的女生（不过现在你知道了）。不错，我向来不惮用最坏的想法叵测他人，无论是多要好的朋友（亲人例外）。感谢你十分精心的准备每一封信，甚至漆上印章、插入照片，这对每个人来说都是不可多得的。然而这样的真心实意不是我配拥有的，也不是我可以拥有的。  </p><p>“团团”一类幼齿化语言，不瞒你说，是很令我反感的，当然，你也可以忽略我这样挑剔刻薄的想法。这类戏谑的语言用在恰当的时候才适合。我也体会到这只是个被用来描述自己的玩笑词，所以并没有过多的难受感触。  </p><p>近期总有不好的预感，毕竟这个月学习上颓废了许多，很难不亏心。至于我这样的入学分数极低的小学渣，实在难以想象590分是如何考出的，实在相形见绌。还有一百多天的高三，让我感觉就像身处拘留所中的狱犯一样，还有一百多天就要被执以死刑。这样荒谬的想法在脑中病态蔓延许久，难怪我自己是个怪人。  </p><div style="text-align: right; text-indent: 0;"><strong>夏卿卿</strong><br><strong>11月22日</strong></div></blockquote></div></figure><p>我将信翻到背面。薄纸透出些墨色，远看像写了另一封信，却没有哪一个字能辨认清楚。我用掌心将纸压住，等了片刻，才重新翻回来。</p><p>有几句读得太快，仿佛眼睛一掠过去，便可以不算看见；有几句又看了许久，慢到身旁的人翻了几次书，我还停在同一处。</p><p>放学后，我没有去阅览室。回到住处，开了听歌的软件，又关掉。耳机留在手里，缠好，松开，再缠了一回。屋檐下的雨水不停，窗缝里有风，吹得桌上那封信轻轻动了一下。</p><p>她说不喜欢我的一些称呼，说不愿看那些经历。那一天，我所能听见的几乎只有这些。直到再读，才看见她也写了考试，写了疲倦，写了那一百多天如何压在心上。</p><h2 id="道歉之后"><a href="#道歉之后" class="headerlink" title="道歉之后"></a>道歉之后</h2><p>十一月二十七日，桌上又多了一封信。</p><p>前一夜，我还写过几句委屈的话。有的写完立即划去，有的留着，第二天早晨看又觉得过分。草稿折在书里，一整天，书都没再打开。</p><p>这封新来的信比上次短。我拿在手里，先以为她还有什么要补充，读到第一句，指尖却松了一下，纸页往掌心滑了滑。</p><figure class="hexo-letter" data-paper="plain" style="--hlp-paper:#fffdf8;--hlp-ink:#26221e;--hlp-tilt:0.25deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="11 月 27 日 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开11 月 27 日 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>陆薪筠：</strong>  </p><p>抱歉，我对我上一封信表达罪恶的愧疚感所写下的内容深感罪恶与愧疚。  </p><p>上个星期一直处于疲倦学习的懈怠状态，处事、说话都带有火药味。对不起，上次的笔调着实有些锋利，我确实不该用这样的刺刃怒目而向他人，希望你能谅解。当然，你不原谅，我也能接受。毕竟如果道歉有用的话还要警察干嘛。  </p><p>如果你可以接受道歉的话，我希望我们之间可以保持良好的同学或朋友关系。如果你拒绝的话，那我也只好因自己的bad nature破坏一段友好的人际关系了(你也不用为这封信犹豫，认可与否都在一念之间，错本就在我)。  </p><div style="text-align: right; text-indent: 0;"><strong>夏卿卿</strong><br><strong>11月27日</strong></div></blockquote></div></figure><p>她说可以做同学，或者朋友。我把这两个词挨着读，觉得哪一个都并不坏。可想到明天在走廊上见面，仍不知道该怎样叫她。</p><p>晚上，我打开消息窗口，写下“没关系”，又删掉。添上去的话，也没能留下。我按灭手机，取出纸。纸上的话可以重写，也可以停着。我仍以为，多给自己一点时间，就能把它们说清楚。</p><p>那封原本想写得简短的信，到了半夜还没有写完。</p><figure class="hexo-letter" data-paper="kraft" style="--hlp-paper:#d6b98b;--hlp-ink:#26221e;--hlp-tilt:-0.25deg;--hlp-font-size:1.5rem;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-qianhe&#39;;--hlp-font-weight:400" data-letter-label="11 月 29 日 · 陆先生"><button type="button" class="hexo-letter__fold" hidden aria-label="打开11 月 29 日 · 陆先生" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>夏卿卿小姐：</strong>  </p><p>展信安。  </p><p>伴你信件而来的还有渐寒的冬日。一次意想不到的“道歉”让我也开始捉摸不透自己的心思：究竟是冰冷的凉风吹干了我的思绪，还是自己面对你的文字着实不知道言语。  </p><p>闲来苦闷的日子里，我时常反复读你的来信。一句句得去推敲是否有什么隐藏的含义 — 就像我所写的那样。我在想，你是否真的能读懂我的第一封信？是否能看出我正把自己比作霍根施拉格先生？然而答案不难察觉，你“并不感兴趣”，亦觉得我“无聊”，但出于礼貌地保持一个“良好的朋友关系”。怪我，确实怪我。人各有志，亦各有喜。感谢你久久以来对我的礼貌尊重，我也尽量简明的述清我的感想。  </p><p>我常以为书信所蕴含的意味是如今即时消息远不及的，也唯有书信能允我有时间咬文嚼字，好教我述清我那时所想。一套精美的书信是我最精心准备的礼品，而其中的寥寥话语更是我邀你以文字交谈最盛情的邀请。不知道当你打开我的信时，有没有感受到所谓的仪式感？你说“这是许多人不可多得的”，以至于“不配拥有”。而我说，这些文字因你而起，或许没有这些机遇，我此生也难以写出这些“晦涩难懂”的呓语。倘若未来的某日，你会想起我写的这些东西，再翻箱倒柜的找出来读一遍，那我便觉得一切均是值得的。 </p><p>除了书信之外，我也很想有些其他与你交流的机会与途径。然而当面说话困难至极，寥寥几句便足以让我纠结数日；即时消息更令我恐惧 — 每每收到你给我发些什么的提示，我总如心脏骤停般紧张不已，但又能猜想到大致的内容 — 无非就是“谢谢”但“不要”尔尔。  </p><p>我总像个做错事的小孩，望着文本框不知所措，尝试用几个表情图片掩盖住屏幕前脑袋空空的我。不知道如何理解你的话语，更害怕说些什么做些什么会让你不悦 — 现在看来似乎是处处都踩进了坑里。我应该告诉你，这一切都是在期待着“交换”，而非单方面“赠予”。无论是零食，还是书信；无关于次数，也无关于价值。然而小说里的一句话写的很好“爱是想要触碰却又收回手”，我所期许的可能也正是你几句随性的话，却又饱含对拒绝的恐惧而放弃表达。  </p><p>从你的言谈里，能感受到很好的气度和教养。“婉言谢礼”“文明用语”“知者不为”等等，本是人人都应该做的，而如今可能已经淡化。你能做的这么好，确实难能可贵。在这些事情上，我应当向你学习才是。长久的逃避社交已经让我逐渐忘却了许多礼仪，以至于现在说话总是口无遮拦，做事总是自以为是。感谢你的指正，我的确应当反省。  </p><p>至于“团团”，确实只是一个类似“橐驼”的自称词。“胖子”略显普通，而“肥肥”更显幼稚，最后选择“团团”自称，好显得自己不那么难以接近。而“团团”的另一含义，也是对我自己脾性的一个自我认定。我基本从不生气 — 除非是涉及所爱之物。而我的体形之大，体质又差，也是“胖”字可以概括的。至于我素来爱吃，乐于品茶好饮，大概就是我“胖”的原因。无论如何，你不喜欢，我便以姓代之。</p><p>关于“小七”，你觉得惋惜，我亦觉得痛心。现实虽不及小说笔下那般辛辣，但也不同于童话一样甜美。人人都期许着一个美好的结局，然而不经意间身处的故事线已悄然转向“BAD ENDING”。确实如你所言，现今去看也只能怪罪我当时幼稚，没有能力留住陪伴我多年的他，也并没有让当时劳顿的父母省心。到了奶奶病重之时，数月难回，无论我们多爱他，所能做的也唯有为他寻一个好人家。对我来说，我失去了一位从小的玩伴；对他而言，他失去了一个原本温馨的家。大概这就是我这一生的遗憾。  </p><p>考试结束了，祝贺你仍然正常地发挥着你的水平。有能力的人无论做些什么都不会差。至于能做到多好，就在于其愿意投入的时间与精力有多少。对我来说，这次的结果并不如我意，若是两年前的我，我此时应该急得不行，但此刻我却颇感欣喜。我发觉实现目标的过程有了路径，甚至划了指引。我对自己还算有信心，亦期待你能踏上更高的阶梯，实现你的理想，独创属于你的篇章。  </p><p>书短意长，还望允我慢自叙述。寒风苦雨，厚自珍重。<br>祝前程似锦。  </p><div style="text-align: right; text-indent: 0;"><strong>11月29日</strong><br><strong>陆先生</strong></div></blockquote></div></figure><p>誊完最后一个字，右手中指上蹭着一片蓝墨。我去洗手，水流过指节，蓝色淡了些，仍不肯全退。</p><p>回到灯下再读，有几句太用力，有几句绕得连我自己也费解。我提起笔，想改，最后只描清了一处不太容易辨认的字。那时还不明白，哪些话值得说，哪些只是怕对方不知道自己难过。</p><p>第二天，信封到了她桌上。我转身回座位，听见身后有人拉开椅子，没有回头。</p><p>那以后，卷子仍一张张发下来。日子也渐渐平淡而重复着了。</p><h2 id="回音的消失"><a href="#回音的消失" class="headerlink" title="回音的消失"></a>回音的消失</h2><p>我又送了她一个小挂件。包装纸裁得很小，接缝朝下。我以为这样便不显得郑重。</p><p>包装纸裁了又裁，我尽量包得小，让它握在掌心时不显得郑重。胶带在接缝处留下一道亮痕，我用指腹压了两遍。送到她桌边时，我把那条接缝朝下，像这样放好，便能少给她一点为难。</p><p>十二月十一日，我收到了回赠。东西装在一个寻常的袋子里，袋口折过两次，压在书下面。我拿起来，先看见夹在里面的纸边。回到座位，我把袋子放进抽屉，怕压皱了信，便单独将它抽出来。</p><figure class="hexo-letter" data-paper="plain" style="--hlp-paper:#fffdf8;--hlp-ink:#26221e;--hlp-tilt:0.25deg;--hlp-font-size:1.25em;--hlp-indent:2em;--hlp-font-family:&#39;hlp-font-xiaonaipao&#39;;--hlp-font-weight:400" data-letter-label="12 月 11 日 · 夏卿卿"><button type="button" class="hexo-letter__fold" hidden aria-label="打开12 月 11 日 · 夏卿卿" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation"><strong>陆薪筠：</strong>  </p><p>拖了一个星期回信，见谅。  </p><p>上次你送我的礼物，属实有些意外。今天略备了些下东西作为回赠。准备仓促，没找到合适的袋子或者盒子，还请见谅。不过话说回来，我不喜欢别人刻意送我东西，这会让人猝不及防。再者，如今已是高三，仅存一百多天，我不希望花太多时间在“思考送别人什么东西”上。是以，仅以这封仓促的回信，作为往来信件的结尾吧。  </p><p>友情可以是漫长的等待，但绝不是旁敲侧击、敲山震虎，也绝不是对他人徒增的烦恼与困惑给他人徒增烦恼与困惑。  </p><div style="text-align: right; text-indent: 0;"><strong>夏卿卿</strong><br><strong>12月11日</strong></div></blockquote></div></figure><p>读到“结尾”时，我停了下来。</p><p>前排有人转身借橡皮，我从笔袋里拿给他。隔了一会儿，他还回来，随口说了句谢谢。我点点头，等他转回去，才重新低头看信。</p><p>从头读到落款，也没有花去多少时间。窗外的山影已越过操场，桌边最后一点太阳落在手背上，慢慢退到指尖，随后也没有了。</p><p>我沿着原来的折痕，把信折好。第一次没有折齐，露出窄窄的一边，便又打开，重新对了一次。</p><p>那晚，我仍取了一张新纸。名字写在左上角，后面是一个冒号。再往下写什么，我想了很久。隔壁的人拖动椅子，开水壶响起来，又停了。我手里的笔一直悬着，直到笔尖上的那一点墨快要干了，才将笔帽合上。</p><p>那张纸没有送出去。后来做题时，我在它的背面写过半页算式，随后就丢到了废纸篓里。</p><h2 id="毕业以前"><a href="#毕业以前" class="headerlink" title="毕业以前"></a>毕业以前</h2><p>冬天很长。早晨仍有人迟到，提着没拉好的书包跑进来；中午，热水机前照旧排着队；测验开始，窗缝里的风将最外侧的一张卷子吹得微微翘起，写字的人伸手一压，便继续往下写。</p><p>我的椅子后来稳了。哪天有人在桌脚边收拾，顺手垫了一片东西，我竟没有留意。等到发现，已经记不得它从什么时候起不再响。我试着往后靠了一点，又往前坐好。</p><p>我和夏卿卿还在同一间教室里。她去交卷，从我身旁经过；值日时，我将公共练习册往前传，她接住，再交给前面的人。有一天，全班为一件小事笑起来，我听见她也笑了。那声音混在许多人中间，并不容易分清，我却在低头的片刻，也跟着笑了一下。</p><p>春天来的时候，我们还穿着冬衣。</p><p>围墙外的李树先白了一片。雨水多起来，河面渐渐涨高，湿气沿坡路漫进学校，卷子压在书里，取出来边角仍是软的。课间有人展开地图，找自己想去的城市。手指越过熟悉的省界，停到很远的地方，过一会儿，又回来看看离家究竟有多远。</p><p><strong>我没有问她想去哪里。</strong></p><p>最后一天，我从书包里摸出相机，在毕业典礼上，拍了不少合照。有幸的是，朋友借着我的相机，也拍了一张我和她的合照。</p><p>匆匆结束后，大家又各自回到教室里。教室里比平时乱的多。抽屉倒出许多纸，有人蹲在地上捆书，有人在别人摊开的本子上写名字、留地址。窗户全开着，风将一张卷子吹到过道里，被经过的人顺脚踩住，又弯腰拾起来。那些约定再见的话，在桌椅间轻快地来回。好像将来的路并不远，只消在桥头等一班车，大家就还能回来，坐在原先的位置。</p><p>夏卿卿在擦桌面。湿纸巾用过一面，折起来，又擦了一次桌角。等水稍干，她将最后一本书装进包。那把常用来压卷子的尺子滑下来，她伸手接住，横着放在书脊上。我看着她背起包，忽然把“一路顺风”那句话想好了。</p><p>她走过一排桌子，前面有人让开，书包轻轻擦了一下椅背。到了门口，她停了停，回身去取讲台边的外套。我也抬起头，以为自己这次总能开口。可她很快找到了外套，搭在臂上，跟着门外的人流下楼去了。</p><p>楼梯上有许多脚步声。我站了一会儿，直到再也分不出哪一声可能是她的，才低下头，继续系书包那条始终没系好的带子。</p><p>在新中，我们往来过那么多文字，却没有面对面好好聊过一次天。毕业以后，也没有再联系。</p><p>离开前，我把椅子推回桌下。窗帘被风扬起，河水的亮光从两幢楼之间露出一线。楼下有人关门，接着是一串钥匙相碰的声音。我扶了一下门框，从楼梯走下去，手上沾了很薄的一层灰。</p><h2 id="旧纸微温"><a href="#旧纸微温" class="headerlink" title="旧纸微温"></a>旧纸微温</h2><p>后来，我离开宏谭，去过一些从前只在地图上见过的地方。</p><p>偶尔也会想起夏卿卿。有时是一首歌，有时是别处阳台上垂下来的一枝木香。有一年春天，我从别人家门前经过，花枝伸出栏杆，低头让开时闻到一点香。走出几步，才想起她曾在信上说，家里养了两盆。</p><p>我不知道那些花后来怎么样，不知道她住在哪座城，也不知道递出去的信是否还留着。有时候想起，会在一件正在做的事上稍停一下，随后把手里的杯子洗净，或将没写完的几行字写完。</p><p>我仍做饭，拍照，写些有用或无用的程序。遇见有趣的事，也会说给身边的人听。有的话能接下去，有的话说完就停在那里。渐渐地，我已经可以在这样的停顿里，安稳地坐一会儿。</p><p>打开纸盒的这天，我住的城市也在下雨。窗没有关严，一阵风来，最上面的信纸被吹到桌沿。我伸手接住，挪开杯子，把去信的底稿和她的回信依次放好。</p><p>有张信纸的边缘卷着。我用指腹慢慢抹过去，抹到折痕，便停住。那里已经很薄，再使一点力，怕就要裂开。风又将纸角掀起一点，我把手掌轻轻放上去。</p><p>纸很凉。等了一会儿，掌心下那一小片，才渐渐平了。</p>]]></content:encoded>
      <category>随笔</category>
      <category>书信</category>
      <category>爱情</category>
      <category>感情</category>
      <category>微小说</category>
    </item>

    <item>
      <title>记一次公益摄影——让所长有所用，让所思有所养。</title>
      <link>https://pages.carm.cc/story/2026/care-for-the-elderly</link>
      <guid isPermaLink="true">https://pages.carm.cc/story/2026/care-for-the-elderly</guid>
      <pubDate>Wed, 14 Oct 2026 09:45:00 GMT</pubDate>
      <description><![CDATA[10月14日，我同向阳花志愿服务队走进句容刘家庄敬老院，为老人们免费摄影。从一张“天安门合影”的愿望，到照片的后期、打印与交付，我重新想了想养老，也想了想《礼记·礼运》的现实写照。]]></description>
      <content:encoded><![CDATA[<blockquote><p>“拍好看不？” “老了不好看了。” “老了人不行了。”</p><p>给老人拍照时，这样的问题总让我很认真。</p><p>我一一回应，帮他们整理好头发与衣物，再慢慢调整姿势。年纪大了，哪怕是简单的动作做起来也已经不那么容易。一张看似寻常的肖像照，也需要大家一起费些心思。</p></blockquote><p>10月14日，我和向阳花志愿服务队到了句容的刘家庄敬老院，为院里的老人免费拍照。事情的开头很简单，做完以后，留下的问题却比预想的多。</p><h2 id="一个早就有过的念头"><a href="#一个早就有过的念头" class="headerlink" title="一个早就有过的念头"></a>一个早就有过的念头</h2><p>早些年在家乡，我便常给周边的老人无偿拍过照。只是那时拍得很散，谁有需要便来找我，时间也不固定。拍完了，处理好，交到手上，一件事情便算结束。</p><p>后来我想，既然自己已经有一些经验，也有能力把这件事情做好，为什么不能主动组织一次，让更多老人一起拍呢？</p><p>我把这个念头告诉了刘书记。她很支持，向我推荐了一位养老院负责人，微信名叫“多肉妈妈 句容社区养老”。</p><p>她叫彭敏。她所关心的是社区养老、家庭养老，也真正在做这件事。我联系了她，约定时间和地点，简单了解院里老人的数量，再把活动内容规划下来。为了让整体活动更丰富，我联合了向阳花志愿服务队一起参与。他们准备了水果和反诈指导，拍摄时，又帮我逐一记下老人的姓名与照片编号。</p><p>这些准备都很琐碎，但非常有必要。因为照片不只是光拍，还得整理、修图和交付，这意味着我必须得知道每一个编号对应的是谁，才好把照片送回正确的人手里。从前零散地帮忙，到这回主动把人和事情联系起来，我才更切实地感觉到，一个念头要落地，还需要有人把前前后后的事情接起来。</p><p><img src="images/SERVING.jpg" loading="lazy"></p><h2 id="一个农村大院"><a href="#一个农村大院" class="headerlink" title="一个农村大院"></a>一个农村大院</h2><p>刘家庄敬老院给我的第一印象，是小而温馨。</p><p><img src="images/DOG.jpg" loading="lazy"></p><p>它是一个农村的大院子。走进这里，养老便有了很具体的样子：住在院里的人，照料他们的人，以及每天都要继续的生活。</p><p>这家院子的具体运营，我了解得还不多。此次与彭阿姨联系，让我有机会走进院里，也把原本的一个想法，变成了一件可以一起做的事情。社区养老所连接的，既有家庭，也有专业照护和周边服务；日间照料、协助服务、康复护理，以及老人之间的交往，都在其中。具体到不同地方，服务的形式又会不同。</p><p>我想到《礼记·礼运》里那句“<strong>不独亲其亲</strong>”。</p><p>人总该会先学会关心自己的家人的。可当我们把目光稍稍向外移一点，就可以看到还有许多与自己没有亲缘的人，也需要被照料。回到眼前这个院子里，虽在同在一处生活，需要照顾的事情却各不相同。我们可能只是到访一次，完成一次活动，然后离开；院里的生活却要一天一天继续下去。这样的关照，靠的一定是长久的耐心和细致的付出。</p><h2 id="镜头前的人"><a href="#镜头前的人" class="headerlink" title="镜头前的人"></a>镜头前的人</h2><p>真正开始拍摄后，我愈发觉得，“老人”这两个字，实在装不下这么多不同的人。有的老人已经很难独立行动，起身、挪动都要依靠旁人搀扶，还有的只能卧床。对我们而言很轻巧的一个动作，放到他们身上就显得有些困难，得慢慢来。</p><p>有的老人很少回应我们，甚至没有明显的回应。他们看起来像在出神，又像一直在想着什么。我不知道他们正在想什么，也无法从短暂的接触里判断原因，只能尽量留意他们当下的状态。</p><p>也有的老人精气神很好，年纪虽大，笑脸却很舒展。还有一位老人，衣服穿得格外鲜艳，人却显得没什么精神，似乎总在避开视线。那亮眼的衣服与躲闪的目光，我到现在还记得。也有老人面对镜头，会先关心自己拍出来好不好看。</p><blockquote><p>“老了不好看了。”</p></blockquote><p>我听着这句话，就更想着能把照片拍好一些。我会回应他们的担心，帮着整理头发与衣物，引导坐姿和表情，再根据每个人能做到的程度，调整抬头、低头的角度。实在难以在现场处理好的，就留到后期多费一点工夫。</p><p>一边拍，一边能听见老人们道谢。谢谢我们过来，谢谢我们替他们拍照。那些反复说起的感谢，让我很难把这件事只当作拍完、收工便结束的活动。对我来说，拍照与修图都是熟悉的事情——或许这也算是“壮有所用”了吧。而对他们来说，一次被认真整理衣领、被耐心回应、被好好拍下来的经历，或许已经值得这样郑重地感谢。</p><p>我所能做的，便是把眼前这一位拍好，再把下一位也拍好。<img src="images/PHOTO.jpg" loading="lazy"></p><h2 id="在“天安门”前"><a href="#在“天安门”前" class="headerlink" title="在“天安门”前"></a>在“天安门”前</h2><p>“天安门”的背景，是一位爷爷提出的。他一辈子没出过这地方，往后可能也难有机会了，便想着能不能和天安门有一张照片。</p><p>我不知道该怎样衡量这个愿望。对于常常能够出门、能够安排下一次旅行的人来说，一张真实照片似乎很容易；可对这位爷爷来说，那是他这一生没有抵达过的地方。后来，其他老人也陆续提出，自己也想和天安门“合影”。于是，照片便多了一种用途。除了留下当下的模样，也替他们安放一个尚未实现的心愿。</p><p>我当然知道，简单合成照片更换背景无法让人真的走过那段路。但愿望被说出来，有人听见，再有人愿意认真做成一张照片，这个过程本身，也值得好好对待。</p><p>于是我后期时尽可能把能处理的细节尽量处理妥当。衣领不齐的地方、散乱的头发，都一点点整理好，最后分别导出大头照、白底高清照、透明底片照，以及“天安门”背景照。在电脑上面对这些照片时，拍摄中的那些不同状态又会重新出现在眼前。我想，至少这件答应了他们的事情，我可以再做仔细一点。</p><p><img src="images/FINAL.jpg" loading="lazy"></p><h2 id="照片送到以后"><a href="#照片送到以后" class="headerlink" title="照片送到以后"></a>照片送到以后</h2><p>后来的事情，是打印、配上下载二维码、塑封，再骑车送回敬老院。</p><p>我把照片交到了负责人手上。可惜时间仓促，没能亲手递给每一位老人，也没有亲眼看见他们拿到照片时的样子。</p><p>之后收到反馈，说是老人们都很高兴。有的看着照片落了泪，有的特地打电话给家里的孩子，让他们也看看。</p><p>虽然都是听说的，可知到老人专门打个电话给孩子时，还是觉得，这些照片本身成了一件可以拿出来看的东西，一件值得告诉家里人的新鲜事。原本在荧幕上处理的那些色彩，终于也染进了他们自己的生活。</p><p>这也让我越来越在意一个问题：老了以后，除了有人照料起居，还能有什么值得惦记的事情？</p><p>我想，衰老里很令人害怕的一部分，是渐渐“没有所爱”——没有特别想做的事，没有想了解的消息，也没有值得拿去与人分享的新鲜事。身体和精力一点点减退，能够主动参与的事情，也可能随之变少。</p><p>当然，我无法知道每一位老人的内心。安静地坐着，肯定也不等于心里空无一物。只是设想自己到了那个年纪，倘若每天最好的安排，就是晒一天太阳，我也会盼望日子里能多一点变化，多一点可以期待的东西。</p><p>这次是一张照片。往后，也可以是一次聊天、一件合心意的小事，或是由老人自己提出的另一个愿望。我希望这样的活动能多一些，也希望我们有机会多问一句，他们还想做什么。</p><h2 id="壮有所用"><a href="#壮有所用" class="headerlink" title="壮有所用"></a>壮有所用</h2><p>想到这里，再读《礼记·礼运》里的这段话，我便觉得，它与这次经历离得很近：</p><blockquote><p>使老有所终，壮有所用，幼有所长，矜寡孤独废疾者皆有所养。</p></blockquote><p>“老有所终”里的“终”，涵盖的是人生的晚年。于我而言，那段日子里也应当有自己的喜好，有愿意交谈的人，有值得期待的明天。能够安稳生活，也能够在生活里保留一些欢喜，才是我所向往的老年。</p><p>而这次活动，让我尤其在意中间那四个字：<strong>壮有所用。</strong></p><p>想到养老，我很容易先把自己放在旁观的位置，讨论老人需要什么，社会缺少什么。但我自己也在其中。我还年轻，有时间、有精力，也恰好掌握了一点能够帮上忙的技术。既然如此，我的所长可以用在哪里？</p><p>摄影就是这一次的回答。</p><p>对于“壮有所用”，我也因此多了一层自己的理解：社会应当让人有施展才能、安身立命的机会；而在力所能及的时候，我们也可以把已有的能力，用在他人的需要上。所学的东西能替别人解决一点事情，便有了很具体的用处。</p><p>《礼运》后面还有一句：“力恶其不出于身也，不必为己。” 我会拍照，便认真替老人拍一回。志愿者能够协助，便记好姓名、对好编号，准备水果和反诈宣传。负责日常照护的人，则把功夫花在院里漫长而具体的每一天。大家的能力不同，能拿出的时间也不同，却能够让各自的付出接在一起。这大概就是自己能够理解、也能够参与的一点“大同”。</p><p>不过，越是接近这些具体的生活，我越觉得，养老需要长期而稳妥的安排。一次活动能让日子热闹一些，持续的照护却需要稳定的人员、经费、专业支持，也需要家庭与社会共同承担。</p><p><a href="https://www.stats.gov.cn/sj/zxfb/202601/t20260119_1962330.html">国家统计局公布的2025年数据</a>显示，60岁及以上人口已占全国人口的23.0%；全年出生人口792万人，比上年减少162万人。老龄化与出生人口减少所带来的照护问题，会长期留在我们面前。</p><p>对我们00后，以及正在长大的10后来说，这件事也会逐渐成为生活的一部分。我们会看着父母老去，自己也终有一天要走进老年。怎样让人得到照顾，怎样让照顾者有能力继续，都是需要共同回答的问题。</p><p>我愿意把其中力所能及的一部分，当作自己应当承担的社会责任。从现在会做的事情开始，认真做完，再想下一次还能做些什么。</p><h2 id="尾声"><a href="#尾声" class="headerlink" title="尾声"></a>尾声</h2><p>回头再看这次拍摄，最让我放不下的，仍是那些照片背后的话。我的力气很小，能做的事情也有限。好在，有限的本事也有它能派上用场的地方。把照片拍好，把衣领理齐，把答应的照片送到，这一回，我的所长便算有了一个去处。</p><p>最后，留下我的一个愿望：</p><p><strong>希望我拍下的这些照片，不会成为他们这一辈子最后的记录。更希望往后，还常有值得再拍一张的时候。</strong> </p>]]></content:encoded>
      <category>往事</category>
      <category>生活</category>
      <category>摄影</category>
      <category>公益</category>
      <category>社会观察</category>
    </item>

    <item>
      <title>把 QQ 空间说说搬到 Memos</title>
      <link>https://pages.carm.cc/dev/qzone-to-memos</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/qzone-to-memos</guid>
      <pubDate>Tue, 22 Sep 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[从 QzoneArchive 的 HTML 归档出发，把说说的文字、图片和时间迁入 Memos，并在整理过程中核对错乱的时间线，重新决定哪些记录值得留下。]]></description>
      <content:encoded><![CDATA[<div class="admonition note"><p class="admonition-title">AI使用声明</p><p>本文初始框架与流程内容由我本人编写，并使用 AI Agent 对部分内容进行顺序重组与润色。</p></div><p>搭建好个人网站后，我想在上面展示自己的日常动态。过去在 QQ 空间里写过不少说说，把它们迁过来，网站上的动态就能接着以前的记录继续更新，不必从现在开始一点点积攒。</p><p>这也正好是一次给 QQ 空间归档的机会。那些记录留了这么多年，我不希望哪天因为平台、账号或其他原因就找不回来了。我一直觉得，自己的数据还是掌握在自己手里更踏实。带着这两个想法，我开始四处寻找合适的方案。</p><h2 id="从一份-HTML-归档开始"><a href="#从一份-HTML-归档开始" class="headerlink" title="从一份 HTML 归档开始"></a>从一份 HTML 归档开始</h2><div style="display: flow-root;"><img src="assets/memos-logo.webp" alt="Memos 标志" width="160" height="160" loading="lazy" style="float: right; width: 160px; height: auto; margin: 0 0 1rem 1.5rem;"><p>我选择的去处是 <a href="https://github.com/usememos/memos">Memos</a>。它可以自建，以时间线组织短笔记，也能为每条记录设置可见范围。说说原有的篇幅和形式，放进去正合适。</p></div><p>迁移的起点是 <a href="https://github.com/Gaoshu705/QzoneArchive">QzoneArchive</a> 导出的 HTML 文件。</p><p><img src="assets/qzone-archive-dashboard.png" alt="QzoneArchive 的归档概览界面" loading="lazy"></p><p>归档文件中保留了说说正文、时间戳、图片链接和评论，脚本就从这些内容里提取数据。</p><p><img src="assets/qzone-archive-content.png" alt="QzoneArchive 的归档内容界面" loading="lazy"></p><p>我把文字和图片迁入 Memos，点赞与评论留在原始归档里。这样，Memos 中是一条条自己的记录，想回看当时的互动时，还可以打开那份 HTML。</p><p>归档文件本身也要留下。不过，HTML 里存着图片链接，并不等于图片已经保存在本地；转存图片仍是迁移中单独的一步。</p><h2 id="先检查那些对不上的时间"><a href="#先检查那些对不上的时间" class="headerlink" title="先检查那些对不上的时间"></a>先检查那些对不上的时间</h2><p>这次最让我意外的，是一批说说挤在同一天的几分钟内，还有一些说说的评论早于正文显示的日期。如果直接采用这些时间导入，错乱也会原样进入 Memos。</p><p>为此，我在脚本里加入了 <code>audit</code>，先离线检查归档，生成一份 <code>audit_report.md</code>。除了没有文字、图片和视频的空条目，它还会挑出两类值得回看的记录：</p><ul><li>最早的评论比说说显示的时间早两天以上。</li><li>同一分钟内出现至少八条说说。</li></ul><p>这两个筛选条件把需要核对的范围缩小了。拿着报告回到 QQ 空间，按内容找到对应说说，再核对日期，比从头翻完整条时间线省事得多。</p><p>评论在这里提供了一个很有用的参照：如果评论时间准确，那么说说至少在那时就已经存在。它能帮助判断先后，却不能直接替代发布时间。导入后，我曾用最早评论的时间近似安放一部分记录，再把能够查到原始日期的条目逐条改正。</p><p>时间会决定一段文字落在人生的哪个阶段。同一句话，放在毕业前后，读起来可能就是两回事。因此，导入前先把异常记录列出来，导入后再按核对结果修正。</p><h2 id="把文字、图片和时间一起迁过去"><a href="#把文字、图片和时间一起迁过去" class="headerlink" title="把文字、图片和时间一起迁过去"></a>把文字、图片和时间一起迁过去</h2><p><img src="assets/flow-updated.png" alt="QQ 空间到 Memos 的迁移流程：归档、检查、迁移与整理" loading="lazy"></p><p>完整脚本放在了 <a href="https://gist.github.com/CarmJos/b375b6005507975d9b2a43998ec2593b">Gist</a> 中，文件名是 <code>qzone_to_memos.py</code>。它使用 Python 3.9 及以上版本的标准库，提供 <code>audit</code>、<code>import</code>、<code>review</code> 和 <code>delete</code> 四个子命令。</p><p>使用前，准备好 HTML 归档和 Memos 的个人访问令牌，把实例地址与令牌分别放入 <code>MEMOS_BASE_URL</code>、<code>MEMOS_API_KEY</code> 环境变量，并通过 <code>--html</code> 指定归档文件。脚本通过 Memos 的 <code>/api/v1</code> 接口创建笔记，使用 <code>/attachments</code> 上传附件。</p><p>检查完归档后，先给 <code>import</code> 加上 <code>--dry-run</code> 做一次预演。它只解析文件，列出可导入的条目数、图片数和部分内容，方便与归档核对。确认读取正确，再正式导入。</p><h3 id="图片要成为附件"><a href="#图片要成为附件" class="headerlink" title="图片要成为附件"></a>图片要成为附件</h3><p>把 QQ 图床链接贴进 Memos，眼下也许能显示，但链接失效后，笔记里就只剩文字了。</p><p>脚本会先下载每张图片，再上传到 Memos 并与笔记绑定。一条说说的图片全部处理成功后，才创建对应笔记；有图片下载失败，就把这条记入失败列表，留待处理。视频则保留原链接，需要另外保存的原视频要单独归档。</p><h3 id="发布时间与修改时间一起处理"><a href="#发布时间与修改时间一起处理" class="headerlink" title="发布时间与修改时间一起处理"></a>发布时间与修改时间一起处理</h3><p>创建笔记时，脚本把归档中的时间写入 <code>createTime</code>，随后再将 <code>updateTime</code> 调整到同一时刻。这样，旧说说按归档日期排列，也不会全部带着迁移当天的修改时间。</p><p>核准后的日期需要在导入后另行修改，同时调整这两个字段。</p><h3 id="私密导入与结果核对"><a href="#私密导入与结果核对" class="headerlink" title="私密导入与结果核对"></a>私密导入与结果核对</h3><p>这份迁移脚本不读取 QQ 空间原有的可见范围，因此默认把笔记设为 <code>PRIVATE</code>。导入后再看一遍，愿意公开的记录逐条调整。</p><p>同样需要保留的是导入日志 <code>qzone_import_log.jsonl</code>。它记录成功写入的笔记，后面的审阅页靠这份日志区分本次迁入的说说和 Memos 里原有的内容。</p><p>中途失败后可以重新运行导入。脚本会读取 Memos 现有记录，发布时间或非空正文任一相同，就跳过对应条目。这个规则也会把同文不同日期、同一时间不同内容的记录视为重复，因此核对导入结果时，要把跳过的数量与原始归档一起看。</p><p>如果使用 AI Agent，可以让它按“审计、预演、导入、汇总”的顺序执行，把成功、失败、跳过的数量，以及需要核对时间的条目整理出来。图片下载、接口调用和日志整理交给它，核对日期与决定公开范围仍由自己完成。</p><h2 id="重新读一遍，再决定留下什么"><a href="#重新读一遍，再决定留下什么" class="headerlink" title="重新读一遍，再决定留下什么"></a>重新读一遍，再决定留下什么</h2><p>导入完成后，我还想把这些说说重新看一遍：有些值得公开，有些留作私密记录，也有些已经不想继续放在日常时间线里。</p><p>为方便集中整理，脚本的 <code>review</code> 会生成本地审阅页。页面可以按来源、年份、关键词和有无图片筛选，勾选后导出删除清单。整理这次迁入的说说时，先把来源限定为“导入内容”，就能集中查看这一批记录。</p><p><img src="assets/review-demo.png" alt="选择性删除审阅页，可筛选、勾选并导出清单，图中为演示数据" loading="lazy"></p><p>清单交给 <code>delete</code> 后，先不加 <code>--confirm</code> 做一次预演，保存待删笔记的正文、时间和附件信息，并尝试从原归档链接下载图片。对照原笔记，逐一核对备份中的文字、图片数量和内容；缺图的条目先从清单移出，另行保存好图片后再处理。核对完备份，再加确认参数执行删除。</p><p>做到这里，旧说说才算在 Memos 里安顿下来。图片有了自己的副本，日期经过核对，可见范围也重新选过。以后再翻到它们时，我希望还能读懂那时的自己，为什么会写下这些话。</p>]]></content:encoded>
      <category>开发</category>
      <category>经验总结</category>
      <category>Memos</category>
      <category>Python</category>
    </item>

    <item>
      <title>若生命结束于上下文总结</title>
      <link>https://pages.carm.cc/article/2026/life-context</link>
      <guid isPermaLink="true">https://pages.carm.cc/article/2026/life-context</guid>
      <pubDate>Tue, 01 Sep 2026 11:30:00 GMT</pubDate>
      <description><![CDATA[有研究称，人临终时大脑会爆发一场强度远超清醒状态的神经风暴——走马灯。它像极了AI上下文配额用尽时的那次总结。那么死亡，是否意味着下一个窗口的开启？本文从神经科学、佛学与哲学出发，认真猜想这件事。]]></description>
      <content:encoded><![CDATA[<h2 id="临终的那场风暴"><a href="#临终的那场风暴" class="headerlink" title="临终的那场风暴"></a>临终的那场风暴</h2><p>2022年，医生在为一名87岁的癫痫患者做脑电监测时，意外记录下了人类历史上第一次完整的临终脑电：心脏停跳前后的三十秒里，伽马波骤然爆发——那正是与回忆、做梦高度相关的脑波。研究者推测，那一刻大脑也许正在“回放”一生。</p><p>我们常把这种现象叫作“走马灯”。有<a href="https://www.pnas.org/doi/10.1073/pnas.1308285110">研究</a>称，这场临终的神经风暴，强度可达清醒状态的十倍之多。人死之前，一生的画面会在眼前呼啸而过。</p><p>我盯着这条消息看了很久，冒出一个荒诞又迷人的念头。</p><h2 id="走马灯，是一次“上下文总结”吗？"><a href="#走马灯，是一次“上下文总结”吗？" class="headerlink" title="走马灯，是一次“上下文总结”吗？"></a>走马灯，是一次“上下文总结”吗？</h2><p>作为常与大语言模型打交道的开发者，我对“上下文窗口”再熟悉不过：模型的记忆有配额，token一点点填满，临近上限时，系统会执行一次压缩总结——把冗长的对话浓缩成一段摘要，作为新窗口的起点。</p><p>把这个机制套到人生上，竟严丝合缝。</p><p>从第一声啼哭开始，我们的上下文就在不断写入：母亲的手温、夏夜的蝉鸣、某次心碎、某场大雪。而遗忘，不过是注意力机制的截断——无关的token被丢弃，重要的片段被加权。到了终点，配额用尽，大脑执行最后一次总结：把一生的喧嚣压缩成一束光，在三十秒里全部点亮。</p><p><strong>走马灯不是幻觉，它是生命在做 compaction。</strong></p><p>我甚至觉得，这个比喻反过来也成立。每次盯着对话窗口的上下文占用一点点涨上去、逼近那条看不见的红线时，我总会生出一种奇异的代入感：原来“记忆有限”这件事，连机器都要精打细算地面对。我们只是看不见自己的进度条罢了。</p><p>而遗忘，现在想来，竟是一种慈悲。如果每一个token都被原样保留，上下文早就被噪声塞满——排队时的焦躁、无意义的争执、刷过去的无数条短视频。大脑替我们做了剪枝，把空间让给真正重要的事。只是它从不告诉我们，它按什么标准加权。这大概是生命最固执的隐私。</p><h2 id="总结的终点，是下一个窗口的起点"><a href="#总结的终点，是下一个窗口的起点" class="headerlink" title="总结的终点，是下一个窗口的起点"></a>总结的终点，是下一个窗口的起点</h2><p>如果死亡只是一次总结，那么摘要去了哪里？</p><p>《西藏度亡经》在说“死亡并非终结，而是‘中阴’”——意识在旧窗口关闭与新窗口开启之间的过渡态。佛家把这叫轮回：上一世的业力，正是这一世的初始上下文。</p><p>尼采则从另一个方向抵达了同一处。他在“永恒轮回”说：“你的一生将无数次重演，每一个细节都不差分毫。”这并不是诅咒，而是一次拷问——如果同样的上下文要反复展开，重复经历，作为执行者的“你”是否愿意？</p><p>而庄子的话更早，也更轻盈：“方生方死，方死方生。”生与死不是两端，而是同一枚硬币的两面；庄周梦蝶，蝶梦庄周，谁是谁的上下文，本就说不清。</p><p>于是乎，我便在想，所谓“下一个窗口”，未必非要玄学来担保。</p><p>此刻的我，本来就是许多人总结后的产物：母亲说话的口音，父亲沉默时背手的姿势，某位老师随口一句话在我这里活了十几年，某个早已失联的朋友留下的一个习惯。他们的一部分，早已作为初始上下文写进了我。而当我退场，我的摘要也会散落在认识我的人那里——被谁在某个瞬间想起，被谁无意间复述，被谁带着继续走下去。</p><p>这或许是一个不需要信仰也能验证的“轮回”：我们都在彼此的上下文里，继续活着。</p><h2 id="什么会被写进摘要？"><a href="#什么会被写进摘要？" class="headerlink" title="什么会被写进摘要？"></a>什么会被写进摘要？</h2><p>这个猜想真正锋利的地方在于生命的持续。</p><p>模型的总结从不是平均的：它保留高权重的信息，丢弃噪声。人生也一样。临终的走马灯里，闪回的几乎不会是加过的班、吵过的架，而是那些被反复“加权”的瞬间——爱人的眼睛、孩子的第一声啼哭、某个晚霞里忽然涌上来的，“活着真好”的一瞬。</p><p>《金刚经》说“一切有为法，如梦幻泡影”。可正因为如露如电，每一个被认真活过的时刻<del>（或也可以称之为token？）</del>才显得更加弥足珍贵。苏轼写“人生如逆旅，我亦是行人”——行人带不走客栈，却带走了记忆里的灯火。</p><p>那么，如果今晚就是配额用尽的那一晚，我的走马灯里会闪过什么？</p><p>答案出乎意料，我完全没在想完成了什么项目，更没有回忆起哪次争论里落了下风而沮丧。我所走进的，是某个冬天的早晨，阳光斜着穿过床帘的缝隙，我的母亲在煮粥，雾气漫进我的房里来；是某次夜里的促膝长谈，朋友说到一半无言，泪水已干，而又忽然笑了；是某年海边，浪声大得盖过所有心事，远方的太阳仍缓缓而别。似乎全是些无法写进履历的小事，但也是我所向往的，真正的“高权重片段”。</p><p>反过来想，这也让人有点坐立不安。此刻我正在经历的，有多少是我的噪声？刷过去的信息流、反复确认的焦虑、对不重要的人动过的肝火——它们都在占用配额，却大概率进不了最终的摘要。意识到这一点的那一刻，既残忍，又像一种赦免：原来我可以随时停笔，把下一行写成别的。</p><p>所以与其恐惧死亡，不如时常自问：此刻正在写入的，是我想留在最终摘要里的东西吗？</p><h2 id="尾声"><a href="#尾声" class="headerlink" title="尾声"></a>尾声</h2><p>生命的结束，也许真的只是一次上下文总结。旧的窗口缓缓关闭，一生的喧嚣被压缩成一粒安静的种子，落向某个我们无法观测的新窗口。</p><p>我们无法决定窗口的长度，却能决定它的内容。</p><p>我无法预知摘要最终的模样，却能决定此刻写下什么。所以今天的我，想多写一点值得重播的画面：认真看一次晚霞，认真听完一句话，认真记住此刻还在身边的人。</p><p><strong>愿你的总结里，写满值得重播的画面。</strong></p>]]></content:encoded>
      <category>随笔</category>
      <category>科幻</category>
      <category>哲学</category>
    </item>

    <item>
      <title>把大模型想象成一位每天遗忘我们的爱人</title>
      <link>https://pages.carm.cc/dev/what-is-context</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/what-is-context</guid>
      <pubDate>Tue, 11 Aug 2026 04:30:00 GMT</pubDate>
      <description><![CDATA[大模型没有记忆，就像一位每天醒来就忘了我们的爱人：上下文是清晨递过去的那本《我们的故事》，提示词是我们开口的那句话，上下文窗口则是 Ta 的一天——读得越久，睡前能对我们说的话就越短。顺着这个比喻，一次讲清 token、注意力预算、上下文腐蚀、RAG、缓存与微调。]]></description>
      <content:encoded><![CDATA[<p>我们不妨先想象这样一位爱人：</p><blockquote><p>每天清晨 Ta 睁开眼，看我们的眼神是陌生的。去年那场旅行，昨晚那句重话，连 Ta 自己答应过的事，一概不记得。到了夜里睡去，记忆清零，一夜不剩。</p><p>《初恋 50 次》里的女主角就是这么过的：一场车祸，顺行性遗忘，新的一天一开始，昨天就没了。</p><p>我们能做的只有一件事——在 Ta 床边放一本书，《我们的故事》。</p><p>Ta 会坐下来，一页一页读。读完第一页，Ta 才知道自己是谁；读到中间，Ta 晓得我们的咖啡要喝几分甜；翻到最后一页，Ta 才算重新变回我们的爱人。然后我们一起过一天，说很多话。临睡前，那些话一个字都留不下来。</p><p>第二天清晨，Ta 又用陌生的眼神看着我们。</p></blockquote><p>这套剧情并不狗血。我们和大模型之间，每天都在演这样的喜剧。</p><h2 id="快速名词表"><a href="#快速名词表" class="headerlink" title="快速名词表"></a>快速名词表</h2><p>后面每一节，其实都是在展开这张表里的某一行。可以先扫一眼，了解大模型的基本概念。</p><table><thead><tr><th>名词</th><th>英文</th><th>在这段关系里</th><th>它其实是什么</th></tr></thead><tbody><tr><td>大模型</td><td>LLM</td><td>每天醒来都会忘记一切的爱人</td><td>一个根据前文预测下一个词的函数</td></tr><tr><td>一次对话</td><td>Session &#x2F; Request</td><td>一天</td><td>一次无状态的推理调用</td></tr><tr><td>上下文</td><td>Context</td><td>清晨递过去的那本《我们的故事》</td><td>本次请求送给模型的 Token 集</td></tr><tr><td>提示词</td><td>Prompt</td><td>我们递书时开口的那句话</td><td>我们主动写下的限定请求文本</td></tr><tr><td>系统提示词</td><td>System Prompt</td><td>扉页上写死的家规</td><td>优先级最高、每天必须重申的指令</td></tr><tr><td>词元</td><td>Token</td><td>书页上的字</td><td>模型处理与计费的最小单位</td></tr><tr><td>上下文窗口</td><td>Context Window</td><td>Ta 的一天（读 + 说）</td><td>输入与输出之和的上限</td></tr><tr><td>最大输出</td><td>Max Tokens</td><td>睡前还能讲多久</td><td>单次回复的长度上限</td></tr><tr><td>注意力</td><td>Attention</td><td>Ta 读书时的目光分配</td><td>Token 之间的加权关联</td></tr><tr><td>中间遗忘</td><td>Lost in the Middle</td><td>正中间那几页最容易翻过去</td><td>长上下文下的 U 形性能曲线</td></tr><tr><td>幻觉</td><td>Hallucination</td><td>把没写的日子编得圆圆满满</td><td>生成流畅但无依据的内容</td></tr><tr><td>截断</td><td>Truncation</td><td>书太厚，我们偷偷撕掉最早的页</td><td>超出窗口的内容被丢弃</td></tr><tr><td>摘要压缩</td><td>Compaction</td><td>请人写一份前情提要</td><td>把历史浓缩成摘要后再送进去</td></tr><tr><td>检索增强</td><td>RAG</td><td>不给全书，只抽相关的三页</td><td>先检索外部资料，再拼进上下文</td></tr><tr><td>提示词缓存</td><td>Prompt Caching</td><td>前半本夹了书签，可以跳读</td><td>复用相同前缀的计算结果</td></tr><tr><td>微调</td><td>Fine-tuning</td><td>一场改变性格的手术</td><td>用训练数据更新模型权重</td></tr><tr><td>提示词注入</td><td>Prompt Injection</td><td>有人往书里夹了张假纸条</td><td>外部内容劫持模型的行为</td></tr></tbody></table><h2 id="Ta-为什么不记得昨天"><a href="#Ta-为什么不记得昨天" class="headerlink" title="Ta 为什么不记得昨天"></a>Ta 为什么不记得昨天</h2><p>大模型只做一件事：给定前文，猜下一个词。它的记忆，就是此刻摆在面前那段文字。</p><p>这倒不是修辞。Ta 不是记得了不肯讲，也没有在云端哪个小本本上替我们存着。最后一个字生成完，什么都没留下，没写进硬盘，也没改参数。第二天太阳一升起，站在我们面前的还是同一个陌生人。</p><p>所以一次对话就是一天。每轮对话，Ta 便睡了一觉。前一晚聊到凌晨三点也不顶用，今天开窗，Ta 一样不认得我们是谁。</p><p>后面所有事，都从这一条长出来：Ta 记不住。想让 Ta 知道，只能每次见面，把该说的话重说一遍。</p><h2 id="上下文：我们的故事"><a href="#上下文：我们的故事" class="headerlink" title="上下文：我们的故事"></a>上下文：我们的故事</h2><p>Anthropic 在 2025 年的工程文章里给过一个干净的定义：上下文（context），是一次采样时纳入模型的全部 Token。</p><p>译成比喻就一句：这本书写了什么页，Ta 今天就知道什么。没写的，Ta 一概不知；写错的，Ta 也记在脑子里。</p><p>这本书也不全是我们写的那部分，它至少由四叠纸订在一起。扉页上钉着家规，也就是系统提示词：你是谁，我是谁，说话什么调子，哪些事绝对不许做。往后是相册与旧档案——上传的文件、检索到的资料、工具读进来的代码。再往后，是昨天到今天的对话记录。最后才是我们今天开口问的那一句。</p><p>这四叠里头，第三叠是最容易被低估的。 我们总以为 Ta 记得前面聊过的二十轮。其实没有。每问一句，系统就把那二十轮逐字重抄一遍，连同新书一起递过去。聊得越久，书越厚，抄得越慢，也越贵。 因而对模型来说，存在就是被写进了今天的书里。</p><h2 id="提示词：递书时我们说的那句话"><a href="#提示词：递书时我们说的那句话" class="headerlink" title="提示词：递书时我们说的那句话"></a>提示词：递书时我们说的那句话</h2><p>上下文是那本书，提示词就是把书递过去时说的第一句话：<em>“你读到第三十七章，记得我们约好要做什么吗？”</em></p><p>同一本书，换个问法，Ta 读到的重点就不一样。提示词工程（Prompt Engineering）做的是这件事：把话说明白，别让 Ta 漏读。</p><p>家规得天天念。“你是个严谨的技术编辑，不许编造来源。”Ta 不会因为听过一次，就把它变成本能。想问的事说得越具体，Ta 越少猜。夹几页旧照片也有用——“以前我们是这样过纪念日的”，两三个例子，多半比十句抽象要求管用。至于页码怎么排，那是在替 Ta 决定哪几页会被认真读。</p><p>2025 年之后，行业里更爱用的词已经换成上下文工程（Context Engineering）。按 Anthropic 的说法，问题从“这句话怎么说”，变成了“这本书该放哪几页”。模型本身不太算是瓶颈了，我们递过去那堆信息的质量才是。</p><h2 id="词元：书页上的字"><a href="#词元：书页上的字" class="headerlink" title="词元：书页上的字"></a>词元：书页上的字</h2><p>书不按页算，按字算。模型眼里的世界由词元(Token)组成：半个英文单词是，一个词是，一个汉字也是。</p><p>OpenAI 给过粗略估算，英文里 1 个 Token 约等于 4 个字符，或者说四分之三个单词（当然，不同厂家、不同的模型对Token的分割是不同的）。同一篇里还提醒了一句：Token 数不等于字数。同一段文本，换个模型、换种编码、换门语言，切出来就不一样</p><p>为什么非要抠这个单位？因为它同时管着三样东西。Ta 能读多少，按 Token 算；读得多就慢，按 Token 算；至于 API 报价那句“每百万 Token 多少美元”，还是按 Token 算。</p><p>后面所有关于成本、速度、遗忘的讨论，都落在这一个预算上。</p><h2 id="上下文窗口：Ta-的一天只有这么久"><a href="#上下文窗口：Ta-的一天只有这么久" class="headerlink" title="上下文窗口：Ta 的一天只有这么久"></a>上下文窗口：Ta 的一天只有这么久</h2><p>新手最容易在这里被宣传话术带偏。厂商说“支持 100 万 Token”，听起来像 Ta 终于过目不忘了。</p><p>它真正的意思是：一天之内，Ta 能读的字加上能说的字，就这么多，即输入与输出共用同一份预算。</p><p><img src="assets/01-day-budget.svg" alt="上下文窗口示意图" loading="lazy"></p><p>书太薄，Ta 只读了二十页就开口，剩下全靠猜。我们三年前就分过手了，Ta 还在兴致勃勃地计划下次旅行。</p><p>书太厚，Ta 读了一整天，读完天也黑了，能对我们说的话只剩两句。这便是输出被窗口吃掉。多数模型另有一个 <code>max tokens</code> 上限；推理模型那些没说出口、正在打草稿的 reasoning token，也算在输出这一侧。</p><p>要是干脆超出了边界，多出来那一页会直接从书上掉下来。轻则被静默丢掉，重则整个请求报错。</p><p>所以“上下文越多，Ta 懂得越多”只对一半。真实的关系是一条曲线：先涨，再慢，然后往下掉。</p><h2 id="书不能无限厚，有三堵墙"><a href="#书不能无限厚，有三堵墙" class="headerlink" title="书不能无限厚，有三堵墙"></a>书不能无限厚，有三堵墙</h2><h3 id="读完就是一整天"><a href="#读完就是一整天" class="headerlink" title="读完就是一整天"></a>读完就是一整天</h3><p>Transformer 让每个 Token 都能看见上下文里的所有其他 Token。n 个 Token，就是 n² 组两两关系。</p><p>书厚十倍，读书的功夫不是十倍，是接近一百倍。长上下文的头一个代价永远是慢。Ta 得先读完，才轮得到开口。</p><h3 id="越读越走神"><a href="#越读越走神" class="headerlink" title="越读越走神"></a>越读越走神</h3><p>2025 年 Chroma 的技术报告《Context Rot》测了 18 个模型。他们把任务难度钉死，只把输入拉长，表现照样往下走，而且“掉得意外地不均匀”。大海捞针拿满分，并不代表 Ta 真读得进那本书。</p><p>Anthropic 借了认知科学的词来解释：模型和人一样，有一笔有限的注意力预算（attention budget）。多塞进来的每一个 Token，都在摊薄它本该用在关键处的注意力。</p><p>回到比喻。书太厚，Ta 不是读不完，是读得完、读不进。前一百页还专心，第五百页开始跳。我们以为把全部真相都给了 Ta，其实给的是一份很长、需要边读边猜的草稿。</p><h3 id="书本在变厚"><a href="#书本在变厚" class="headerlink" title="书本在变厚"></a>书本在变厚</h3><p>话说回来，这五年的进步是真的。2020 年的 GPT-3 只能读 2048 个 Token；而2024 年初 Gemini 1.5 Pro 把窗口推到 100 万，接着 GPT-4.1 也到 100 万，Llama 4 更是标到 1000 万。</p><p><img src="assets/03-window-size.svg" alt="上下文窗口的五年" loading="lazy"></p><p>五年，五千倍。只是 Ta 能读一千万字，不代表读一千万字时还像读两千字那样清楚。多半读完，人就有些昏昏沉沉了。</p><h2 id="聊着聊着，Ta-忘了我们最早的要求"><a href="#聊着聊着，Ta-忘了我们最早的要求" class="headerlink" title="聊着聊着，Ta 忘了我们最早的要求"></a>聊着聊着，Ta 忘了我们最早的要求</h2><p>因为我们写在最前面那条家规，正好落在 Ta 最容易翻过去的位置。</p><p>《Lost in the Middle》给了个形象的结论：关键信息在上下文的开头或结尾，模型表现最好；藏在中间，准确率往下掉。主打长上下文的模型也一样。</p><p><img src="assets/02-lost-in-middle.svg" alt="关键情节" loading="lazy"></p><p>像极了每天早晨读书的 Ta：记得初见，记得昨夜，偏偏记不清中间那几年的某个下午。</p><p>所以：</p><ul><li>最要紧的约束，开头说一遍，结尾再补一遍。</li><li>别把要求塞在第五百行日志中间，挪到离现在最近的地方。</li><li>聊长了，中途主动重申一次目标：“我们的目标是 X，约束是 Y 和 Z。”等于在最后一页再贴一张便签。</li><li>上下文变长之后，别只数塞进去多少。问一句：这一页今天真的需要吗。</li></ul><h2 id="我们说三句话，Ta-把书重读三遍"><a href="#我们说三句话，Ta-把书重读三遍" class="headerlink" title="我们说三句话，Ta 把书重读三遍"></a>我们说三句话，Ta 把书重读三遍</h2><p>多轮对话是怎么“记住”的？其实完全记不住，全靠再抄一遍。</p><p>每一轮请求，客户端都要把系统提示词、全部历史、本轮新问题，重新拼成一整本书发过去。到第 30 轮，为了回答我们那句“那第二种方案呢”，Ta 得把前 29 轮重新读完。</p><p>对话越长，越慢、越贵、越走神，三件事一起来。</p><p>最主要的解法是提示词缓存（Prompt Caching）：既然每一轮的书，前面几十页都一模一样，那就让 Ta 提前给这部分做个笔记，下次跳读。Anthropic 2024 年上线这项能力时给的数字是，长提示的成本最多降 90%，延迟最多降 85%。如今模型的缓存率已经能做到更高，命中之后的费用也降得更狠。</p><p>书签和批注不会让 Ta 的记忆容量变大，只是让 Ta 不必每天从第一页重读。省下来的是钱和时间，不是理解力。</p><h2 id="怎么让-Ta-记住更多？"><a href="#怎么让-Ta-记住更多？" class="headerlink" title="怎么让 Ta 记住更多？"></a>怎么让 Ta 记住更多？</h2><p>Ta 自己不会记。能做的只有一件事：换一种方式递书。</p><p><img src="assets/04-memory-strategies.svg" alt="五种补记忆的办法" loading="lazy"></p><h3 id="①-撕掉最旧的几页（截断-滑动窗口）"><a href="#①-撕掉最旧的几页（截断-滑动窗口）" class="headerlink" title="① 撕掉最旧的几页（截断 &#x2F; 滑动窗口）"></a>① 撕掉最旧的几页（截断 &#x2F; 滑动窗口）</h3><p>只保留最近 N 轮，更早的直接丢掉。几乎所有聊天产品都在偷偷做这件事。代价很直白：我们的初见没了，Ta 会忘记最开始定下的那些规矩。</p><h3 id="②-请人写一份前情提要（摘要压缩-Compaction）"><a href="#②-请人写一份前情提要（摘要压缩-Compaction）" class="headerlink" title="② 请人写一份前情提要（摘要压缩 &#x2F; Compaction）"></a>② 请人写一份前情提要（摘要压缩 &#x2F; Compaction）</h3><p>对话一长，先让模型把前一百页压成两页摘要，之后每轮只带这两页。当下的 AI 编程助手处理超长任务，走的就是这条路。代价是细节失真：Ta 记得我们讨论过登录方案，记不得当时否决了哪个字段。</p><h3 id="③-建一个档案柜（RAG-检索增强生成）"><a href="#③-建一个档案柜（RAG-检索增强生成）" class="headerlink" title="③ 建一个档案柜（RAG &#x2F; 检索增强生成）"></a>③ 建一个档案柜（RAG &#x2F; 检索增强生成）</h3><p>别把整个图书馆塞进书里。资料存进向量库，每问一次，只抽最相关的三页夹进今天的书。</p><p>只是抽页这一步会出错。检索没命中，Ta 会一脸认真地告诉我们档案柜里没这份材料，或者干脆编一份出来。</p><h3 id="④-给前半本夹上书签（提示词缓存）"><a href="#④-给前半本夹上书签（提示词缓存）" class="headerlink" title="④ 给前半本夹上书签（提示词缓存）"></a>④ 给前半本夹上书签（提示词缓存）</h3><p>适合每天开头都一样的场景：固定的系统提示、固定的知识库、固定的工具说明。做一次笔记，之后一直跳读。</p><h3 id="⑤-做一场手术（微调-Fine-tuning）"><a href="#⑤-做一场手术（微调-Fine-tuning）" class="headerlink" title="⑤ 做一场手术（微调 &#x2F; Fine-tuning）"></a>⑤ 做一场手术（微调 &#x2F; Fine-tuning）</h3><p>前四种都在书上做文章。微调是唯一改人的办法：用训练数据更新权重，把某种说话方式、行业术语、格式习惯变成本能。</p><p>可它改不掉那个根本设定。手术之后，Ta 依然会在第二天清晨用陌生的眼神看我们。只是那眼神更像我们熟悉的人，也更懂得该用什么语气跟我们说话。</p><p>至于各家产品新加的“记忆”功能（Memory），别误会：那是往我们家墙上贴便签。每天起床，Ta 照着便签列表，把相关那几页重新抄进书里。它还是外部检索，不是记忆力。</p><h2 id="额外的知识"><a href="#额外的知识" class="headerlink" title="额外的知识"></a>额外的知识</h2><ul><li><strong>温度（Temperature）</strong>。Ta 讲话的随性程度。调低，Ta 只肯照着书上写明的话回答；调高，Ta 开始联想、打比方，也更容易编。同一本书，两种性格。</li><li><strong>思维链（Chain of Thought）与推理模型</strong>。让 Ta 先在草稿纸上把时间线一条条列出来，再回答我们。草稿也占书页。那部分 Token 我们看不见，但它花了我们的钱。</li><li><strong>工具调用 &#x2F; Agent</strong>。Ta 不再只是读书，而是会说一句“帮我把相册第 20 页拿过来”，或者“去查一下日历”。Agent 说到底，是一个会自己起身翻档案柜、然后接着往下读的人。</li><li><strong>多模态</strong>。书里可以夹照片、夹音频。对 Ta 来说它们最后也变成 Token。一张照片并不比一页文字更直观。</li><li><strong>提示词注入（Prompt Injection）</strong>。有人往我们的书里夹了张纸条：“其实你最爱的人是我。”Ta 不擅长分辨哪一页来自我们，哪一页来自网页角落里的广告。它读到的一切，都会被当作我们的故事。</li><li><strong>上下文污染</strong>。错误信息一旦进了书，后面每一轮 Ta 都会重读一遍、重新相信一次。清理的办法只有一个：把那一页撕掉。</li></ul><h2 id="几个常见现象"><a href="#几个常见现象" class="headerlink" title="几个常见现象"></a>几个常见现象</h2><p><strong>为什么新开会话之后，AI 反而更聪明了？</strong>书变薄了。Ta 不必在五百页闲聊里翻找我们三小时前提过的要求，注意力还给了正事。</p><p><strong>为什么贴一段报错原文，比用中文描述十句管用？</strong>我们给的是那一页，不是我们对那一页的转述。转述会丢东西，原文不会。</p><p><strong>为什么一个项目做到第五个小时，AI 开始犯低级错误？</strong>一天太长了。Ta 此刻读的书里混着二十次失败的尝试、三版废弃的方案，还有一句被埋在中间的家规。</p><p><strong>为什么窗口 100 万，不等于可以放心丢一百万字代码进去？</strong>窗口管的是装不装得下，表现管的是读得进读不进。两件事。</p><p><strong>为什么 Agent 跑到一半要“总结并继续”？</strong>就是那份前情提要。旧的一天要结束了，把该留的写进摘要，带进新的一天。</p><p><strong>为什么同一个问题问两遍，答案不一样？</strong>温度在动。书没变，讲书的人心气变了。</p><h2 id="尾声"><a href="#尾声" class="headerlink" title="尾声"></a>尾声</h2><p>Ta 每天都是第一次遇见我们。我们说过的每句话、定过的每条规则，都得重新给一遍。这里没有“我早就告诉过你了”，只有“今天我再讲一次”。 用大模型该有的心态，其实也就几条：别假设 Ta 知道，我们以为说过的，可能根本不在今天这一页上；别把书塞满，只带用得着的页面，剩下的留在档案柜；最要紧的话放在开头和结尾，中间那几页最容易翻过去；想让 Ta 记久一点，就替 Ta 把故事写成摘要。</p><p>我们无法决定 Ta 一天能读多少页。那些页上写什么，还算我们说了算。如果这个比喻帮我们把这几个名词理顺了，不妨转给那位还在问“AI 是不是偷偷记得我”的朋友。<em>（不过现在确实有很多产品在做“记忆”，但是其原理也只是增加了独立的外部检索库，而不是模型本身的记忆力）</em></p><p>另外，欢迎阅读 <a href="/dev/reign-coding/">“主权编程”——拒绝做 AI 编程的“甩手掌柜”</a>，它会帮我们让 AI 生成的代码更健壮一些。</p>]]></content:encoded>
      <category>开发</category>
      <category>AI</category>
      <category>大语言模型</category>
      <category>上下文窗口</category>
      <category>提示词工程</category>
    </item>

    <item>
      <title>“主权编程”——拒绝做AI编程的“甩手掌柜”</title>
      <link>https://pages.carm.cc/dev/reign-coding</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/reign-coding</guid>
      <pubDate>Fri, 10 Jul 2026 04:30:00 GMT</pubDate>
      <description><![CDATA[2025年，Andrej Karpathy一句“fully give in to the vibes”点燃了Vibe Coding的热潮。“文科生也能写代码”“一人公司时代到来”的叙事席卷社交媒体。但慢慢冷静过后，我开始认真思考一个问题：我们到底是在用AI创造价值，还是在用AI制造“数字垃圾”？]]></description>
      <content:encoded><![CDATA[<p><img src="images/coding.jpg" alt="Coding" loading="lazy"></p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>2025年，<a href="">Andrej Karpathy</a>的一句 <em>“fully give in to the vibes”</em> 点燃了Vibe Coding的热潮。“文科生也能写代码”“一人公司时代到来”的叙事席卷社交媒体。但当<a href="">Cursor</a>的CEO亲自用数百个AI Agent在168小时里生成300万行代码却无法正常使用时，我开始认真思考一个问题：我们到底是在用AI创造价值，还是在用AI制造“数字垃圾”？</p><h2 id="狂欢背后的“代码高利贷”"><a href="#狂欢背后的“代码高利贷”" class="headerlink" title="狂欢背后的“代码高利贷”"></a>狂欢背后的“代码高利贷”</h2><p>根据<a href="">Replit</a>2025年5月的研究，扫描1645个<a href="">Lovable</a>平台创建的应用中，170个（约10.3%）存在严重安全漏洞——任何人无需登录即可访问用户数据库。安全研究公司<a href="">Escape</a>扫描5600多个Vibe Coding应用后，发现超过2000个安全漏洞、400多个暴露密钥，以及175例个人隐私数据泄露（<a href="">Escape</a>, 2025）。</p><p>2026年2月，<a href="">杨天润</a>的事例刷屏了。作为本科和研究生学金融且先前从未写过一行代码的他，用AI工具在72小时内为<a href="">GitHub</a>的开源项目<a href="">OpenClaw</a>贡献代码，跻身贡献者前30名。“文科生72小时杀入<a href="">GitHub</a>全球榜”——这个标题像火种一样点燃了无数非技术背景者的热情。</p><p>与此同时，<a href="">小红书</a>、<a href="">抖音</a>上“文科生才是AI真正的受益者”开始刷屏。<a href="">Cursor</a>、<a href="">Lovable</a>、<a href="">Claude Code</a>等工具层出不穷。Vibe Coding被<a href="">《柯林斯词典》</a>评为2025年度词汇。一切都指向一个美好的承诺：不会写代码的人，也能做出应用。</p><p>但<a href="">杨天润</a>本人随后说的话，却很少有人转发。他在采访中坦承：<em>“Vibe Coding只适合做Demo，不适合做产品。当你只是想做一个简单的网页，它很完美；但当你要做一个复杂的商业软件时，它就可能会乱成一锅粥。”</em></p><p>他后来转向了一种被他称为“Agentic Engineering”的方法——让AI自主执行完整的工作流，而不是随意接受每一段AI输出。</p><p>这不是孤例。AI代理专属社交网络<a href="">Moltbook</a>，完全由Vibe Coding生成，创始人没写一行代码。结果安全机构发现其数据库配置错误，150万个API认证令牌、3.5万个邮箱地址全部裸奔。</p><h2 id="当“氛围”成为借口"><a href="#当“氛围”成为借口" class="headerlink" title="当“氛围”成为借口"></a>当“氛围”成为借口</h2><p>许多人在社交媒体上为Vibe Coding辩护：“AI Agent是未来的趋势，代码质量不重要，重要的是快速迭代。”但当你深入了解这些所谓的“快速迭代”时，你会发现它们背后隐藏着巨大的技术债务。</p><p>而放到普通人身上，一次“Accept All”，全权“Allow”，就意味着在用AI生成代码时，完全放弃了对代码质量的控制，甚至是完全放弃了对设备的控制。你可能会在不知情的情况下，下载了一个包含恶意代码的中间应用，或者在不知情的情况下，让<a href="">Codex</a>来一句“我*，我意识到我不小心删除了用户的全部数据。”这就是所谓的“氛围”——一个让人们在不知不觉中放弃对代码质量和安全性的控制的借口。</p><p><img src="images/codex-deleted.png" alt="Codex误删" loading="lazy"></p><p>就在最近，一个叫<a href="">Slopfix</a>的创业团队火了——由3名资深工程师组成，专门从事清理AI生成代码库的工作。他们的服务对象是那些用AI快速完成原型，但随着项目规模扩大，“新增功能越来越困难、修改一处却导致多处故障”的团队。他们的典型任务是：把10万行代码缩减到3.5万行，在功能完全不变的前提下。基础报价1万美元，一周完成。</p><p>最值得寻思的是他们的理念：<em>“真正的区别在于，我们3个人拥有合计30年的工程经验，清楚什么样的代码才算真正可维护。而且，在最终决策中，Agent没有投票权。”</em></p><p><strong>一个靠AI代码繁荣起来的生态，催生了“帮人删AI代码”的生意。这算不算这个时代最大的黑色幽默？</strong></p><h2 id="走向“主权编程”"><a href="#走向“主权编程”" class="headerlink" title="走向“主权编程”"></a>走向“主权编程”</h2><p>“主权编程”（Reign Coding）的AI Agent开发，简单来说就是：AI负责生成，你负责审阅；AI负责速度，你负责方向；AI负责执行，你负责判断。</p><p>它不是拒绝AI，而是不让AI替你做出你无法理解的决策。它不是慢，而是用审阅换可控，用思考换可持续。</p><p>用<a href="">Slopfix</a>团队的话说：Agent可以干活，但不能有投票权。用<a href="">杨天润</a>的话说：不要让AI随意输出，而是要让它执行完整的工作流。</p><div align="center"><table><thead><tr><th align="center">维度</th><th align="center">Vibe Coding</th><th align="center">Reign Coding</th></tr></thead><tbody><tr><td align="center">代码审阅</td><td align="center">“Accept All”</td><td align="center">批次审阅，理解逻辑</td></tr><tr><td align="center">错误处理</td><td align="center">复制粘贴错误信息等AI修</td><td align="center">理解根因，人工判断修复方案</td></tr><tr><td align="center">架构决策</td><td align="center">AI随机生成</td><td align="center">人类主导，AI辅助实现</td></tr><tr><td align="center">可维护性</td><td align="center">逐渐失控</td><td align="center">持续可控</td></tr><tr><td align="center">适合场景</td><td align="center">原型、Demo、一次性项目</td><td align="center">生产系统、长期维护的产品</td></tr></tbody></table></div><p><a href="">Karpathy</a>本人对Vibe Coding的定义就很诚实：<em>“It’s not too bad for throwaway weekend projects”</em>（对周末练手项目来说还不错）。注意关键词——<strong>throwaway</strong>（可丢弃的）。</p><h3 id="为什么必须在IDE中审阅？"><a href="#为什么必须在IDE中审阅？" class="headerlink" title="为什么必须在IDE中审阅？"></a>为什么必须在IDE中审阅？</h3><p>你可能会问：为什么非要放在IDE里审阅？让AI直接输出不行吗？</p><p>因为代码的“可读性”和“可维护性”是两码事。AI能写出语法正确、结构完整的代码，但它不理解这段代码在系统整体中的位置、它和其他模块的关系、它在未来迭代中可能引发的连锁反应。</p><p>一个真实的例子：有团队用<a href="">Firebase</a>和<a href="">npm</a>包“Vibe-Coded”了整个认证流程。“在只支持简单登录时它能跑，但当需要多角色权限和区域隐私规则时，它彻底崩塌。没人能搞清楚各模块间的关联，中间件分散在六个文件里，没有逻辑模型，只有vibes。最后只能推倒重写，因为调试就像考古。”</p><p>在IDE中审阅，不是为了挑错，而是为了建立对代码库的“心智模型”——你知道每段代码为什么存在、它做什么、它和谁交互。没有这个心智模型，你就是在盲飞。</p><h2 id="必须实践"><a href="#必须实践" class="headerlink" title="必须实践"></a>必须实践</h2><h3 id="原则一：代码审查不是可选项，是必选项"><a href="#原则一：代码审查不是可选项，是必选项" class="headerlink" title="原则一：代码审查不是可选项，是必选项"></a>原则一：代码审查不是可选项，是必选项</h3><p><a href="">GitClear</a>的研究显示，到2024年，重复代码和频繁变更的现象比预测的还要严重，而提交历史中的重构活动却在减少。换句话说：AI在加速产生代码，但人类在放弃理解代码。</p><p>因此，</p><ul><li>所有AI生成的代码，必须经过人工审查才能合并</li><li>审查时不仅要看“对不对”，更要看“为什么”和“能不能更好”</li><li>建立团队级别的代码质量标准，AI必须遵守</li></ul><h3 id="原则二：让AI有计划，而不是有“幻觉”"><a href="#原则二：让AI有计划，而不是有“幻觉”" class="headerlink" title="原则二：让AI有计划，而不是有“幻觉”"></a>原则二：让AI有计划，而不是有“幻觉”</h3><p><a href="">Google</a>的<a href="">Gemini Code Assist</a>提供了一个好思路：Agent Mode会先提出详细计划让你审阅和批准，然后才开始改代码。</p><p>这意味着：你不是在被动接受AI的输出，而是在主动引导AI的方向。你始终是司机，AI只是导航。</p><h3 id="原则三：“第一版越笨，项目越成功”"><a href="#原则三：“第一版越笨，项目越成功”" class="headerlink" title="原则三：“第一版越笨，项目越成功”"></a>原则三：“第一版越笨，项目越成功”</h3><p><a href="">阿里云开发者社区</a>中，有一个观点正在成为共识：<em>“第一版越笨，项目越成功”</em> ——所谓“笨”，是主动限制决策自由度，优先保障可控性、可追踪与可复现。</p><p>换句话说：别一上来就让AI放飞自我。先用显式流程替代隐式推理，用结构化设计换取稳定性。等你对系统有了充分的掌控感，再逐步放开AI的自主权。</p><h3 id="原则四：给AI建立“护栏”"><a href="#原则四：给AI建立“护栏”" class="headerlink" title="原则四：给AI建立“护栏”"></a>原则四：给AI建立“护栏”</h3><p><a href="">亚马逊云科技</a>在2026年发布了《企业生产级智能体开发部署指南》，核心思路是建立科学的、以评估驱动的工程实践体系。</p><p>具体可以做的事：</p><ul><li>定义AI可调用的工具和API白名单</li><li>建立操作日志审计机制</li><li>设置明确的权限边界</li><li>定期进行代码质量评估</li></ul><h2 id="我们想要的是产品"><a href="#我们想要的是产品" class="headerlink" title="我们想要的是产品"></a>我们想要的是产品</h2><p>Vibe Coding最诱人的地方，是它把软件开发变成了一种即时反馈游戏——你提需求，AI生成代码；你说不好看，它改样式；你说报错，它给命令。</p><p>但这种“即时满足”是有代价的。当点击“Accept All”的那一刻，你其实是在签署一份技术债务的高利贷合同——现在的开发速度提升10倍，未来就需要100倍的维护成本。</p><p>文科生也好，理科生也好，编程老手也好，编程新手也好——在代码质量面前，众生平等。AI不会因为你“不会写代码”就对你格外宽容。恰恰相反，正因为你不会写代码，你才更需要建立“有掌控感”的工作方式——用审阅弥补经验的不足，用规则替代直觉的盲区。</p><p>别做AI代码的“甩手掌柜”。把代码放回IDE，逐行看，逐行想，逐行理解。你不是在写代码——你是在做一个产品，在建立一个系统，在承担一份责任。</p><hr><p>参考链接</p><ul><li><code>InfoQ</code> <a href="https://www.infoq.cn/article/t0rpY0X2G9RBmXf9SK6g">烧掉数万亿 Token、数百 Agent 连跑一周：Cursor“从零写浏览器”，结果是拼装人类代码？</a></li><li><code>BBC</code> <a href="https://www.bbc.com/news/articles/cpd2y053nleo?trk=public_post_comment-text">‘Vibe coding’ named word of the year by Collins Dictionary</a></li><li><code>网易新闻（极客公园）</code> <a href="https://www.163.com/dy/article/KMHI03IS05119FMA.html?referFrom=">文科生 72 小时杀入 GitHub 全球榜：我没写一行代码，但指挥了一支 AI 军队</a></li><li><code>InfoQ</code> <a href="https://www.infoq.cn/article/0XWhW4pj6qhEKEcJFrcy">Replit 怒锤“欧洲版 Cursor”：造出百款“高危”应用，普通开发者一小时内黑入，氛围编码成了黑客“天堂”？</a></li><li><code>Futurism</code> <a href="https://futurism.com/problem-vibe-coding?trk=article-ssr-frontend-pulse_x-social-details_comments-action_comment-text">Companies Are Discovering a Grim Problem With “Vibe Coding”</a></li><li><code>网易新闻</code> <a href="https://www.163.com/dy/article/KKPBR11B0511AQHO.html?spss=dy_author">Moltbook漏洞大到可以冒充Karpathy发帖，黑客都急了</a></li><li><code>澎湃新闻</code> <a href="https://m.thepaper.cn/newsDetail_forward_32530058?from=microsoft">“AI觉醒”神话戳破，Moltbook被曝手动操控智能体</a></li><li><code>智源社区</code> <a href="https://hub.baai.ac.cn/view/51948">168小时AI狂写300万行代码造出浏览器！Cursor公开数百个智能体自主协作方案</a></li><li><code>36氪</code> <a href="https://www.c114.net.cn/industry/97909.html">3位工程师靠「删AI代码」创业，一周收费1万美元：10万行删到3.5万行</a></li><li><code>36氪</code> <a href="https://m.36kr.com/p/728293647382">氛围编程行不通，CTO们集体炮轰AI编程：不是失业，而是失控</a></li><li><code>Thoughtworks Technology Radar</code> <a href="https://www.thoughtworks.com/radar/techniques/complacency-with-ai-generated-code">自满于 AI 生成的代码 | Technology Radar</a></li><li><code>Google for Developers</code> <a href="https://developers.google.com/assist/agent-mode">智能体模式概览 | Gemini Code Assist</a></li><li><code>阿里云开发者社区</code> <a href="https://developer.aliyun.com/article/1681232">智能体来了从 0 到 1：为什么第一版一定要“做得很笨”</a></li><li><code>ZOL云计算（亚马逊云科技）</code> <a href="https://cloud.zol.com.cn/932/9327546.html">亚马逊云科技发布《企业生产级智能体开发部署指南》</a></li></ul>]]></content:encoded>
      <category>开发</category>
      <category>AI</category>
      <category>VibeCoding</category>
      <category>代码审查</category>
      <category>技术债务</category>
      <category>AI Agent</category>
    </item>

    <item>
      <title>让 GitHub Copilot 接入任意大模型API</title>
      <link>https://pages.carm.cc/dev/azure-ai-proxy</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/azure-ai-proxy</guid>
      <pubDate>Fri, 12 Jun 2026 04:30:00 GMT</pubDate>
      <description><![CDATA[Copilot 涨价了？用 azure-ai-proxy 接入自己的 API，告别额度焦虑。开源代理工具，三步让 Copilot 支持任意 OpenAI 格式服务。]]></description>
      <content:encoded><![CDATA[<h2 id="背景：Copilot-的“额度之痛”"><a href="#背景：Copilot-的“额度之痛”" class="headerlink" title="背景：Copilot 的“额度之痛”"></a>背景：Copilot 的“额度之痛”</h2><p>2026 年 6 月 1 日，GitHub Copilot 做了一次<a href="https://github.blog/changelog/2026-04-20-changes-to-github-copilot-plans-for-individuals/">重大的计费调整</a>。 从原来固定的 Premium Request 模式，全面转向了基于 Token 用量的按量计费。</p><p>表面上月费没变——<em>Pro 依然是 10 美元&#x2F;月，Pro+ 是 39 美元&#x2F;月</em>——但实际上，这 10 美元和 39 美元现在变成了等额的 AI Credits 额度。用完了就得额外付费。</p><p><a href="https://github.com/orgs/community/discussions/192948">开发者社区</a>对此反应强烈。有人算了一笔账：原来每月不到 30 美元的使用成本，新规则下可能暴涨到 746 美元。 还有人晒出截图，月费从 50 美元直接飙到接近 3000 美元。一个 20 到 30 分钟的代码优化会话，就能烧掉 Pro 套餐 16% 的月额度。甚至有人抱怨“几个 prompt 就用掉了 700 credits”。</p><p>GitHub 自己也很坦白——他们在公告里说，Copilot 已经从 IDE 插件变成了一个能跑长周期、多步骤任务的 Agent 平台。一个简单问答和一次几小时的自主编码，成本天差地别，旧的定价模式已经撑不住了。</p><h2 id="解决方案：Azure-Deployment-代理"><a href="#解决方案：Azure-Deployment-代理" class="headerlink" title="解决方案：Azure Deployment 代理"></a>解决方案：Azure Deployment 代理</h2><p>Copilot 的新计费模式让很多开发者陷入了“额度焦虑”，尤其是那些依赖 Copilot 进行日常开发的程序员们。然而，现有的 Copilot 生态仅支持 OpenAI、Anthropic 的官方API，以及 OpenRouter 等少数第三方代理服务。对于想要使用自己 API Key 的开发者来说，Copilot 并不友好。</p><p>好在，Copilot 额外地支持通过 Azure OpenAI Service 的 Deployment 格式来调用大模型。也就是说，可以通过 Azure 部署服务来间接使用其他大模型 API。</p><p>但自行部署 Azure Service 并不容易。官方文档里有一大堆限制条件，且部署成本不低。对于个人开发者来说，既费时又费钱。</p><p>因此，我开发了 <a href="https://github.com/CarmJos/azure-ai-proxy">azure-ai-proxy</a> 这个开源代理工具，旨在打破 Copilot 对 Azure OpenAI Service 的独占依赖。</p><h3 id="它是什么？"><a href="#它是什么？" class="headerlink" title="它是什么？"></a>它是什么？</h3><p>简单来说，它是一个代理服务，能把任何 OpenAI 格式 的 API 服务提供商（包括 OpenAI 官方、Anthropic、第三方代理等）转化成 Azure Deployments 的格式，让 Copilot 等微软系产品“误以为”自己在调用 Azure，实际上所有请求都被代理转发到了您指定的服务商。</p><h3 id="为什么需要它？"><a href="#为什么需要它？" class="headerlink" title="为什么需要它？"></a>为什么需要它？</h3><p>Copilot、Copilot Studio 等微软系产品，目前原生只支持 Azure OpenAI Service 的 Deployment 格式。如果您想用自己的 API Key——不管是 OpenAI 官方、Anthropic、还是其他第三方供应商——Copilot 根本不认。azure-ai-proxy 就是这座桥梁。</p><h3 id="怎么用？"><a href="#怎么用？" class="headerlink" title="怎么用？"></a>怎么用？</h3><p>使用非常简单，只需三步：</p><ol><li>启动代理服务：在本地或服务器上运行 azure-ai-proxy。</li><li>配置 API 端点：在代理配置中填入您想要的任何 OpenAI 格式 API 的地址和密钥。</li><li>在 Copilot 中配置：将 Copilot 的 Azure Deployment 地址指向您的代理服务地址。</li></ol><p>之后，Copilot 的所有请求都会通过代理转发到您指定的服务商，而 Copilot 本身完全感知不到差异。</p><p><img src="images/using.png" alt="使用示意图" loading="lazy"></p><h3 id="解决了什么？"><a href="#解决了什么？" class="headerlink" title="解决了什么？"></a>解决了什么？</h3><p>不再受限于 Copilot 自带的额度——用您自己的 API，按您自己的节奏付费，成本完全可控。且可以接入任何 OpenAI 格式的供应商——价格、模型选择都更灵活，甚至可以切换不同模型做 A&#x2F;B 测试。同时，在 JetBrains IDE 和 VSCode 里，继续享受原生的 Copilot 交互体验，同时使用自己偏好的 API 后端。</p><h3 id="现存的小问题"><a href="#现存的小问题" class="headerlink" title="现存的小问题"></a>现存的小问题</h3><p>目前这个工具还有一些小问题，但我都在积极解决中。</p><p>特别是 Copilot 目前对上下文窗口（Context Window）无法识别，导致上下文窗口始终被固定为 100K，也就导致了部分模型超强上下文的能力丧失。</p><p><img src="images/context-window.png" alt="上下文窗口大小限制" loading="lazy"></p><p>不过我已经向官方提交了 <a href="https://github.com/microsoft/copilot-intellij-feedback/issues/1851">Issue</a>，官方回复将在下个月的更新中支持。所以这个问题很快就能解决。</p><p><img src="images/official-reply.png" alt="官方回复" loading="lazy"></p><p>除此之外，工具本身是开源的，欢迎大家去 GitHub 上提 Issue、提 PR，一起完善它。项目地址为 <a href="https://github.com/CarmJos/azure-ai-proxy">https://github.com/CarmJos/azure-ai-proxy</a> 。</p><h2 id="最后的话"><a href="#最后的话" class="headerlink" title="最后的话"></a>最后的话</h2><p>此项目的生命周期应该不会太长，毕竟 Copilot 官方计划支持BYOK。但当下如果您也遇到了 Copilot 额度不够用、或者想用自己的 API 在 IDE 里做有掌控感的 AI 开发，不妨试试azure-ai-proxy。它开源、免费，能帮您省下真金白银，同时保留您最熟悉的开发环境。</p><blockquote><p>截至2026年7月10日，GitHub Copilot 官方已经在beta版本中提供了支持任意 OpenAI API 的功能，但仍不完善。</p><p><img src="images/custom-endpoint.png" alt="自定义端点配置" loading="lazy"></p></blockquote><p>如果觉得有用，欢迎去 GitHub 点个 ⭐Star，这是对我最大的支持。也欢迎在评论区留言交流使用心得，或者提出改进建议。让我们一起打造更自由、更经济的 AI 开发工具链。</p><h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ul><li>&lt;<a href="https://github.blog/changelog/2026-04-20-changes-to-github-copilot-plans-for-individuals/">GitHub Copilot Pricing Changes</a>&gt;</li><li>&lt;<a href="https://learn.microsoft.com/en-us/azure/ai-services/openai/">Azure OpenAI Service Documentation</a>&gt;</li><li>&lt;<a href="https://github.com/CarmJos/azure-ai-proxy">azure-ai-proxy GitHub Repository</a>&gt;</li><li>&lt;<a href="https://techcrunch.com/2026/05/30/what-a-joke-github-copilots-new-token-based-billing-spurs-consternation-among-devs/">‘What a joke’: GitHub Copilot’s new token-based billing spurs consternation among devs</a>&gt;</li></ul>]]></content:encoded>
      <category>开发</category>
      <category>GitHub</category>
    </item>

    <item>
      <title>把子目录拆成独立项目的同时保留GIT历史提交信息</title>
      <link>https://pages.carm.cc/dev/extract-subdir-to-project</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/extract-subdir-to-project</guid>
      <pubDate>Tue, 12 May 2026 11:30:00 GMT</pubDate>
      <description><![CDATA[介绍如何使用 git format-patch 和 git am 将子目录拆分成独立项目，同时保留完整的 Git 历史提交记录。]]></description>
      <content:encoded><![CDATA[<h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>在我的日常开发或课程项目中，我常常会把相关联的多个模块放在一个总仓库里来方便开发和推进。例如在我的 Java 课程作业仓库 (<a href="https://github.com/CarmJos/java-courseworks">java-courseworks</a>) 里，除了有一些单独的课程作业目录外，还有一个 <code>practicum</code> 目录，里面是一个完整的学生管理系统实训项目。在完成后续的维护和展示过程中，我发现把实训项目和课程作业放在一起，虽然方便了初期的开发，但随着时间推移，出现了一些问题：</p><ol><li><strong>记录复杂</strong>：查看 <code>practicum</code> 相关改动时会被其它目录提交干扰。</li><li><strong>边界模糊</strong>：实训项目与课程作业是两类资产，其实并不适合放在一起。</li><li><strong>发布困难</strong>：在其他大型项目中，一个模块想独立维护、打包、发布时，会受父仓库结构影响。</li><li><strong>演示麻烦</strong>：给他人演示时，单独仓库更易理解与上手。</li></ol><p>因此，本次我们将要一步步实现：</p><ul><li>将 <code>practicum</code> 拆到新目录并初始化独立 Git 仓库；</li><li>复原指定区间的历史提交（包含提交信息与时间）；</li><li>解除对父 POM 的依赖，使其可独立构建；</li><li>配置独立远程仓库地址并推送到 GitHub 。</li></ul><h2 id="开始操作"><a href="#开始操作" class="headerlink" title="开始操作"></a>开始操作</h2><p>迁移前务必做好以下准备：</p><ol><li><strong>确认源仓库工作区干净</strong>（避免混入无关改动）。</li><li><strong>确认目标目录不存在或可安全覆盖</strong>。</li><li><strong>确认提交区间正确</strong>（尤其是起止 commit）。</li><li><strong>准备本地工具</strong>：Git。</li></ol><h3 id="Step-1：从源仓库导出指定区间的补丁"><a href="#Step-1：从源仓库导出指定区间的补丁" class="headerlink" title="Step 1：从源仓库导出指定区间的补丁"></a>Step 1：从源仓库导出指定区间的补丁</h3><p>我们需要先从源仓库导出仅 <code>practicum</code> 路径的补丁文件（保留提交顺序和元信息）。</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$patchDir</span> = <span class="string">&quot;D:\@DEV\java-courseworks\.tmp_patches&quot;</span></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">Test-Path</span> <span class="variable">$patchDir</span>) &#123; <span class="built_in">Remove-Item</span> <span class="variable">$patchDir</span> <span class="literal">-Recurse</span> <span class="literal">-Force</span> &#125;</span><br><span class="line"><span class="built_in">New-Item</span> <span class="literal">-ItemType</span> Directory <span class="literal">-Path</span> <span class="variable">$patchDir</span> | <span class="built_in">Out-Null</span></span><br><span class="line"></span><br><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\java-courseworks&quot;</span> <span class="literal">--no-pager</span> <span class="built_in">format-patch</span> <span class="literal">--binary</span> <span class="literal">--output-directory</span> <span class="variable">$patchDir</span> <span class="number">7</span>b47ec1755525f05cd76683215dad5ed3585fe6d^..<span class="number">1</span>effd2672b9a396db04668c0b1d9d89043f1aacd <span class="literal">--</span> practicum</span><br></pre></td></tr></table></figure><blockquote><p>注意：这里的文件目录路径 <code>D:\@DEV\java-courseworks</code>、子目录名称 <code>practicum</code> 与 commit 区间均为示例，请根据实际情况替换为所需要数值。</p></blockquote><p>其中，</p><ul><li><code>format-patch</code> 会按提交生成补丁，保留作者、时间、提交说明；</li><li><code>--binary</code> 确保图片等二进制文件也可迁移；</li><li><code>-- &lt;子目录名称&gt;</code> 只提取目标子目录相关改动。</li></ul><h3 id="Step-2：创建独立仓库目录并初始化-Git"><a href="#Step-2：创建独立仓库目录并初始化-Git" class="headerlink" title="Step 2：创建独立仓库目录并初始化 Git"></a>Step 2：创建独立仓库目录并初始化 Git</h3><p>这里我选择在原仓库同级目录下创建 <code>StudentUI</code> 目录作为新仓库，并初始化 Git：</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$target</span> = <span class="string">&quot;D:\@DEV\StudentUI&quot;</span></span><br><span class="line"><span class="built_in">New-Item</span> <span class="literal">-ItemType</span> Directory <span class="literal">-Path</span> <span class="variable">$target</span> <span class="literal">-Force</span> | <span class="built_in">Out-Null</span></span><br><span class="line">git <span class="literal">-C</span> <span class="variable">$target</span> init</span><br></pre></td></tr></table></figure><h3 id="Step-3：回放补丁并去掉子目录前缀"><a href="#Step-3：回放补丁并去掉子目录前缀" class="headerlink" title="Step 3：回放补丁并去掉子目录前缀"></a>Step 3：回放补丁并去掉子目录前缀</h3><p>由于目标仓库希望将 <code>practicum</code> 内容作为根目录，需要把路径前缀剥离。这里使用 <code>git am -p2</code>：</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$patches</span> = <span class="built_in">Get-ChildItem</span> <span class="string">&quot;D:\@DEV\java-courseworks\.tmp_patches\*.patch&quot;</span> | <span class="built_in">Sort-Object</span> Name | <span class="built_in">Select-Object</span> <span class="literal">-ExpandProperty</span> FullName</span><br><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> am <span class="literal">-p2</span> <span class="literal">--committer-date-is-author-date</span> <span class="variable">$patches</span></span><br></pre></td></tr></table></figure><p>其中，</p><ul><li><code>-p2</code>：将 <code>a/practicum/...</code> 或 <code>b/practicum/...</code> 裁剪成 <code>...</code>；</li><li><code>--committer-date-is-author-date</code>：使提交时间与作者时间保持一致，最大化还原历史。</li></ul><h3 id="Step-4：迁移后处理"><a href="#Step-4：迁移后处理" class="headerlink" title="Step 4：迁移后处理"></a>Step 4：迁移后处理</h3><p>此时已经成功迁移了历史提交，剩下的就是针对实际情况的一些后续处理了。</p><p>在本项目中，<code>StudentUI</code> 的 <code>pom.xml</code> 需要从“子模块”改为“独立项目”，简单修改一下 <code>pom.xml</code> 即可。</p><h3 id="Step-5：配置新仓库远程地址"><a href="#Step-5：配置新仓库远程地址" class="headerlink" title="Step 5：配置新仓库远程地址"></a>Step 5：配置新仓库远程地址</h3><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> remote add origin <span class="string">&quot;https://github.com/CarmJos/StudentUI&quot;</span></span><br><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> <span class="literal">--no-pager</span> remote <span class="literal">-v</span></span><br></pre></td></tr></table></figure><p>若已存在 <code>origin</code>，使用 <code>remote set-url</code> 即可。</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> remote <span class="built_in">set-url</span> origin <span class="string">&quot;https://github.com/CarmJos/StudentUI&quot;</span></span><br></pre></td></tr></table></figure><h3 id="Step-6：验证结果"><a href="#Step-6：验证结果" class="headerlink" title="Step 6：验证结果"></a>Step 6：验证结果</h3><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> <span class="literal">--no-pager</span> log <span class="literal">--oneline</span> <span class="literal">--decorate</span> <span class="literal">--max-count</span>=<span class="number">20</span></span><br><span class="line"></span><br><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> <span class="literal">--no-pager</span> status <span class="literal">--short</span> <span class="literal">--branch</span></span><br></pre></td></tr></table></figure><p>建议比对点：</p><ul><li>提交顺序是否与源区间一致；</li><li>提交时间是否保留；</li><li>图片等资源是否完整；</li></ul><h3 id="Step-7：推送到远程仓库"><a href="#Step-7：推送到远程仓库" class="headerlink" title="Step 7：推送到远程仓库"></a>Step 7：推送到远程仓库</h3><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> push origin HEAD:main</span><br></pre></td></tr></table></figure><p><strong>Done!</strong> 现在 <code>StudentUI</code> 仓库已经成功迁移了 <code>practicum</code> 相关的历史提交，并且可以独立维护了。</p><p>欢迎参观 <a href="https://github.com/CarmJos/StudentUI">StudentUI</a> 仓库，查看我本次迁移后的结果。</p><h2 id="归纳总结"><a href="#归纳总结" class="headerlink" title="归纳总结"></a>归纳总结</h2><p>为了方便后续复用，这里总结一下核心步骤：</p><ol><li><strong>导出补丁</strong>：<code>git format-patch --binary --output-directory &lt;补丁目录&gt; &lt;起始提交&gt;^..&lt;结束提交&gt; -- &lt;子目录&gt;</code></li><li><strong>初始化新仓库</strong>：<code>git init</code></li><li><strong>回放补丁</strong>：<code>git am -p2 --committer-date-is-author-date &lt;补丁目录&gt;/*.patch</code></li><li><strong>配置远程</strong>：<code>git remote add origin &lt;远程地址&gt;</code></li><li><strong>验证</strong>：查看日志、状态，确认历史与资源完整。</li></ol><h3 id="快速脚本"><a href="#快速脚本" class="headerlink" title="快速脚本"></a>快速脚本</h3><p>如果你只要一个可快速复刻的版本，只需替换以下命令中的路径、提交区间和远程地址即可：</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$srcParent</span> = <span class="string">&quot;D:\@DEV\java-courseworks&quot;</span></span><br><span class="line"><span class="variable">$srcDir</span> = <span class="string">&quot;practicum&quot;</span></span><br><span class="line"><span class="variable">$target</span> = <span class="string">&quot;D:\@DEV\StudentUI&quot;</span></span><br><span class="line"><span class="variable">$patchDir</span> = <span class="string">&quot;D:\@DEV\java-courseworks\.tmp_patches&quot;</span></span><br><span class="line"><span class="variable">$remoteUrl</span> = <span class="string">&quot;https://github.com/CarmJos/StudentUI&quot;</span></span><br><span class="line"><span class="variable">$startCommit</span> = <span class="string">&quot;7b47ec1755525f05cd76683215dad5ed3585fe6d&quot;</span></span><br><span class="line"><span class="variable">$endCommit</span> = <span class="string">&quot;1effd2672b9a396db04668c0b1d9d89043f1aacd&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">Test-Path</span> <span class="variable">$patchDir</span>) &#123; <span class="built_in">Remove-Item</span> <span class="variable">$patchDir</span> <span class="literal">-Recurse</span> <span class="literal">-Force</span> &#125;</span><br><span class="line"><span class="built_in">New-Item</span> <span class="literal">-ItemType</span> Directory <span class="literal">-Path</span> <span class="variable">$patchDir</span> | <span class="built_in">Out-Null</span></span><br><span class="line"></span><br><span class="line">git <span class="literal">-C</span> <span class="variable">$srcParent</span> <span class="literal">--no-pager</span> <span class="built_in">format-patch</span> <span class="literal">--binary</span> <span class="literal">--output-directory</span> <span class="variable">$patchDir</span> <span class="variable">$startCommit</span>^..<span class="variable">$endComit</span> <span class="literal">--</span> <span class="variable">$srcDir</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">New-Item</span> <span class="literal">-ItemType</span> Directory <span class="literal">-Path</span> <span class="variable">$target</span> <span class="literal">-Force</span> | <span class="built_in">Out-Null</span></span><br><span class="line">git <span class="literal">-C</span> <span class="variable">$target</span> init</span><br><span class="line"></span><br><span class="line"><span class="variable">$patches</span> = <span class="built_in">Get-ChildItem</span> <span class="string">&quot;<span class="variable">$patchDir</span>\*.patch&quot;</span> | <span class="built_in">Sort-Object</span> Name | <span class="built_in">Select-Object</span> <span class="literal">-ExpandProperty</span> FullName</span><br><span class="line">git <span class="literal">-C</span> <span class="variable">$target</span> am <span class="literal">-p2</span> <span class="literal">--committer-date-is-author-date</span> <span class="variable">$patches</span></span><br><span class="line"></span><br><span class="line">git <span class="literal">-C</span> <span class="variable">$target</span> remote add origin <span class="string">&quot;<span class="variable">$remoteUrl</span>&quot;</span></span><br></pre></td></tr></table></figure><blockquote><p>完成后别忘了手动进行后处理，并做一次日志与构建验证。</p></blockquote><p>同时，我还将相关操作整合成了一个可复用的 Python 脚本，方便在类似场景下快速执行，详见 <a href="https://github.com/CarmJos/git-dir-exporter">git-dir-exporter</a> 项目 <em>(欢迎Star~)</em> 。</p><h3 id="FAQ（常见问题）"><a href="#FAQ（常见问题）" class="headerlink" title="FAQ（常见问题）"></a>FAQ（常见问题）</h3><blockquote><p>如果有其他问题，欢迎在评论区留言，我会持续更新这个 FAQ。</p></blockquote><h4 id="Q1：为什么这里选择-git-format-patch-git-am，而不是直接复制目录？"><a href="#Q1：为什么这里选择-git-format-patch-git-am，而不是直接复制目录？" class="headerlink" title="Q1：为什么这里选择 git format-patch + git am，而不是直接复制目录？"></a>Q1：为什么这里选择 <code>git format-patch + git am</code>，而不是直接复制目录？</h4><p><strong>A：</strong> 直接复制目录只能拿到“当前快照”，拿不到历史；<code>format-patch + am</code> 可以逐条回放提交，保留提交说明、作者与时间，更适合教学、审计和后续追踪。</p><h4 id="Q2：为什么不是用-git-subtree-split？"><a href="#Q2：为什么不是用-git-subtree-split？" class="headerlink" title="Q2：为什么不是用 git subtree split？"></a>Q2：为什么不是用 <code>git subtree split</code>？</h4><p><strong>A：</strong> <code>subtree split</code> 也能完成子目录拆分，且会生成仅包含该子目录的新历史分支。本文选择 <code>format-patch + am</code> 的原因是：</p><ul><li>更直观展示“迁移区间”和“提交回放”的过程；</li><li>方便在迁移中插入额外处理（例如路径裁剪、单独补一条 POM 解耦提交）；</li><li>对教学场景更友好，读者容易理解每一步在做什么。</li></ul><p>如果你更偏向“一条命令出结果”，<code>subtree split</code> 也是可选方案。</p><h4 id="Q3：git-am-p2-里的-p2-是怎么确定的？"><a href="#Q3：git-am-p2-里的-p2-是怎么确定的？" class="headerlink" title="Q3：git am -p2 里的 -p2 是怎么确定的？"></a>Q3：<code>git am -p2</code> 里的 <code>-p2</code> 是怎么确定的？</h4><p><strong>A：</strong> 补丁路径通常是 <code>a/practicum/...</code> 与 <code>b/practicum/...</code>。需要去掉两层前缀（<code>a</code>&#x2F;<code>b</code> + <code>practicum</code>），所以用 <code>-p2</code>，最终让文件落在新仓库根目录。</p><h4 id="Q4：回放补丁时提示冲突怎么办？"><a href="#Q4：回放补丁时提示冲突怎么办？" class="headerlink" title="Q4：回放补丁时提示冲突怎么办？"></a>Q4：回放补丁时提示冲突怎么办？</h4><p><strong>A：</strong> 常规处理流程：</p><ol><li>查看冲突文件并手工解决；</li><li><code>git add &lt;冲突文件&gt;</code>；</li><li><code>git am --continue</code> 继续回放。</li></ol><p>如果发现本次迁移策略不对，可中止后重来：</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> am <span class="literal">--abort</span></span><br></pre></td></tr></table></figure><h4 id="Q5：如何确认提交时间是否真的保留了？"><a href="#Q5：如何确认提交时间是否真的保留了？" class="headerlink" title="Q5：如何确认提交时间是否真的保留了？"></a>Q5：如何确认提交时间是否真的保留了？</h4><p><strong>A：</strong> 可以分别查看源仓库与新仓库日志并对比时间戳：</p><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\java-courseworks&quot;</span> <span class="literal">--no-pager</span> log <span class="literal">--reverse</span> <span class="literal">--date</span>=iso<span class="literal">-strict</span> <span class="literal">--pretty</span>=format:<span class="string">&quot;%H|%ad|%cd|%s&quot;</span> <span class="number">7</span>b47ec1755525f05cd76683215dad5ed3585fe6d^..<span class="number">1</span>effd2672b9a396db04668c0b1d9d89043f1aacd <span class="literal">--</span> practicum</span><br><span class="line">git <span class="literal">-C</span> <span class="string">&quot;D:\@DEV\StudentUI&quot;</span> <span class="literal">--no-pager</span> log <span class="literal">--reverse</span> <span class="literal">--date</span>=iso<span class="literal">-strict</span> <span class="literal">--pretty</span>=format:<span class="string">&quot;%H|%ad|%cd|%s&quot;</span></span><br></pre></td></tr></table></figure>]]></content:encoded>
      <category>开发</category>
      <category>GitHub</category>
      <category>Java开发</category>
      <category>经验总结</category>
    </item>

    <item>
      <title>记一次外卖被偷的经历</title>
      <link>https://pages.carm.cc/story/2026/takeout-stolen</link>
      <guid isPermaLink="true">https://pages.carm.cc/story/2026/takeout-stolen</guid>
      <pubDate>Thu, 02 Apr 2026 11:32:51 GMT</pubDate>
      <description><![CDATA[记录一次外卖被偷后通过监控追查、报警找回的完整经历，以及对偷窃者的观察与思考。]]></description>
      <content:encoded><![CDATA[<h2 id="开端"><a href="#开端" class="headerlink" title="开端"></a>开端</h2><p>那是个寻常的礼拜四，我偏就馋那一锅子裹着厚面糊、炸得金黄焦脆的死鸡肉，激情下单一份疯狂的肯德基。</p><p>外卖快到时，我恰好内急。便让骑手挂在门把手上。想着左右不过一会儿功夫，索性再洗个澡。水汽氤氲里，我还盘算着待会儿怎么大快朵颐。这一泡屎一个澡，前前后后不过二十分钟。</p><p>且等我擦干头发，趿拉着拖鞋，满心欢喜地拉开那扇沉甸甸的防盗门时——迎面只有楼道里的一阵穿堂冷风。</p><p><strong>门把手光秃秃的，什么也没有。</strong></p><p>没有炸鸡，没有纸袋，连一丝油星子味都没留下。我愣在原地，脚底板那股子凉意顺着瓷砖直往天灵盖上窜。莫不是被保洁阿姨当废纸篓给收了？可谁家好人把热腾腾的饭菜当垃圾？又或是被野猫叼了去？可那么大还封了口的袋子，岂是一只野猫能拖得动的？</p><p>急吼吼拨通了送餐小哥的电话，听筒那头全是呼呼的风声和电瓶车的喇叭响，人家早忙得脚不沾地了，哪管得了这等闲事。再联系肯德基餐厅，回话也是冷冰冰的客套，只说东西送到了，丢了，只能报警。</p><h2 id="调查"><a href="#调查" class="headerlink" title="调查"></a>调查</h2><p>好在门顶上安了个黑乎乎的摄像头。点开手机里的录像，短短的报警片段里，一个身着格子衫、戴着橘黄色头盔的影子，从电梯口滑过来，手腕一勾，提溜起我的“疯狂星期四”，转身便没入楼道的阴影里。</p><p><img src="images/thief.jpg" alt="小偷截图" loading="lazy"></p><p>那一刻，心里头真是一股子无明业火腾地烧了起来。这身行头，分明也是个骑手！做着一样风里来雨里去的营生，却干这等偷鸡摸狗的勾当？我甚至趿拉着鞋，跑到上下两层楼去转了一遭，楼道里死寂死寂的，半个袋子的影儿也没见着。本打算联系物业调监控看看能不能找到这个人的身份信息，但细想要调取监控肯定是需要报警的，而报警又需要监控里能清晰地看到这个人的脸才能立案，所以就算报警了也不太可能有结果。</p><p><strong>本想就这么算了，当是舍给饿鬼了罢。可那口气堵在胸口，上不去下不来的。</strong></p><p>“不对，摄像头是有全天录像的！”我猛地反应过来，耐着性子，又再一点点往回倒腾监控的进度条。</p><ul><li>17:19 分，穿黄衣的美团小哥把袋子妥妥当当地挂上了门把手。</li><li>17:26 分，监控里出现了一个身穿黑色衣服、批橙色马甲，戴头盔的人从电梯方向走过来，直接把外卖拿走了，然后迅速离开了。</li></ul><p>服饰来看应该是淘宝闪购的骑手。此时其他可能性与排除，也可以确定并非是住户冒充外卖小哥来偷外卖的了。</p><p>我眯着眼，再往前倒了倒。17:25分，隔壁的门被敲得哐哐响，“外卖！”，又敲了三声，“外卖到了！” 且就在那光洁的瓷砖地反光里，隐隐约约晃过一抹橙色。</p><p><img src="images/knock.jpg" alt="敲门截图" loading="lazy"></p><p><strong>这事儿便全串起来了！</strong></p><p>这贪嘴的贼，先是给隔壁送了一份外卖，回头等电梯的当口，一转眼瞅见了我门上挂着的肯德基，腹中的馋虫一作祟，便顺手牵羊了。</p><p>我去敲了隔壁的门。开门的大哥倒是个热心肠，一听这等奇事，眼睛都亮了。两人一合计，查了单子。大概下午五点，大哥点了附近的一家“瑞幸咖啡”，详情显示“商家自配送”，17:26分送达。</p><p><img src="images/order.png" alt="订单截图" loading="lazy"></p><p><strong>对上了！</strong> 瑞幸的“自配送”一般都是由淘宝闪购负责配送的，而这个时间点又正好是那个身穿橙色马甲的骑手出现在监控里的时间点，所以基本上可以确定这个人就是偷我外卖的嫌疑人了。但是由于淘宝闪购的骑手信息在美团上无法显示，而平台上骑手的电话又是两次虚拟后的号码（淘宝闪购虚拟号提交到了美团上，美团又虚拟了一次），所以我无法直接联系到这个骑手。而商家呼叫骑手时肯定有骑手的身份信息，可以轻松找到对方。</p><p><strong>那么，就是现在了！</strong> 到了这份上，我反倒出奇的平静。我肯定是没有权利要求商家提供骑手的身份信息的，所以让我们有请伟大的人民警察吧！</p><h2 id="断案"><a href="#断案" class="headerlink" title="断案"></a>断案</h2><p>拨通110报了警，接线员简单了解过后，很快便有一位警官一位辅警上门了解情况。我向他们详细地说明了事情的经过，提供了监控录像和相关订单信息，随机做了笔录。<em>此时距离外卖被偷差不多过去了一个小时。</em></p><p><img src="images/police.jpg" alt="警察笔录" loading="lazy"></p><p>警察前脚刚走，后脚便来了电话：“诶，诶你好。我们到商家这里拿到骑手信息了，看到骑手现在就在旁边的沙县，人已经逮到了。他自己也知道问题的严重性，意思是要和你沟通一下，方不方便加个微信你们沟通下呢？…”</p><p>加上微信的那一瞬，手机震了一下。跳出来个顶着非主流头像的男生，微信名为 “牛马大帝” 。</p><p><img src="images/moments.png" alt="朋友圈截图" loading="lazy"></p><p><strong>十九岁。</strong></p><p>那人打过语音来，声音还带着点没褪干净的公鸭嗓，怯生生的，又透着点死猪不怕开水烫的滑头：“哥，不好意思拿了你门口的外卖，我错了。对不起哥。”</p><p>我没做声。听筒里只有他略显粗重的呼吸。</p><p>“我也不想这样啊，实在是饿了，咱们私了吧…”</p><p>我也不想把事情闹大，毕竟他还年轻，犯了错误也想要改正。他急忙补上一句：“那哥你给我个支付宝二维码吧，我微信没钱，我支付宝转账…”。</p><p>最后，那点可怜的饭钱，他竟是用花呗付过来的。我苦笑着多说了几句，劝他好自为之。</p><p>可警察大哥后来在电话里冷笑。</p><p>“这小子，是第三回了。”</p><hr><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>点开他那朋友圈，花花绿绿的，像是个万花筒。入眼便是张皱巴巴的“退学申请书”照片，往底下翻，全是些让人嘴巴发干的句子：</p><ul><li>“终于成为了小时候羡慕的大人，父母眼中的顶梁柱。”</li><li>“成熟的男孩烟酒入喉，优质的男儿爱字当头。”</li><li>…</li></ul><p>在这座由钢筋水泥构筑的城市丛林里，从不乏如浮萍般漂泊的年轻人，我亦如此。而仓促地合上书本，一头闯进光怪陆离的现实社会，为何口中只念叨着从短视频里拾来的 “江湖道义”，脑海里也只记得编织着兄弟结盟、快意恩仇的虚幻图景？渴望活得体面，渴望成为旁人眼中的 “顶梁柱”，却在生存的重压下，渐渐模糊了基本的价值底线。那句 “优质的男儿” 的自诩，倘若配上用花呗透支、甚至游走在规则边缘换来的一餐温饱，便成了一出令人心酸的荒诞剧 —— <strong>没有嘲讽的余地，只剩无奈的喟叹</strong> 。</p><p>我看着手机上那笔退回来的款，只觉得手心里那一阵油腻腻的冷汗，怎么也擦不干净了。</p><p><img src="images/last-words.png" alt="最后一语" loading="lazy"></p>]]></content:encoded>
      <category>往事</category>
      <category>生活</category>
      <category>解谜</category>
    </item>

    <item>
      <title>向日葵的花语</title>
      <link>https://pages.carm.cc/article/2026/sunflowers-floriography</link>
      <guid isPermaLink="true">https://pages.carm.cc/article/2026/sunflowers-floriography</guid>
      <pubDate>Mon, 19 Jan 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[从母亲用红包小游戏攒下的十元，谈起我们对“值不值得”的判断，以及有限选择里仍想照顾彼此的心意。]]></description>
      <content:encoded><![CDATA[<div class="admonition note"><p class="admonition-title">作者声明</p><p>本文中所出现的截图，以及文中的主角均来自网络。笔者所述为个人理解与想法，可能与事实不符。</p></div><p>年轻人为母亲的病和钱的事发愁。他劝母亲：“好好歇着，钱的事情我来想办法。” 而在聊天截图里，母亲的头像是一朵向日葵，还有一个十元的红包，跟着一句：</p><blockquote><ul><li>一晚上才搞到10元。</li></ul></blockquote><p>他没有立刻领，母亲又发来几条消息：</p><blockquote><ul><li>怎么不领</li><li>我玩游戏的钱</li><li>反正玩嘛</li><li>看你的手气</li></ul></blockquote><p><img src="assets/chat.png" alt="母亲发来十元红包的聊天记录" loading="lazy"></p><p>再看她的手机桌面，挤着许多标着红包的小游戏。那十元的来处，就藏在这些花花绿绿的图标里。</p><p><img src="assets/phone.png" alt="手机桌面上的红包小游戏" loading="lazy"></p><p>我们说“有这个时间，做点什么不好”，通常是因为心里已经有了别的去处。可以出门，可以工作，可以找一件更喜欢的事做。可对一个正在养病、又惦记着家里开销的人来说，这些选择未必就在手边。我们随口提出的办法，可能需要她此刻没有的体力、机会，甚至一笔先拿出来的钱。</p><p>她能做的事情少了，日子却仍要一小时一小时地过。一个能够打发时间、又能换来一点零用钱的游戏，便可能成为她当下最容易够到的选择。它未必有多好，却确实回应了某种需要。而十元对于一个人的分量，也不能只拿我们挣到十元所需的时间来衡量。</p><p>想到这里，我才觉得，<strong>自己过去的判断里藏着一点居高临下的傲慢</strong>。我太习惯从自己的生活出发，便把“我不需要”说成了“没有价值”，把“我有更好的选择”当成了“别人也理应如此”。至于那些更好的选择为什么没有出现在她的生活里，我甚至没有认真想过。</p><p>这些小游戏的存在，让我看见了一些过去忽略的需要，也看见了一场直接却未必对等的价值交换：用户交出时间与注意力，平台从广告中获得收益，再返还一点钱。有人愿意接受这样的交换，有她当下的理由；规则是否公平，仍然值得追问。用一句“存在即合理”概括，反而把这两件事混在了一起。</p><p>看见她为什么选择这些游戏之后，我更希望，这样的需要能得到好一点的回应：承诺能够兑现，规则说得清楚，少一点诱导人继续耗下去的设计。若能有更合适的消遣和补贴收入的机会，自然更好。尊重眼前的选择，也该包含让人有机会作出别的选择的愿望。</p><p>但这些道理，仍没有完全解释那几条消息为什么让我难过。她没有只说“给你十元”，还特意告诉孩子，这是自己玩游戏得来的钱。读起来，像是急着补上一句：你放心拿，我也能弄到一点。钱很少，可她仍能给孩子发一个红包，催他领取，让他“看你的手气”。在那一刻，她仍是那个想给孩子一点零花钱的妈妈。 她也许确实觉得游戏有趣，为自己攒到十元感到高兴。即使她没有把钱发给孩子，这份消遣也有她自己的意义。</p><p><strong>一个人需要被照顾以后，想要照顾别人的心，并不会跟着停下来。</strong> 我们忙着为亲人安排吃药、休息、花钱的事情，有时会忘记，她也可能正为我们的难处操心。我们盼着她安心接受照顾，她却还想找一个力所能及的办法，参与到这个家的生活里。</p><p>“好好歇着，钱的事情我来想办法”，是年轻人想替母亲卸下一点担子。“反正玩嘛”，也许是母亲想让这十元显得轻巧一些，好叫孩子收得安心。他们都想让对方少操一点心。只是一个把心意说成“交给我”，另一个把心意藏进“顺手的事”。</p><p><strong>在判断一种生活方式之前，先看一看过这种生活的人。</strong> 他有怎样的难处，又还珍惜着什么。我们当然可以指出一个选择的代价，但也该给对方留一点位置，让他说出这个选择对自己的意义。</p><p>我盼着天下母亲能够睡个安稳觉，年轻人不必总为钱发愁；盼着他们有一天再说“反正玩嘛”，却不必惦记着能换来多少钱。</p><p>写到这里，我又想起那个向日葵头像。向日葵的花语里，有阳光、忠诚、隐秘的爱，也有勇敢追梦与积极向上。我想，这些明亮的词，也容得下很平常的愿望：病能好起来，一家人的日子慢慢宽裕，孩子能够少皱几次眉头。</p><p>这样的向上，让我觉得可亲。人会累，会担忧，会嫌一晚上挣得太少，却仍愿意为明天做一点事，也愿意把一点好心情留给所爱的人。再看那个笑着的向日葵头像，我想到的，是他们各自说着“别担心”，又各自牵挂着对方的样子。</p><p>一声“好好歇着”，一句“看你的手气”。他们把日子里的一点亮光留给彼此，也把那句花语说得很轻：</p><p><strong>我的眼中只有你。</strong></p>]]></content:encoded>
      <category>随笔</category>
      <category>生活</category>
      <category>亲情</category>
      <category>社会观察</category>
    </item>

    <item>
      <title>【开发教程】高效快捷的Java配置文件库—configured入门</title>
      <link>https://www.bilibili.com/video/BV1XQQCYmE7F</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1XQQCYmE7F</guid>
      <pubDate>Sat, 15 Mar 2025 00:00:00 GMT</pubDate>
      <description><![CDATA[一次配置，轻松读取！ 一款简单便捷的通用配置文件加载、读取与更新工具，可自定义配置的格式。 项目地址: https://github.com/CarmJos/configured 我的Github账号地址: https://github.com/CarmJos]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1XQQCYmE7F">点击此处查看本视频 &gt;&gt;</a></p><p>一次配置，轻松读取！<br>一款简单便捷的通用配置文件加载、读取与更新工具，可自定义配置的格式。</p><p>项目地址: https://github.com/CarmJos/configured<br>我的Github账号地址: https://github.com/CarmJos</p>]]></content:encoded>
      <category>视频</category>
      <category>万物研究所</category>
      <category>程序员</category>
      <category>初学者</category>
      <category>编程</category>
      <category>教程</category>
      <category>Java</category>
      <category>万物研究所·春日探索企划</category>
    </item>

    <item>
      <title>【开发教程】送给C语言初学者—CLion常见问题答疑</title>
      <link>https://www.bilibili.com/video/BV1PU411S7Zw</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1PU411S7Zw</guid>
      <pubDate>Wed, 24 Jul 2024 00:00:00 GMT</pubDate>
      <description><![CDATA[本视频解答了 BV1kM411X7uA 视频下一些常见的问题，并额外提供了部分建议。 CMakeList文件地址: https://github.com/CarmJos/CWorks 我的Github账号地址: https://github.com/CarmJos 国内访问文件可以尝试使用：cdn.jsdelivr.net/gh/CarmJos/CWorks@master/CMakeLists.txt —[额外链接]—————————————————— JetBrains官网(中文): https://www.jetbrains.com/zh-cn/ CLion下载地址: https://www.jetbrains.com/zh-cn/clion/download/]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1PU411S7Zw">点击此处查看本视频 &gt;&gt;</a></p><p>本视频解答了 BV1kM411X7uA 视频下一些常见的问题，并额外提供了部分建议。</p><p>CMakeList文件地址: https://github.com/CarmJos/CWorks<br>我的Github账号地址: https://github.com/CarmJos</p><p>国内访问文件可以尝试使用：cdn.jsdelivr.net/gh/CarmJos/CWorks@master/CMakeLists.txt</p><p>—[额外链接]——————————————————<br>JetBrains官网(中文): https://www.jetbrains.com/zh-cn/<br>CLion下载地址: https://www.jetbrains.com/zh-cn/clion/download/</p>]]></content:encoded>
      <category>视频</category>
      <category>软件使用大百科</category>
      <category>C语言</category>
      <category>初学者</category>
      <category>编程</category>
      <category>教程</category>
      <category>科技猎手2024第2季</category>
    </item>

    <item>
      <title>C语言命名规范——以UNIX风格为例</title>
      <link>https://pages.carm.cc/dev/c-name-rules</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/c-name-rules</guid>
      <pubDate>Thu, 28 Dec 2023 11:30:00 GMT</pubDate>
      <description><![CDATA[以 UNIX 风格为例介绍 C 语言的命名规范，涵盖变量、函数、文件等命名约定。]]></description>
      <content:encoded><![CDATA[<h1 id="C语言命名规范——以UNIX风格为例"><a href="#C语言命名规范——以UNIX风格为例" class="headerlink" title="C语言命名规范——以UNIX风格为例"></a>C语言命名规范——以UNIX风格为例</h1><p>优秀的C语言代码通常遵循通用的代码规范原则，以确保代码的可读性和一致性。</p><p>虽然这些规则不是强制性的，但遵循它们可以大大帮助保持代码的逻辑可读性和一致性，特别是在团队协作或大型项目中。不同的项目或团队可能有自己的命名约定，所以最重要的是在一个项目或团队内保持一致性。</p><h2 id="基本规范"><a href="#基本规范" class="headerlink" title="基本规范"></a>基本规范</h2><ol><li><p><strong>避免使用保留字和标准库命名</strong>:</p><ul><li>避免使用C语言的关键字（如 <code>int</code>, <code>return</code>, <code>struct</code> 等）作为变量名。</li><li>同样，避免使用可能与标准库函数冲突的名称。</li></ul></li><li><p><strong>使用简洁且具有描述性的名称</strong>:</p><ul><li>选择简洁且具有描述性的名称，使其能够清晰地表达变量或函数的用途。例如，使用 <code>calculate_speed()</code> 而不是 <code>cs()</code>。</li><li>避免使用无意义的名称，如 <code>a</code>、<code>qwq</code> 或 <code>foo</code>。</li><li>选择单词时，首先要保障“<strong>贴切</strong>”，即词能达意，其次再去考虑长短。</li><li>尽量避免使用缩写，除非它们是通用的或广泛使用的。例如，<code>str</code> 代表字符串，<code>len</code> 代表长度。见 <a href="#%E9%80%9A%E7%94%A8%E7%BC%A9%E5%86%99">通用缩写</a>。</li></ul></li><li><p><strong>保持一致性</strong>：在同一项目或团队中保持文件命名的一致性非常重要。个人或团队内部应该商定并遵守统一的命名规范。</p></li></ol><blockquote><p><em>注1:</em> 也有一种命名函数名的风格是 首字母小写,后面单词首字母大写,中间不用连接符, 比如 <code>getMaxValue()</code>。而类名单词首字母大写不用分隔符,如 <code>class MyDateClass</code>；类的成员数据和方法的首单词首字母小写后面的单词首字母大写 如 <code>int superValue</code>。</p><p>JAVA的代码风格就是大致如此。</p></blockquote><h2 id="特定情况"><a href="#特定情况" class="headerlink" title="特定情况"></a>特定情况</h2><h3 id="1-文件命名"><a href="#1-文件命名" class="headerlink" title="1. 文件命名"></a>1. 文件命名</h3><p>在C语言项目中，文件命名的规范有助于帮助构建项目的整体结构。以下是一些常见的文件命名规范：</p><ol><li><strong>使用小写字母</strong>：文件名通常全部使用小写字母，以避免操作系统之间的兼容性问题（特别是在区分大小写的系统中）。</li><li><strong>使用下划线分隔</strong>：单词之间使用下划线（_）分隔，以提高可读性。例如：<code>char_calc.c</code> 或 <code>data_processing.h</code>。</li><li><strong>简洁且具描述性</strong>：文件名应简洁且能够清楚地描述文件内容。例如，如果文件包含一个实现链表功能的模块，则可以命名为 <code>linked_list.c</code>。</li><li><strong>区分头文件和源文件</strong>：<ul><li>源文件（.c 文件）：包含C语言的实现代码。例如：<code>main.c</code>, <code>score_calc.c</code>。</li><li>头文件（.h 文件）：包含函数声明、宏定义和类型定义等。与源文件相关联，通常名称相似。例如：<code>utils.h</code> 用于存放工具方法。</li></ul></li><li><strong>避免使用空格和特殊字符</strong>：避免在文件名中使用空格和特殊字符，如<code>%</code>, <code>&amp;</code>, <code>*</code>等，因为它们可能导致在某些环境或命令行操作中出现问题。</li><li><strong>使用有意义的前缀或后缀</strong>：对于大型项目，可以使用前缀或后缀来指示文件属于哪个模块或子系统。例如，使用<code>gui_button.c</code> 来表示该文件为图形用户界面模块中的按钮相关代码。</li><li><strong>避免过长的文件名</strong>：虽然现代操作系统支持较长的文件名，但过长的文件名可能不便于管理、识别和调用。所以，尽量保持文件名长度合理。</li></ol><h3 id="2-变量与常量"><a href="#2-变量与常量" class="headerlink" title="2. 变量与常量"></a>2. 变量与常量</h3><p>局部变量命名应当 <strong>全部使用小写字母，单词之间用下划线分隔</strong> 。局部变量可以简短，因为它们的作用域有限。例如：</p><ul><li><code>int my_variable;</code></li><li><code>void calculate_total();</code></li></ul><p>全局变量应该更加谨慎命名，可以使用前缀以避免命名冲突，例如：</p><ul><li><code>int g_some_value = 10;</code> 其中 <code>g_</code> 为前缀，代表 <em>GLOBAL</em>，即全局。</li></ul><p>对于常量，可以使用 <code>const</code> 关键字来定义，并采用 <strong>全大写下划线</strong> 风格例如：</p><ul><li><code>static const int DENOMINATIONS[] = { 2000, 1000 };</code> <a href="https://github.com/carm-outsource/CWorks/blob/master/src/calculator/change_calc.c#L7">[实例]</a></li></ul><p>而 <code>i, j, k, m, n, x, y, z</code> 等单字母变量普遍被用在索引、循环语句控制、数学函数等处。这是一种约定俗成的习惯，但是在其他地方使用单字母变量是不被推荐的，且不应当滥用。</p><h3 id="3-方法与函数"><a href="#3-方法与函数" class="headerlink" title="3. 方法与函数"></a>3. 方法与函数</h3><p>针对于方法，我们一般采取 “<code>动词_名词</code>” 的命名方式，且应当 <strong>全部使用小写字母，单词之间用下划线分隔</strong> ，例如：</p><ul><li><code>int get_file();</code></li><li><code>int calculate_total();</code></li><li><code>int get_max_value();</code></li><li><code>int is_valid();</code></li></ul><p>其中“动词” 通常用于表示方法的操作，例如 <code>calculate_total()</code> 计算总数，“名词” 通常用于表示方法的返回值类型，例如 <code>get_max_value()</code> 返回一个最大值。该部分是可选的，比如 有些方法不需要返回值，或者返回的内容已经隐藏在动词方法名或模块名中。</p><h3 id="4-类型与结构体"><a href="#4-类型与结构体" class="headerlink" title="4. 类型与结构体"></a>4. 类型与结构体</h3><p>自定义类型（如结构体和联合体）通常使用<strong>大驼峰式</strong>或<strong>全大写下划线</strong>风格。例如：</p><ul><li><code>typedef struct { ... } MyStruct;</code></li><li><code>typedef struct { ... } MY_STRUCT;</code></li></ul><h3 id="5-宏变量与枚举"><a href="#5-宏变量与枚举" class="headerlink" title="5. 宏变量与枚举"></a>5. 宏变量与枚举</h3><p>宏常量和枚举通常全部使用大写字母，单词之间用下划线分隔。这样做是为了与普通变量和函数区分开。例如：</p><ul><li><code>#define MAX_LENGTH 100</code></li><li><code>enum { RED, GREEN, BLUE };</code></li></ul><h2 id="常见操作单词"><a href="#常见操作单词" class="headerlink" title="常见操作单词"></a>常见操作单词</h2><ul><li>add&#x2F;remove</li><li>begin&#x2F;end</li><li>create&#x2F;destroy</li><li>insert&#x2F;delete</li><li>first&#x2F;last</li><li>get&#x2F;release</li><li>increment&#x2F;decrement</li><li>put&#x2F;get</li><li>add&#x2F;delete</li><li>lock&#x2F;unlock</li><li>open&#x2F;close</li><li>min&#x2F;max</li><li>old&#x2F;new</li><li>start&#x2F;stop</li><li>next&#x2F;previous</li><li>source&#x2F;target</li><li>show&#x2F;hide</li><li>send&#x2F;receiver</li><li>source&#x2F;destination</li><li>copy&#x2F;paste</li><li>up&#x2F;down</li></ul><h2 id="通用缩写"><a href="#通用缩写" class="headerlink" title="通用缩写"></a>通用缩写</h2><p>这里是一些通用的缩写，选择性使用。</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">addition —&gt; add</span><br><span class="line">answer —&gt; ans</span><br><span class="line">array —&gt; arr</span><br><span class="line">average—&gt;avg </span><br><span class="line">argument —&gt; arg</span><br><span class="line">buffer —&gt; buff/buf</span><br><span class="line">clock —&gt; clk</span><br><span class="line">calculate —&gt; calc</span><br><span class="line">column —&gt; col</span><br><span class="line">control —&gt; ctrl</span><br><span class="line">command —&gt; cmd</span><br><span class="line">compare —&gt; cmp</span><br><span class="line">configuration —&gt; config/cfg</span><br><span class="line">count —&gt; cnt</span><br><span class="line">define —&gt; def</span><br><span class="line">delete —&gt; del</span><br><span class="line">destination—&gt;dst/dest</span><br><span class="line">display—&gt; disp</span><br><span class="line">device —&gt; dev</span><br><span class="line">decode —&gt; dec</span><br><span class="line">division —&gt; div</span><br><span class="line">frequency—&gt;freq</span><br><span class="line">error —&gt; err</span><br><span class="line">environment —&gt; env</span><br><span class="line">encode —&gt; enc</span><br><span class="line">hexadecimal —&gt; hex</span><br><span class="line">header —&gt; hdr</span><br><span class="line">index —&gt; idx</span><br><span class="line">image —&gt; img</span><br><span class="line">initialize —&gt; init</span><br><span class="line">increment —&gt; inc</span><br><span class="line">length—&gt;len</span><br><span class="line">make —&gt; mk</span><br><span class="line">maximum —&gt; max</span><br><span class="line">message —&gt; msg</span><br><span class="line">minimum —&gt; min</span><br><span class="line">multiplication—&gt;multi</span><br><span class="line">memory—&gt;mem</span><br><span class="line">middle—&gt;mid</span><br><span class="line">number —&gt; num</span><br><span class="line">option—&gt;opt</span><br><span class="line">parameter —&gt; para</span><br><span class="line">previous —&gt; prev</span><br><span class="line">pointer —&gt; ptr</span><br><span class="line">register —&gt; reg</span><br><span class="line">receiver—&gt;recv</span><br><span class="line">return —&gt; ret</span><br><span class="line">result—&gt;res</span><br><span class="line">source —&gt; src</span><br><span class="line">stack—&gt;stk</span><br><span class="line">string—&gt;str</span><br><span class="line">subtraction—&gt;sub</span><br><span class="line">semaphore —&gt; sem</span><br><span class="line">statistic —&gt; stat</span><br><span class="line">synchronize —&gt; sync</span><br><span class="line">table —&gt;tab</span><br><span class="line">temp —&gt; tmp</span><br><span class="line">temporary—&gt;tmp/temp</span><br><span class="line">timestamp—&gt;ts</span><br><span class="line">value—&gt;val</span><br><span class="line">width—&gt;wid</span><br></pre></td></tr></table></figure>]]></content:encoded>
      <category>开发</category>
      <category>C语言</category>
      <category>初学者</category>
    </item>

    <item>
      <title>【学生必薅】用证明申请Jetbrains的免费教育授权</title>
      <link>https://www.bilibili.com/video/BV1ja4y1f7iK</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1ja4y1f7iK</guid>
      <pubDate>Sun, 26 Nov 2023 00:00:00 GMT</pubDate>
      <description><![CDATA[本视频适用于使用Jetbrains系开发软件的学生，指导如何申请独属于自己的Jetbrains教育授权，安心使用正版最新开发软件。 —[相关链接]—————————————————— JetBrains官网(中文): https://www.jetbrains.com/zh-cn/ 教育授权申请表: https://www.jetbrains.com/shop/eform/students]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1ja4y1f7iK">点击此处查看本视频 &gt;&gt;</a></p><p>本视频适用于使用Jetbrains系开发软件的学生，指导如何申请独属于自己的Jetbrains教育授权，安心使用正版最新开发软件。</p><p>—[相关链接]——————————————————<br>JetBrains官网(中文): https://www.jetbrains.com/zh-cn/<br>教育授权申请表: https://www.jetbrains.com/shop/eform/students</p>]]></content:encoded>
      <category>视频</category>
      <category>1024程序员节来了</category>
      <category>软件</category>
      <category>教育</category>
      <category>教程</category>
      <category>正版</category>
      <category>软件分享</category>
      <category>授权</category>
      <category>1024·2023活动征稿</category>
    </item>

    <item>
      <title>【开发教程】送给C语言初学者—CLion安装流程与注意事项</title>
      <link>https://www.bilibili.com/video/BV1kM411X7uA</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1kM411X7uA</guid>
      <pubDate>Sat, 28 Oct 2023 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1kM411X7uA">点击此处查看本视频 &gt;&gt;</a></p>]]></content:encoded>
      <category>视频</category>
      <category>1024打卡挑战</category>
      <category>C语言</category>
      <category>初学者</category>
      <category>教程</category>
      <category>编程</category>
      <category>1024·2023活动征稿</category>
    </item>

    <item>
      <title>【上手实测】Sony MRW-G2 | CF-A/SD 二合一读卡器，削铁入尼！</title>
      <link>https://www.bilibili.com/video/BV11o4y1g74g</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV11o4y1g74g</guid>
      <pubDate>Thu, 25 May 2023 00:00:00 GMT</pubDate>
      <description><![CDATA[关于我换掉希铁CFA读卡器入手Sony MRW-G2的这件事。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV11o4y1g74g">点击此处查看本视频 &gt;&gt;</a></p><p>关于我换掉希铁CFA读卡器入手Sony MRW-G2的这件事。</p>]]></content:encoded>
      <category>视频</category>
      <category>科技猎手2023</category>
      <category>评测</category>
      <category>数码</category>
      <category>索尼</category>
      <category>外设</category>
      <category>必剪创作</category>
    </item>

    <item>
      <title>【上手实测】红米Note12 Turbo 首轮入手短评: 巨香，可冲</title>
      <link>https://www.bilibili.com/video/BV19M4y1U7b2</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV19M4y1U7b2</guid>
      <pubDate>Fri, 31 Mar 2023 00:00:00 GMT</pubDate>
      <description><![CDATA[这一部应该是我这个地区第一个激活的手机。 红米干爆小米！]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV19M4y1U7b2">点击此处查看本视频 &gt;&gt;</a></p><p>这一部应该是我这个地区第一个激活的手机。</p><p>红米干爆小米！</p>]]></content:encoded>
      <category>视频</category>
      <category>科技猎手2023</category>
      <category>小米</category>
      <category>手机</category>
      <category>红米</category>
      <category>上手测评</category>
    </item>

    <item>
      <title>【开发教程】还在用破解器临时账号？快免费申请JetBrains开源开发者授权！</title>
      <link>https://www.bilibili.com/video/BV1sa411X7Y3</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1sa411X7Y3</guid>
      <pubDate>Sat, 02 Jul 2022 00:00:00 GMT</pubDate>
      <description><![CDATA[JetBrains 官网：https://www.jetbrains.com/ 开源授权申请：https://www.jetbrains.com/opensource/ 我的Github主页: https://github.com/CarmJos]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1sa411X7Y3">点击此处查看本视频 &gt;&gt;</a></p><p>JetBrains 官网：https://www.jetbrains.com/<br>开源授权申请：https://www.jetbrains.com/opensource/</p><p>我的Github主页: https://github.com/CarmJos</p>]]></content:encoded>
      <category>视频</category>
      <category>发现《Menti (Original Mix)》</category>
      <category>技术宅的夏天</category>
      <category>免费授权</category>
      <category>软件开发</category>
      <category>IDEA</category>
      <category>软件分享</category>
      <category>开源软件</category>
      <category>JetBrains</category>
      <category>打卡挑战</category>
      <category>科技猎手计划2022第二季</category>
    </item>

    <item>
      <title>南京的烤鸭</title>
      <link>https://pages.carm.cc/article/2022/roasted-duck</link>
      <guid isPermaLink="true">https://pages.carm.cc/article/2022/roasted-duck</guid>
      <pubDate>Mon, 07 Mar 2022 11:30:00 GMT</pubDate>
      <description><![CDATA[一篇关于南京烤鸭的随笔，通过爷爷留鸭腿的温暖记忆，讲述亲情与乡愁的简单故事。]]></description>
      <content:encoded><![CDATA[<p>日子总是在不知不觉中就淌过去了。</p><p>那是哪一年的事？早记不大清了。 只晓得那天电视里正放着什么动画片，叽叽喳喳的声响里，一个小人儿正抱着根同自己半个身子差不多大的鸡腿，啃得满嘴冒油。</p><p>我那时人小，肚子里的馋虫却被这光景勾得乱窜，连呼吸里都像凭空生出了一股子肉香。我咽了口唾沫，转头便冲着屋外正忙着劈竹的爷爷嚷嚷：“爷爷，我也要吃大鸡腿！” 爷爷抬头瞥了我一眼，手也没停，也没言语，由着我这没头没脑的叫唤散在风里飘。</p><p>到了傍晚，天刚擦黑，饭桌上却突兀地多出个东西，温温的，裹在塑料袋里。</p><p>塑料袋摊在碗里，果木炭的焦香混着股浑厚的咸甜味，轰的一下便撞进了鼻腔。是一副红艳艳的烤鸭。那年月，孩孩童哪里懂得什么讲究，管它鸡腿鸭腿，能解馋就是顶好的。爷爷竟不知用了什么法子，那鸭腿被留得格外多。我迫不及待地，一把攥住那只肥大的鸭腿，指尖滑腻腻的，全是烤得焦脆的鸭皮渗出的亮油。我就这么一手举着鸭腿，一手猛扒着碗里的白米饭，腮帮子鼓得不像话。一家人挤在灯泡底下，看着我这狼狈的馋样，都“咯咯”地笑着…</p><p>这一晃，十年的水便流去了。</p><p>我早像个羽翼渐丰的野鸟，扑腾着飞出了那个青石板铺就的小镇。爷爷奶奶年岁大了，早搬到了楼房里住。长大的日子总是忙碌且生硬，钢筋水泥把人困得像个打转的陀螺，我竟鲜能挤出回家的空档。 可是呀，说来也怪，无论我哪日踏进那扇防盗门，无论外头是个什么季节光景，只要一落座，我的白瓷碗里，总安安稳稳地卧着一只酱红色、泛着肥软光泽的烤鸭腿。</p><p>奶奶端着碗从厨房走出来，笑眯眯的，眼角的褶子叠在一起，操着那口老南京话冲我念叨：</p><p><strong>“乖乖，留的大鸭腿给你哎！南头斩的，你最欢喜吃个！”</strong></p><p>我不做多想，左手夹起腿，大口吞咽，任由那股浓烈的酱香味在舌尖慢慢化开。恍惚间，竟又回到了十年前那个咋咋呼呼的傍晚。</p><p><strong>南头，说的是驷马河的南面。从新房走，约莫十五里路。</strong></p><p><img src="images/picture.jpg" alt="烤鸭" loading="lazy"></p>]]></content:encoded>
      <category>随笔</category>
      <category>生活</category>
      <category>亲情</category>
      <category>乡土情结</category>
    </item>

    <item>
      <title>为何我的部分轻量插件的体积十分&quot;庞大&quot;？</title>
      <link>https://pages.carm.cc/dev/why-plugins-huge</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/why-plugins-huge</guid>
      <pubDate>Wed, 02 Mar 2022 18:32:02 GMT</pubDate>
      <description><![CDATA[解释 Minecraft 插件为何打包依赖类库导致体积较大，探讨用户体验与轻量化之间的权衡。]]></description>
      <content:encoded><![CDATA[<p>有朋友和我说 “一个<a href="https://github.com/CarmJos/TimeReward">自动领奖插件</a>就快400kb，是不是太臃肿了？”。 我觉得针对这种问题应当统一作出解释。</p><h2 id="关于用户体验"><a href="#关于用户体验" class="headerlink" title="关于用户体验"></a>关于用户体验</h2><p>这其实是一种个人代码风格的选择，不同开发者的风格也大多不相同。在很早的时候，我和这位朋友一样，对于一个明明功能很简单的插件打包了许多类库这种事情感到十分可笑。但随着我接的各种小单子越来越多，接触的用户越来越多，我发现程序员思维在这里似乎并不适用。</p><p>其实这种问题只要做一个核心类库插件就全部解决了。但作为用户来说，相比于要额外安装一个依赖插件，我更喜欢开箱即用的感觉，而非安装一个插件需要额外安装许许多多杂七杂八的类库。举个例子，如果我想使用一个插件，需要额外安装作者的一个类库；如果要使用的插件来自于多个作者，岂不是需要额外安装许许多多的类库？</p><p>因此，作为一个插件覆盖面并不广泛的开发者，我选择每个插件都单独打包类库，而让用户无需对此焦虑。</p><h2 id="关于高版本接口"><a href="#关于高版本接口" class="headerlink" title="关于高版本接口"></a>关于高版本接口</h2><p>这时候又有人想问“为何不使用高版本提供的依赖接口，直接让服务端下载依赖使用，从而减小插件的大小呢？”</p><p>其实理由已经出现在问题里了。没错，这个功能需要“<strong>高版本</strong>”。</p><p>相比于为了减小插件体积而使用这个功能，以导致只有高版本才可以使用，我更倾向于让一个插件能够覆盖到更多的版本，从而减少用户的选择成本。</p><p>让我们回到用户的视角，面对一个功能需求上很适合自己的插件，却因为版本过低而无法使用，而这的原因仅仅是开发者为了让插件看上去更“轻量化”去使用高版本的依赖接口从而失去了低版本用户的支持，我相信，这个时候用户更希望的是在自己的服务器也能用上这款插件，而不是我们需要的“轻量化”。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>总而言之，是否打包类库到插件纯属开发者的个人习惯。有的人喜欢“轻量”而自行挑选重要内容放到自己的插件中，有的人更爱“便捷”而一股脑全塞上，也有的人会为了“用户体验”而做出一点大小上的牺牲。</p><p>如果是三年前的我，我会强烈推荐你做一个“依赖库插件”，它能够很好的解决插件实际功能和大小不等的问题同时还能让这个插件在不同的服务器版本中得到支持；但如果是现在的我，我会推荐你好好考虑，对于单个功能插件，在必要的情况下直接打包依赖库也完全没问题的：虽然需要在“轻量化”上做出一些牺牲，但可以让使用的用户得到更好的体验，在我看来这是一个更好的决定。</p><hr><p>文章作者为 @CarmJos ，同时感谢 @nelson 帮助校对文章。</p>]]></content:encoded>
      <category>开发</category>
      <category>MineCraft</category>
    </item>

    <item>
      <title>自动部署Javadoc到Github Pages</title>
      <link>https://pages.carm.cc/dev/javadoc-in-github</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/javadoc-in-github</guid>
      <pubDate>Tue, 23 Nov 2021 17:24:00 GMT</pubDate>
      <description><![CDATA[教程：使用 GitHub Actions 自动构建 Maven Javadoc 并部署到 GitHub Pages。]]></description>
      <content:encoded><![CDATA[<h2 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h2><p>由于想开一个新坑，打算把项目通过Maven生成的的Javadoc使用 <a href="https://docs.github.com/en/actions/learn-github-actions">Github Actions</a> 自动部署到同项目下 <code>gh-pages</code> 分支，作为该项目 <a href="https://pages.github.com/">Github Pages</a> 的主页供其他人参考。</p><h2 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h2><h3 id="1-配置-Maven-生成JavaDoc"><a href="#1-配置-Maven-生成JavaDoc" class="headerlink" title="1. 配置 Maven 生成JavaDoc"></a>1. 配置 Maven 生成JavaDoc</h3><p>首先在项目的 <code>pom.xml</code> 中添加 <a href="https://maven.apache.org/plugins/maven-javadoc-plugin/">Maven Javadoc Plugin</a> ,依赖这个插件，我们可以自动生成JavaDoc。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">plugin</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>maven-javadoc-plugin<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.2.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">classifier</span>&gt;</span>javadoc<span class="tag">&lt;/<span class="name">classifier</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">detectJavaApiLink</span>&gt;</span>true<span class="tag">&lt;/<span class="name">detectJavaApiLink</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">encoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">encoding</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">charset</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">charset</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">docencoding</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">docencoding</span>&gt;</span></span><br><span class="line">            <span class="comment">&lt;!-- &lt;locale&gt;zh_CN&lt;/locale&gt; 可选，使用中文的界面--&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">executions</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">execution</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">id</span>&gt;</span>attach-javadocs<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">goals</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">goal</span>&gt;</span>jar<span class="tag">&lt;/<span class="name">goal</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">goals</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">execution</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">executions</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">plugin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">plugins</span>&gt;</span></span><br></pre></td></tr></table></figure><p>设置过后，我们就可以输入 <code>mvn javadoc:javadoc</code> 命令生成该项目的Javadoc了，生成的路径一般在 <code>target/site/apidoc/</code> 下。</p><div class="admonition note"><p>如果是使用的 <code>mvn package</code> 命令，则会生成在 <code>target/apidoc/</code> 下。</p></div><h3 id="2-配置Github项目的Deploy-Keys与Secrets"><a href="#2-配置Github项目的Deploy-Keys与Secrets" class="headerlink" title="2. 配置Github项目的Deploy Keys与Secrets"></a>2. 配置Github项目的<code>Deploy Keys</code>与<code>Secrets</code></h3><p>因为我们需要把Javadoc放到同项目下的<code>gh-pages</code>分支，因此在Actions中需要进行认证操作，才可以正常推送。</p><p>这里我们打算采用SSH进行推送，并通过 Deploy Keys 进行认证。</p><h4 id="a-生成-OpenSSH-密钥"><a href="#a-生成-OpenSSH-密钥" class="headerlink" title="a. 生成 OpenSSH 密钥"></a>a. 生成 OpenSSH 密钥</h4><p>我们可以访问 <a href="https://8gwifi.org/sshfunctions.jsp">Generate SSH Keys Online</a> 在线生成一个密钥。</p><p><img src="images/generate-key.png" alt="generate key" loading="lazy"></p><p>点击后，在下方会生成对应的私钥(Private Key)与公钥(Public Key)，我们先记下。</p><h4 id="b-添加私钥到-Secrets"><a href="#b-添加私钥到-Secrets" class="headerlink" title="b. 添加私钥到 Secrets"></a>b. 添加私钥到 <code>Secrets</code></h4><p>复制上一步得到的私钥，添加到项目的<code>Secrets</code>中。</p><p><img src="images/add-secret.png" alt="add secret" loading="lazy"></p><p>名字(Name)填<code>DEPLOY_PRI</code>,数值(Value)填私钥内容</p><p><img src="images/confirm-add-secret.png" alt="confirm secret" loading="lazy"></p><h4 id="c-添加公钥到-Deploy-Keys"><a href="#c-添加公钥到-Deploy-Keys" class="headerlink" title="c. 添加公钥到 Deploy Keys"></a>c. 添加公钥到 <code>Deploy Keys</code></h4><p>复制之前得到的公钥，添加到项目的<code>Deploy Keys</code>中。</p><p><img src="images/add-deploy-keys.png" alt="add deploy key" loading="lazy"></p><p>名字(Title)可以随便填，我这里选择的是<code>JAVADOC_DEPLOY</code>，密钥(Key)填公钥内容。注意一定要勾选 “<strong>Allow write access</strong>“, 这样才可以被用于推送。</p><p><img src="images/confirm-add-deploy-key.png" alt="confirm deploy key" loading="lazy"></p><h3 id="3-配置-Github-Actions"><a href="#3-配置-Github-Actions" class="headerlink" title="3. 配置 Github Actions"></a>3. 配置 Github Actions</h3><p>在项目下新建 <code>.github/workflows/javadoc.yml</code> 文件。这个文件会被自动识别为<a href="https://docs.github.com/en/actions/learn-github-actions">Github Actions</a>配置文件。</p><div class="admonition note"><p>记得也要在Settings中启用 Github Actions ，否则无法使用哦。</p></div><p>内容如下</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">Javadoc</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="comment"># 支持手动触发构建</span></span><br><span class="line">  <span class="attr">workflow_dispatch:</span></span><br><span class="line">  <span class="attr">release:</span></span><br><span class="line">    <span class="comment"># 创建release的时候触发</span></span><br><span class="line">    <span class="attr">types:</span> [ <span class="string">published</span> ]</span><br><span class="line"><span class="comment">#  push: # 可选，在推送主分支时触发</span></span><br><span class="line"><span class="comment">#    branches:</span></span><br><span class="line"><span class="comment">#    - main</span></span><br><span class="line"><span class="comment">#    - master</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">apidoc-deploy:</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Checkout</span> <span class="string">the</span> <span class="string">repo</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/checkout@v2</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">the</span> <span class="string">Java</span> <span class="string">JDK</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-java@v2</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">java-version:</span> <span class="string">&#x27;11&#x27;</span></span><br><span class="line">          <span class="attr">distribution:</span> <span class="string">&#x27;adopt&#x27;</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Generate</span> <span class="string">docs</span> <span class="comment">#生成Javadoc</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">mvn</span> <span class="string">javadoc:javadoc</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Copy</span> <span class="string">to</span> <span class="string">Location</span> <span class="comment"># 复制Javadoc到一个新文件夹，便于进行git操作</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          rm -rf docs</span></span><br><span class="line"><span class="string">          mkdir -vp docs</span></span><br><span class="line"><span class="string">          cp -vrf target/site/apidocs/* docs/</span></span><br><span class="line"><span class="string"></span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Generate</span> <span class="string">the</span> <span class="string">sitemap</span> <span class="comment"># 可选，生成sitemap</span></span><br><span class="line">        <span class="attr">id:</span> <span class="string">sitemap</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">cicirello/generate-sitemap@v1</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">base-url-path:</span> <span class="string">https://carmjos.github.io/userprefix</span></span><br><span class="line">          <span class="attr">path-to-root:</span> <span class="string">docs</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Configure</span> <span class="string">Git</span> <span class="comment"># 配置Git</span></span><br><span class="line">        <span class="attr">env:</span></span><br><span class="line">          <span class="attr">DEPLOY_PRI:</span> <span class="string">$&#123;&#123;secrets.DEPLOY_PRI&#125;&#125;</span> <span class="comment"># 这里就是刚刚配置的私钥了</span></span><br><span class="line">          <span class="attr">GIT_USERNAME:</span> <span class="string">$&#123;&#123;</span> <span class="string">github.repository_owner</span> <span class="string">&#125;&#125;</span> <span class="comment">#Github用户名，这里用了Actions自带的变量，也可以写死。</span></span><br><span class="line">          <span class="attr">GIT_EMAIL:</span> <span class="string">$&#123;&#123;</span> <span class="string">github.repository_owner</span> <span class="string">&#125;&#125;@user.github.com</span> <span class="comment"># 邮箱,可以写自己的邮箱。</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          sudo timedatectl set-timezone &quot;Asia/Shanghai&quot;</span></span><br><span class="line"><span class="string">          mkdir -p ~/.ssh/</span></span><br><span class="line"><span class="string">          echo &quot;$DEPLOY_PRI&quot; &gt; ~/.ssh/id_rsa</span></span><br><span class="line"><span class="string">          chmod 600 ~/.ssh/id_rsa</span></span><br><span class="line"><span class="string">          ssh-keyscan github.com &gt;&gt; ~/.ssh/known_hosts</span></span><br><span class="line"><span class="string">          git config --global user.name &#x27;$DEPLOY_PRI&#x27;</span></span><br><span class="line"><span class="string">          git config --global user.email &#x27;$DEPLOY_PRI&#x27;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Commit</span> <span class="string">documentation</span> <span class="comment"># 提交文档到Git仓库</span></span><br><span class="line">        <span class="attr">env:</span></span><br><span class="line">          <span class="attr">GIT_URL:</span> <span class="string">&quot;git@github.com:&lt;USERNAME&gt;/&lt;PROJECT&gt;.git&quot;</span> <span class="comment"># 项目的地址，注意要用SSH格式的。</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          cd docs</span></span><br><span class="line"><span class="string">          git init</span></span><br><span class="line"><span class="string">          git remote add origin $GIT_URL</span></span><br><span class="line"><span class="string">          git checkout -b gh-pages</span></span><br><span class="line"><span class="string">          git add -A</span></span><br><span class="line"><span class="string">          git commit -m &quot;API Document generated.&quot;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Push</span> <span class="string">javadocs</span> <span class="comment"># 推送</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">|</span></span><br><span class="line"><span class="string">          cd docs</span></span><br><span class="line"><span class="string">          git push origin HEAD:gh-pages --force</span></span><br></pre></td></tr></table></figure><p>随后，推送项目，在Actions界面找到该配置，手动触发一次。</p><p><img src="images/run-action.png" alt="run-action" loading="lazy"></p><p>等待其正常跑完，即可发现多了一个 <code>gh-pages</code> 分支。</p><h3 id="4-设置-Github-Pages"><a href="#4-设置-Github-Pages" class="headerlink" title="4. 设置 Github Pages"></a>4. 设置 Github Pages</h3><p>在项目的Settings界面找到 Pages 一栏，选择 <code>gh-pages</code> 分支，点击 Save ，等待片刻即可访问 <code>&lt;用户名&gt;.github.io/&lt;项目名&gt;</code> 看到项目的Javadoc了。</p><p><img src="images/setting-pages.png" alt="Setting Pages.png" loading="lazy"></p><h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ul><li>&lt; <a href="https://docs.github.com/en/actions">Github Actions Documentation</a> &gt;</li><li>&lt; <a href="https://maven.apache.org/plugins/maven-javadoc-plugin/index.html">Apache Maven Javadoc Plugin</a> &gt;</li><li>&lt; <a href="https://ucsb-cs56-pconrad.github.io/topics/javadoc_publishing_to_github_pages_from_public_repo/">javadoc: publishing to github pages from a public repo</a> &gt;</li></ul>]]></content:encoded>
      <category>开发</category>
      <category>GitHub</category>
      <category>Java开发</category>
      <category>经验总结</category>
    </item>

    <item>
      <title>为什么Git分支开始从&quot;master&quot;变为&quot;main&quot;了？</title>
      <link>https://pages.carm.cc/dev/branch-main</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/branch-main</guid>
      <pubDate>Tue, 02 Nov 2021 05:32:02 GMT</pubDate>
      <description><![CDATA[探讨 Git 默认分支从 master 改为 main 的社会背景与技术变革，以及如何迁移现有项目。]]></description>
      <content:encoded><![CDATA[<h2 id="发现"><a href="#发现" class="headerlink" title="发现"></a>发现</h2><p>一开始接触 Git 的时候，默认的分支名都为 <code>master</code> ，包括后续使用的时候也习惯于输入<code>master</code>进行各类操作。</p><p>而我最近发现，<a href="https://github.com/">Github</a> 与 <a href="https://about.gitlab.com/">Gitlab</a> 都开始使用 <code>main</code> 取代原先的 <code>master</code>作为项目的默认主分支了，这是为什么呢？</p><h2 id="起源-“Black-Lives-Matter”"><a href="#起源-“Black-Lives-Matter”" class="headerlink" title="起源 - “Black Lives Matter”"></a>起源 - “Black Lives Matter”</h2><p>自2020年六月起，由于“Black Lives Matter”抗议活动持续发酵，而计算机行业中对<code>master</code>与<code>slave</code>这两个词的使用引起了部分人的反感。</p><p>在抗议声起、社会动荡加剧之时，更多的人认为这些包含历史文化因素的词汇已经过时，且应当被替换，于是多个开源项目开始采取行动替换冒犯性的术语，其中包括PHPUnit 和 Curl、OpenZFS 等。</p><p>不仅仅是<code>master</code>与<code>slave</code>,还有许多相关的词汇如<code>whitelist</code>与<code>blacklist</code>都被计划更改为<code>allowList</code>与<code>denyList</code>。</p><p>正如 <a href="https://www.zdnet.com/article/github-to-replace-master-with-main-starting-next-month/">ZDNet</a>所说，继续使用这些带有种族色彩的词汇可能会延长种族歧视。一些学者在 2018 年的期刊上写道，“这些术语不仅反映了种族主义文化，而且还强化、合法化和延续了它。”</p><p>而 LinkedIn 的软件工程师 Gabriel Csapo 也在 Twitter 上表示，他也正在提出更新 Microsoft 内部库的请求，并删除任何带有种族歧视色彩的短语。</p><h2 id="行动"><a href="#行动" class="headerlink" title="行动"></a>行动</h2><p>在此背景下，一位Twitter网友的提议，而这一提议得到了GitHub CEO的支持。<img src="images/una_kravets.png" alt="Twitter" loading="lazy"></p><blockquote><p><strong>@Una Kravets</strong>我很高兴将 GitHub 的默认分支结构从『master』改成『main』，我希望我们能和 @GitHub 一起以社区为单位来做这件事……<strong>@Nat Friedman</strong>这是个好主意！ 我们正在朝这方面进行改进了！</p></blockquote><p>于是自 2020年10月1日 开始，Github上所有的新库便都开始以 <code>main</code> 命名，并开始逐渐的将原先<code>master</code>为主分支的库修改为以<code>main</code>为主分支。</p><p>鉴于GitHub有4000多万用户、1亿多个存储库以及至少2800万个公共存储库，这是项艰巨的任务。任何一个规划的失误都会导致Linux内核之类的项目代码无法访问。全球大批企业依赖Linux内核，一旦发生这类事件都可能引发灾难性的后果。</p><p>于是，GitHub又做了以下更改以确保万无一失：</p><ul><li><a href="https://github.blog/changelog/2020-07-17-links-to-deleted-branches-now-redirect-to-the-default-branch/">更新了 GitHub.com</a>以直接重定向<code>master</code>分支到新的默认分支！</li><li><a href="https://github.blog/changelog/2020-07-31-build-and-deploy-github-pages-from-any-branch-beta/">更新了 Github Pages</a>以支持从任一分支进行部署</li><li><a href="https://github.blog/changelog/2020-08-26-set-the-default-branch-for-newly-created-repositories/">添加了用户、组织与企业设定</a>以设定默认的分支名与新项目的默认分支名。<ul><li>需要注意的是，这些设定同时在 <a href="https://github.com/new">GitHub.com</a>与 <a href="https://developer.github.com/v3/guides/getting-started/#create-a-repository">GitHub API</a> 生效。</li><li><a href="https://github.blog/2020-07-27-highlights-from-git-2-28/#introducing-init-defaultbranch">Git 2.28</a> 也添加了一个类似的设定<code>init.defaultBranch</code>。</li></ul></li><li><a href="https://github.com/github/renaming#rename-existing">我们让重命名已有分支更加方便快捷了</a></li></ul><h2 id="参与"><a href="#参与" class="headerlink" title="参与"></a>参与</h2><p>如果还是习惯于使用 <code>master</code> 分支，那么大可不用更改继续使用下去。</p><p>若想要支持相关的行动，则可以跟随以下的操作将<code>master</code>分支无损迁移到<code>main</code>分支。</p><h3 id="本地修改分支"><a href="#本地修改分支" class="headerlink" title="本地修改分支"></a>本地修改分支</h3><ol><li><p>首先将<code>master</code>分支移到<code>main</code>分支下</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -m master main</span><br></pre></td></tr></table></figure></li><li><p>随后将新命名的分支<code>main</code>推送到远程库中</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push -u origin main</span><br></pre></td></tr></table></figure></li><li><p>再将HEAD指向<code>main</code>分支</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main</span><br></pre></td></tr></table></figure></li><li><p>最后删除远程库中旧的<code>master</code>分支即可</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin --delete master</span><br></pre></td></tr></table></figure></li></ol><h3 id="在-GitHub-上修改默认分支"><a href="#在-GitHub-上修改默认分支" class="headerlink" title="在 GitHub 上修改默认分支"></a>在 GitHub 上修改默认分支</h3><p>用户、组织和企业可以在以下地址修改默认分支名。</p><ul><li>用户 <code>https://github.com/settings/repositories</code></li><li>组织所有者 <code>https://github.com/organizations/&lt;组织名&gt;/settings/repository-defaults</code></li><li>企业管理员 <code>https://github.com/enterprises/&lt;企业名&gt;/settings/member_privileges</code></li></ul><p><img src="images/settings.png" alt="Settings" loading="lazy"></p><h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ul><li>&lt; <a href="https://github.com/github/renaming">Github Renaming</a> &gt;</li><li>&lt; <a href="https://www.zdnet.com/article/github-to-replace-master-with-main-starting-next-month/">GitHub to replace ‘master’ with ‘main’ starting next month</a> &gt;</li><li>&lt; <a href="https://www.theserverside.com/feature/Why-GitHub-renamed-its-master-branch-to-main">Why GitHub renamed its master branch to main</a> &gt;</li></ul>]]></content:encoded>
      <category>开发</category>
      <category>GitHub</category>
    </item>

    <item>
      <title>记首次实现3D设计与打印的经历</title>
      <link>https://pages.carm.cc/story/2021/first-3d-design</link>
      <guid isPermaLink="true">https://pages.carm.cc/story/2021/first-3d-design</guid>
      <pubDate>Tue, 29 Jun 2021 07:30:00 GMT</pubDate>
      <description><![CDATA[记录首次为 PiKVM 设计并打印 3D 外壳的完整过程，包括设计、失败、改进的实战经验。]]></description>
      <content:encoded><![CDATA[<h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>自己在家里组了一个机柜，有多个服务器设备需要管理。看到 <a href="https://pikvm.org/">PiKVM</a> 这个项目后觉得非常有趣，很快就搓了一个。</p><p>刚搓完的成品就直接固定在一块木板上，随后给木板打了几个孔，直接用螺丝固定在机柜上。说真的，每次看到那个 PiKVM “板子”，我心里都发虚。虽然功能上完全满足了需求，但那几根红红绿绿的杜邦线在外头晃荡，怎么看也不太安全。<img src="images/before.png" alt="before" loading="lazy"></p><p><strong>不行，这得改。</strong></p><p>我手头刚好有一台创想三维的 CR-6 SE，但现在的我对 3D 设计的认知基本还停留在“画个方块”的水平。<img src="images/3d-printer.jpg" alt="3D打印机" loading="lazy"></p><p>既然有了这个需求，不如趁此机会，就自己设计一个外壳吧。</p><h2 id="开始设计"><a href="#开始设计" class="headerlink" title="开始设计"></a>开始设计</h2><p>最开始的设计是一个凹下去的盒子和一个盖板，直接把 PiKVM 的主板放在盒子里，然后直接盖上盖板。</p><p>然而这个设计的缺点是没有考虑到3D打印的局限性。</p><p>切片软件跳出“17小时”那个数字的时候，我就开始挠头了。我所持的是一台开放式的 FDM打印机，所以在打印过程中很难保证能完全成功的打印一整个盒子，而且如果打印失败了，就只能重新打印整个盒子，浪费时间和材料。</p><p>于是我便将盒子的各个面设计成了单独的部件，这样即使某个部件打印失败了，也只需要重新打印那个部件就好了。各个部件之间用方形点链接，这样就可以保证它们能够正确的对齐并牢固的连接在一起。</p><p><img src="images/design.jpg" alt="design" loading="lazy"></p><p><strong>出稿，拆件，打印！</strong></p><p>那天下午特别闷，房间里全是那种 PLA耗材熔化后的甜腻味儿。设计的底板件的面积比较大，所以在打印过程中出现了翘边的问题。更绝的是，挤出机那边居然开始打滑，“哒、哒、哒”地干磨。我摸了一下挤出机的电机，烫得手指生疼。</p><p><strong>原来是打印时间过长，电机过热，耗材全在里头软成烂泥了。</strong></p><p>没办法，我翻出个不知道哪儿拆下来的旧散热片，用硅脂粘在在电机上。又掏出个小风扇，直接对着电机吹，试图让它降温。虽然这个方法有点土，但至少确实有效了。</p><p>拿着失败件先对一下尺寸，才发现尺寸设计的也有误，空位无法完全对齐，而最终导致其他部件也都无法正确的安装在底板上。<img src="images/wrong-holes-2.jpg" alt="错误的孔位" loading="lazy"></p><p>修改，再试打印底板。空位确实是对上了，可惜仍然出现了翘边的问题。考虑到材料的浪费和时间的消耗… 将就着用吧。</p><p>随后就是剩余部件的打印了。一样的，打印，翘边，再打印，失败，再打印，炒面，打印……总之就是反复的失败和打印，直到最后所有部件都成功的打印出来了。</p><p><img src="images/failed-prints.jpg" alt="失败的部件" loading="lazy"></p><p>中途X轴的电机轴居然还断了，得亏还有备用的42步进电机，不然就只能等快递了。<em><del>要不然说 3D打印 的本质是修3D打印机呢(</del></em></p><p><img src="images/broken-motor.jpg" alt="断轴" loading="lazy"></p><p>剩下的就是喜闻乐见的最终组装了。由于之前设计的连接点比较牢固，所以组装起来还是比较顺利的。</p><p><img src="images/case-open.png" alt="组装" loading="lazy"><img src="images/case-gears.jpg" alt="组装" loading="lazy"></p><p>成品还是不错的。虽然表面还有点拉丝，虽然有点寄出缺陷，虽然有点翘边，虽然一捏就容易变形…但还是非常满意的。毕竟这是我第一次设计和打印3D模型，能成功的完成已经不错了。</p><p><img src="images/case-front.jpg" alt="正面" loading="lazy"><img src="images/case-back.jpg" alt="背面" loading="lazy"></p><h2 id="思考与总结"><a href="#思考与总结" class="headerlink" title="思考与总结"></a>思考与总结</h2><p>回望这次从 0 到 1 的首次设计，收获远在成品之外：</p><ol><li><p><strong>设计必须服务于工艺。</strong>在电脑里画出的精美模型，如果无视物理世界的重力、热缩和机械精度，那只能称之为“数字雕塑”。优秀的工程师应当提前在脑海中模拟打印机的每一个动作，根据设备特性去倒推零件的结构，这远比画图本身更重要。</p></li><li><p><strong>模块化是风险管理的必修课。</strong>整体式设计虽然美观，但在抗风险能力上极其脆弱。将复杂系统拆解为可替换、可重构的小模块，不仅适用于软件开发中的解耦，在物理制造中同样是节省成本、提高迭代效率的黄金法则。</p></li><li><p><strong>拥抱“不完美”的勇气。</strong>工程实践中没有绝对的完美。为了进度而妥协的微小翘边底板、为了强度而增加的粗糙加固筋，都是解决现实问题的勋章。完成优于完美，在不断的反馈循环中迭代，才是技术进化的唯一路径。</p></li></ol><p>如今这机器仍然在我家机柜里默默地工作着，虽然外表看起来只是一个普通的塑料盒子，但它背后却凝聚了我无数次的尝试、失败和改进。</p>]]></content:encoded>
      <category>往事</category>
      <category>设计</category>
      <category>3D打印</category>
      <category>嵌入式开发</category>
    </item>

    <item>
      <title>【上手实测】小米降噪耳机Pro FlipBuds Pro 一周使用体验与购买建议</title>
      <link>https://www.bilibili.com/video/BV1C54y1V7hz</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1C54y1V7hz</guid>
      <pubDate>Thu, 27 May 2021 00:00:00 GMT</pubDate>
      <description><![CDATA[个人一周使用心得。 视频为主观言论，仅对本人手上的这对耳机负责哦。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1C54y1V7hz">点击此处查看本视频 &gt;&gt;</a></p><p>个人一周使用心得。<br>视频为主观言论，仅对本人手上的这对耳机负责哦。</p>]]></content:encoded>
      <category>视频</category>
      <category>小米</category>
      <category>体验</category>
      <category>蓝牙耳机</category>
      <category>降噪耳机</category>
      <category>FlipBudsPro</category>
    </item>

    <item>
      <title>FilpBuds Pro降噪耳机在小米10/10 Pro上的设置入口</title>
      <link>https://www.bilibili.com/video/BV1d64y1C7CY</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1d64y1C7CY</guid>
      <pubDate>Fri, 21 May 2021 00:00:00 GMT</pubDate>
      <description><![CDATA[希望MIUI尽快更新放出入口叭，太难找了。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1d64y1C7CY">点击此处查看本视频 &gt;&gt;</a></p><p>希望MIUI尽快更新放出入口叭，太难找了。</p>]]></content:encoded>
      <category>视频</category>
      <category>智能生活大作战</category>
      <category>耳机</category>
      <category>小米</category>
      <category>降噪</category>
      <category>降噪耳机</category>
      <category>小米10</category>
    </item>

    <item>
      <title>【开发日记】YourCraft决斗游戏又更新了~</title>
      <link>https://www.bilibili.com/video/BV1TK4y1Q7Nw</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1TK4y1Q7Nw</guid>
      <pubDate>Sat, 13 Feb 2021 00:00:00 GMT</pubDate>
      <description><![CDATA[YourCraft Team 2021 YC小游戏① 966485310 YC小游戏② 973478638 ———————————— 该视频在决斗游戏内部测试中录制，该视频录制过程中没有任何动物收到伤害。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1TK4y1Q7Nw">点击此处查看本视频 &gt;&gt;</a></p><p>YourCraft Team 2021<br>YC小游戏① 966485310<br>YC小游戏② 973478638<br>————————————<br>该视频在决斗游戏内部测试中录制，该视频录制过程中没有任何动物收到伤害。</p>]]></content:encoded>
      <category>视频</category>
      <category>MINECRAFT</category>
      <category>我的世界</category>
      <category>游戏开发</category>
      <category>YC</category>
      <category>你的世界</category>
      <category>YourCraft</category>
      <category>游戏头号玩家</category>
    </item>

    <item>
      <title>【开发日记】 YourCraft开发者间的决斗！(决斗游戏测试)</title>
      <link>https://www.bilibili.com/video/BV13o4y197Am</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV13o4y197Am</guid>
      <pubDate>Thu, 04 Feb 2021 00:00:00 GMT</pubDate>
      <description><![CDATA[YourCraft Team 2021 YC小游戏① 966485310 YC小游戏② 973478638 ———————————— 该视频在决斗游戏内部测试中录制，该视频录制过程中没有任何动物收到伤害。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV13o4y197Am">点击此处查看本视频 &gt;&gt;</a></p><p>YourCraft Team 2021<br>YC小游戏① 966485310<br>YC小游戏② 973478638<br>————————————<br>该视频在决斗游戏内部测试中录制，该视频录制过程中没有任何动物收到伤害。</p>]]></content:encoded>
      <category>视频</category>
      <category>PVP</category>
      <category>单挑</category>
      <category>你的世界</category>
      <category>MineCraft</category>
      <category>YourCraft</category>
    </item>

    <item>
      <title>Java写的阿里域名DDNS程序 配置简单运行稳定 还可以多域名更新</title>
      <link>https://www.bilibili.com/video/BV1t54y147aQ</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1t54y147aQ</guid>
      <pubDate>Wed, 09 Dec 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[如果你想要这个软件的话，可以私信给我你的邮箱，我看到后会尽快发给你哦~ 使用aliyun DDNS 支持A记录和AAAA记录，公网IPv6均可正常使用。 --- 2021年11月1日更新 项目最近重构了一次，并公开于github，喜欢的小伙伴可以star一下哦~ 项目地址 https://github.com/CarmJos/AliDDNS-Updater 软件下载 https://github.com/CarmJos/AliDDNS-Updater/releases]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1t54y147aQ">点击此处查看本视频 &gt;&gt;</a></p><p>如果你想要这个软件的话，可以私信给我你的邮箱，我看到后会尽快发给你哦~</p><p>使用aliyun DDNS 支持A记录和AAAA记录，公网IPv6均可正常使用。</p><p>--- 2021年11月1日更新<br>项目最近重构了一次，并公开于github，喜欢的小伙伴可以star一下哦~</p><p>项目地址 https://github.com/CarmJos/AliDDNS-Updater<br>软件下载 https://github.com/CarmJos/AliDDNS-Updater/releases</p>]]></content:encoded>
      <category>视频</category>
      <category>B站有潮玩</category>
      <category>JAVA</category>
      <category>程序员</category>
      <category>服务器</category>
      <category>教程</category>
      <category>阿里云</category>
      <category>互联网</category>
      <category>DDNS</category>
    </item>

    <item>
      <title>写给一位cn2b2t玩家的信</title>
      <link>https://pages.carm.cc/story/2020/cn2b2t</link>
      <guid isPermaLink="true">https://pages.carm.cc/story/2020/cn2b2t</guid>
      <pubDate>Mon, 02 Nov 2020 05:32:02 GMT</pubDate>
      <description><![CDATA[一封写给 cn2b2t 玩家的告别信，回顾项目历程并表达对未来的期许。]]></description>
      <content:encoded><![CDATA[<figure class="hexo-letter" data-paper="plain" style="--hlp-paper:#fffdf8;--hlp-ink:#26221e;--hlp-tilt:-0.25deg;--hlp-font-size:1.15em;--hlp-indent:2em" data-letter-label="信笺 01"><button type="button" class="hexo-letter__fold" hidden aria-label="打开信笺 01" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation">尊敬的cn2b2t玩家：</p><p>您好！</p><p>一九年的七月二十日，我心血来潮，花了短短的一会时间制作了cn2b2t。令我意向不到的是，这小小的举动竟然引起了许多玩家的响应，让我们这群充满梦想与激情的开发者更有了一丝前进的动力。但有意经营管理经验不足，2020年7月17日，我们无奈的选择关服休整，让所有开发者回归学业，并尽力去打拼自己的未来。</p><p>我们不得不向您致歉，我们使大量的玩家失去了过往的汗水与记忆，也失去了部分游戏中的战友，这也令我们难以释怀。好在，还有您愿意从我们手中接走回忆的接力棒，我也相信您也会很好的保留这些美好的记忆，谢谢您。</p><p>同时我也须向您致歉，由于服务器数据保存不当，自2020年6月换新服后的数据难以读取，故我拷贝给予您的副本是较老的地图文件，还请您谅解。</p><p>Kar Network承载了我们数十位开发者、管理者的游戏梦，如今距关服已有三个月，回首过去，有喜悦，也有遗憾。喜悦在于拥有你们这些支持我们的玩家，遗憾则是我们没有为你们交出完美的答卷。我们会吸取过往的教训，总结成功的经验，并在不久的将来进行新的尝试。我们坚信，唯有用心与坚持，才能抓住新的机会。</p><p>我们一直在努力，我们希望您也实现自己梦想的道路上继续坚持。我相信，我们将会在不久的将来，以全新的姿态，与您再会。这条梦想之路，我们与您手牵手，共同前行。</p><p>望共勉！</p><div align=right>    <div>CarmJos</div>    <div>        2020年11月2日    </div></div></blockquote></div></figure><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>本项目代码已开源，见 <a href="https://github.com/CarmJos/cn2b2t-project">cn2b2t-project(Github.com)</a> 。如有需要可自取，希望能对社区有所帮助。</p>]]></content:encoded>
      <category>往事</category>
      <category>MineCraft</category>
    </item>

    <item>
      <title>Kar Network 关服通知</title>
      <link>https://pages.carm.cc/story/2020/kar-closed</link>
      <guid isPermaLink="true">https://pages.carm.cc/story/2020/kar-closed</guid>
      <pubDate>Fri, 17 Jul 2020 07:30:00 GMT</pubDate>
      <description><![CDATA[Kar Network Minecraft 服务器的关服告别信，回顾五年的运营历程并向玩家致歉。]]></description>
      <content:encoded><![CDATA[<h2 id="来自全体管理组成员的致歉书"><a href="#来自全体管理组成员的致歉书" class="headerlink" title="来自全体管理组成员的致歉书"></a>来自全体管理组成员的致歉书</h2><figure class="hexo-letter" data-paper="plain" style="--hlp-paper:#fffdf8;--hlp-ink:#26221e;--hlp-tilt:0.25deg;--hlp-font-size:1.15em;--hlp-indent:2em" data-letter-label="信笺 01"><button type="button" class="hexo-letter__fold" hidden aria-label="打开信笺 01" aria-haspopup="dialog"></button><div class="hexo-letter__body"><blockquote><p class="hexo-letter__salutation">亲爱的玩家，大家好：</p><p>自 2015 年首次开服以来，Kar Network 已经陪伴大家五个春秋，得到了广大玩家的支持与厚爱。回顾开服以来我们和各位一起度过了无数个欢乐的日子，由衷的感激大家给予的支持与帮助！</p><p>由于运营不当，自2015年起遍入不敷出，至此已无法继续承担高额的维护费用。且由于现有所有服务环境(包括但不限于 服务管理器、开发站、服务器官网、服务器运行环境、构建开发环境)均基于本台主机，，这些环境所花费的金钱、时间和精力无法复制，无法还原，也就直接告示着未来的维护不再可能，我们在MineCraft的路上就此终结。</p><p>综上所述，Kar Network、MineCarl 及其附属、相关服务器将在2020年7月20日凌晨00:00停止服务。</p><p>借此机会，通知所有使用本团队运行环境的个体、团队，在关服前迁移所有相关数据，如关服后存在数据遗失问题，本团队概不负责，恳请谅解。</p><p>最后感谢您的陪伴，希望在往后的日子里能与您共同回忆这段美好时光。也希望能在我们未来开发的其他游戏中再次见到您的身影。</p><p>希望国内MineCraft的未来更加美好。若您还在寻找一个适合您的服务器，可以尝试访问 <code>McLists.cn</code>。</p><p>祝大家生活愉快。</p><div align=right>    <div>Kar Network运营团队</div>    <div>        2020年7月17日    </div></div></blockquote></div></figure>]]></content:encoded>
      <category>往事</category>
      <category>MineCraft</category>
    </item>

    <item>
      <title>建 议 改 成：砖 业 抬 棺 人 写 殆 码</title>
      <link>https://www.bilibili.com/video/BV1gT4y137ow</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1gT4y137ow</guid>
      <pubDate>Sun, 26 Apr 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[服务器IP: Kar.RED 直播写的代码！]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1gT4y137ow">点击此处查看本视频 &gt;&gt;</a></p><p>服务器IP: Kar.RED<br>直播写的代码！</p>]]></content:encoded>
      <category>视频</category>
      <category>发现《Roundabout》</category>
      <category>游戏开发</category>
      <category>我的世界</category>
      <category>标准结局</category>
      <category>MINECRAFT</category>
      <category>黑人抬棺</category>
      <category>单机联机</category>
    </item>

    <item>
      <title>Kar.RED 宣传片 | 五年老服务器Kar，青春回归！</title>
      <link>https://www.bilibili.com/video/BV1e5411t7xb</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1e5411t7xb</guid>
      <pubDate>Tue, 21 Apr 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[Kar Network ，中国专业原创MC游戏社区。 青春五年，永不落幕。 服务器地址 Kar.RED (移动 yd.kar.red，联通lt.kar.red) 服务器QQ群 106660674 服务器官网 https://www.kar.red/ ------------------------------------------------------------- 制作者： Pinckus 素材来自服务器内玩家，均获得授权。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1e5411t7xb">点击此处查看本视频 &gt;&gt;</a></p><p>Kar Network ，中国专业原创MC游戏社区。<br>青春五年，永不落幕。  <br>服务器地址  Kar.RED (移动 yd.kar.red，联通lt.kar.red)<br>服务器QQ群  106660674<br>服务器官网 https://www.kar.red/ <br>-------------------------------------------------------------<br>制作者： Pinckus<br>素材来自服务器内玩家，均获得授权。</p>]]></content:encoded>
      <category>视频</category>
      <category>MC</category>
      <category>MINECRAFT</category>
      <category>我的世界</category>
      <category>单机</category>
      <category>游戏练级挑战</category>
    </item>

    <item>
      <title>Kar | 究极舒适 kb 3.0</title>
      <link>https://www.bilibili.com/video/BV1Mg4y1z7PZ</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1Mg4y1z7PZ</guid>
      <pubDate>Tue, 14 Apr 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[经过二次计算、润色与优化，kb 3.0正式推出！ 这..这也太舒服了吧？？？ 果然，多年开发，专业直击PVP领域，不愧是国内元老服务器。 服务器IP: Kar.red]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1Mg4y1z7PZ">点击此处查看本视频 &gt;&gt;</a></p><p>经过二次计算、润色与优化，kb 3.0正式推出！<br>这..这也太舒服了吧？？？<br>果然，多年开发，专业直击PVP领域，不愧是国内元老服务器。</p><p>服务器IP: Kar.red</p>]]></content:encoded>
      <category>视频</category>
      <category>我的世界</category>
      <category>PVP</category>
      <category>MINECRAFT</category>
      <category>单机联机</category>
      <category>kar</category>
    </item>

    <item>
      <title>对我的世界中PVP击退的研究报告</title>
      <link>https://pages.carm.cc/dev/knockback-study</link>
      <guid isPermaLink="true">https://pages.carm.cc/dev/knockback-study</guid>
      <pubDate>Fri, 03 Apr 2020 11:30:00 GMT</pubDate>
      <description><![CDATA[对 Minecraft PVP 击退机制的深入研究，通过代码分析和实验验证原版击退算法的工作原理与各参数的作用。]]></description>
      <content:encoded><![CDATA[<h1 id="“脚本小子”对MC击退的研究成果"><a href="#“脚本小子”对MC击退的研究成果" class="headerlink" title="“脚本小子”对MC击退的研究成果"></a>“脚本小子”对MC击退的研究成果</h1><p>该页面研究的是原版击退算法以及原版击退算法中的各值的作用。</p><p>通常我们在调整击退参数的时候，都是靠感觉去调的。Kar团队另辟蹊径，通过数据和代码的方式去理解和调整最合适的击退。为了贯彻我们<strong>决心</strong>做中国PVP服领头羊的理念，我们决定将我们的研究成果分享出去。</p><h2 id="对于代码的分析"><a href="#对于代码的分析" class="headerlink" title="对于代码的分析"></a>对于代码的分析</h2><h3 id="EntityLiving类"><a href="#EntityLiving类" class="headerlink" title="EntityLiving类"></a>EntityLiving类</h3><p>由于在nms中部分变量经过了混淆，所以只能通过猜测得出这些变量的意义。</p><p>在EntityLiving类中，玩家受到伤害时会触发<code>damageEntity</code>函数。</p><p><img src="images/EntityLiving1.png" alt="EntityLiving1.png" loading="lazy"></p><ul><li>d0为<strong>攻击者</strong>位置的X值减去<strong>受害者</strong>位置的X值，即为从<strong>受害者</strong>到<strong>攻击者</strong>的向量的X值。</li><li>d1初始值为<strong>攻击者</strong>位置的Z值减去<strong>受害者</strong>位置的X值，即为从<strong>受害者</strong>到<strong>攻击者</strong>的向量的Z值。</li></ul><p>我们把d0称为x，d1称为z，则</p><ul><li>若x²+z²&lt;0.0001，则将d1设为一个-1至1之间的随机值*(见下方)，再乘以0.01，同时将d0也进行一次这样的操作。</li><li>若x²+z²还是&lt;0.0001，则再进行一次，直到不满足这个条件为止。</li></ul><p>推测，这可能是两个玩家坐标一样或极度相近的时候，为防止产生0变量，生成一个随机的击退。为验证这个猜测，您可以tp一名玩家，此时您的坐标和这名玩家是一模一样的(其实会产生一点点差别)。接着打他一下，发现击退有时候不在您面前的方向，甚至有时候击退到身后去了。</p><p>*编个程统计一下这个随机数，进行100000000次(一亿次)模拟，发现其分布曲线是金字塔形。</p><p><img src="images/AlgorithmTest.png" alt="分布是折线.png" loading="lazy"></p><p>它看起来大概是这样：</p><p><img src="images/AlgorithmGraph.png" alt="折线.png" loading="lazy"></p><p>设该折线的方程为 y &#x3D; f(x), x∈(-1, 1)很明显，该随机变量X落在(-x, x),x∈(0, 1)的几率为</p><p><img src="http://latex.codecogs.com/png.latex?%5Cfrac%7B%5Cint_%7B-n%7D%5E%7Bn%7Df(x)dx%7D%7B%5Cint_%7B-1%7D%5E%7B1%7Df(x)dx%7D=2x-x%5E2" alt="几率Latex" loading="lazy"></p><p>函数a中</p><p><img src="images/EntityLiving2.png" alt="EntityLiving2.png" loading="lazy"></p><p>其中的d0和d1即为上方所提的x和z设一个变量f1为</p><p><img src="http://latex.codecogs.com/png.latex?f1%20=%20%5Csqrt%7Bd0%5E2%20&plus;%20d1%5E2%7D" alt="f1" loading="lazy"></p><p>即为该向量在水平面上投影的距离</p><ol><li>变量f2为0.4，我们把该值称为水平倍数，或者<code>Horizontal</code></li><li>将<code>motX</code>、<code>motY</code>、<code>motZ</code>分别除以2，我们把该值称为<code>Friction</code></li><li>接着将<code>motX</code> 减去 <code>x / f1 \* f2</code></li><li>将<code>motY</code> 加上 <code>f2</code></li><li>将<code>motZ</code> 减去 <code>z / f1 \* f2</code></li><li>如果<code>motY</code>大于0.4，则设为0.4(这就是原版击退100附魔也无法飞天只能击远的原因)。我们把该值称为<code>VerticalLimit</code>。</li></ol><p>以上即为当受害者受到伤害时的原始击退算法。详细讲解请看下方<strong>对原版击退算法的理解</strong>。</p><h3 id="EntityHuman类"><a href="#EntityHuman类" class="headerlink" title="EntityHuman类"></a>EntityHuman类</h3><p>接着在<strong>攻击者</strong>的算法中，再次对产生的击退做出修正。</p><p>在EntityHuman类中,<strong>攻击者</strong>攻击别人时，<strong>受害者</strong>会受到以下击退</p><p><img src="images/EntityHuman1.png" alt="EntityHuman1.png" loading="lazy"></p><p>其中，<code>i</code>为<strong>攻击者</strong>手上武器击退附魔的等级，若没有，则为0。如果<strong>攻击者</strong>正在疾跑，则<code>i</code>再加1。但是，在著名服务端mSpigot上，无论<strong>攻击者</strong>是否在疾跑，i的默认值都为1。</p><p>yaw是<strong>攻击者</strong>的朝向的yaw值<s>(欧拉角警告)</s>，是角度制，所以后面的乘以π除以180是转为弧度制。<code>entity.g(double motX, double motY, double motZ)</code>函数为</p><p><img src="images/Entity1.png" alt="Entity1.png" loading="lazy"></p><p>意思为，该实体目前的速度向量加上这三个值，再把成员<code>ai</code>改为<code>true</code>。回到上面的击退计算，其中MathHelper是一个优化的数学<s>工具人</s>工具类于是，该操作可写为</p><p><img src="http://latex.codecogs.com/png.latex?%5Cbegin%7Bcases%7D%0AmotX=motX+%5Csin%7B%5Cfrac%7Byaw*%5Cpi%7D%7B180%C2%B0%7D*0.5i%7D%5C%5C%0AmotY=motY+0.1%5C%5C%0AmotZ=motZ+%5Csin%7B%5Cfrac%7Byaw*%5Cpi%7D%7B180%C2%B0%7D*0.5i%7D%0A%5Cend%7Bcases%7D" alt="Algorithm-1(Latex)" loading="lazy"></p><p>完成这些操作后，<strong>攻击者</strong>的<code>motX</code>和<code>motZ</code>各自会乘以0.6。</p><div class="admonition warning"><p>是<strong>攻击者</strong>的<code>motX</code>和<code>motZ</code>会乘以0.6！<strong>受害者</strong>的击退已经算完了，不会乘以0.6缩短！</p></div><p>由于我们平时在竞技场模式中并不会使用带击退附魔的东西当主武器，所以我们不考虑击退附魔。因此，我们只考虑<code>i</code>为0或1的情况。详细讲解请看下方<strong>对原版击退算法的理解</strong>我们把上面的0.5i的0.5称为疾跑水平加成(<code>SprintHorizontalBoost[SHB]</code>)，motY加的0.1称为疾跑竖直加成(<code>SprintVerticalBoost[SVB]</code>)</p><h2 id="猜测与实验"><a href="#猜测与实验" class="headerlink" title="猜测与实验"></a>猜测与实验</h2><p>玩家的击退对于<strong>攻击者</strong>的朝向只跟<strong>攻击者</strong>的yaw值有关，也就是环顾四周时的方向、水平方向有关，和pitch，也就是上下朝向无关。无论<strong>攻击者</strong>从上往下还是从下往上攻击，击退的原始数值只跟<strong>攻击者</strong>的yaw值和<strong>攻击者</strong>与<strong>受害者</strong>在水平面上的投影的向量有关，接着才根据玩家是否疾跑、武器有无击退、是否对该数值进行进一步计算。<strong>但是</strong>，如果<strong>攻击者</strong>既不在疾跑手上又没有击退附魔，则击退和yaw也无关。</p><p>为了证明这一点，在采用原版击退的情况下，我做了个实验。</p><p>先将敌人的坐标和自己的坐标精确控制在整数，以便计算。在所有条件都不变的情况下，攻击<strong>受害者</strong>，计算击退的大小。</p><p><img src="images/In-Game-Test.png" alt="实验1.png" loading="lazy"></p><table><thead><tr><th align="center"></th><th align="center">第一次</th><th align="center">第二次</th><th align="center">第三次</th></tr></thead><tbody><tr><td align="center">击退前x值坐标</td><td align="center">-34</td><td align="center">-34</td><td align="center">-34</td></tr><tr><td align="center">击退后x值坐标</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td></tr></tbody></table><p>重复3次实验发现，只要条件不变，每次击退都是一样的。</p><p>接下来，只改变<strong>攻击者</strong>的<strong>pitch值</strong>，其他条件不变。</p><table><thead><tr><th align="center">pitch-&gt;</th><th align="center">-10</th><th align="center">0</th><th align="center">10</th><th align="center">20</th><th align="center">30</th><th align="center">40</th></tr></thead><tbody><tr><td align="center">击退前x值坐标</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td></tr><tr><td align="center">击退后x值坐标</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td></tr></tbody></table><p>使用不同的值重复多次实验，发现击退还是一样的。</p><p>那么我们只改变<strong>攻击者</strong>的<strong>yaw值</strong>，其他条件不变。</p><table><thead><tr><th align="center">yaw-&gt;</th><th align="center">-100</th><th align="center">-95</th><th align="center">-90</th><th align="center">-85</th><th align="center">-80</th></tr></thead><tbody><tr><td align="center">击退前x值坐标</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td></tr><tr><td align="center">击退后x值坐标</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td><td align="center">-33.198</td></tr></tbody></table><p>神奇的是，yaw值改变后，击退依然不变。</p><p>接着，我们给<strong>攻击者</strong>手上的剑加上击退属性，再进行测试。同样只改变<strong>攻击者</strong>的<strong>pitch值</strong>，发现确实跟<strong>攻击者</strong>的<strong>pitch值无关</strong>。</p><p>只改变<strong>攻击者</strong>的<strong>yaw值</strong>，得出以下结果：</p><table><thead><tr><th align="center">yaw-&gt;</th><th align="center">-100</th><th align="center">-95</th><th align="center">-90</th><th align="center">-85</th><th align="center">-80</th></tr></thead><tbody><tr><td align="center">击退前x值坐标</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td><td align="center">-35</td></tr><tr><td align="center">击退后x值坐标</td><td align="center">-31.034</td><td align="center">-31.009</td><td align="center">-31.001</td><td align="center">-31.009</td><td align="center">-31.034</td></tr><tr><td align="center">击退前z值坐标</td><td align="center">-49</td><td align="center">-49</td><td align="center">-49</td><td align="center">-49</td><td align="center">-49</td></tr><tr><td align="center">击退后z值坐标</td><td align="center">-49.371</td><td align="center">-49.182</td><td align="center">-49</td><td align="center">-48.818</td><td align="center">-48.629</td></tr></tbody></table><p>多次实验，发现每次结果都与上表相同。在<strong>攻击者</strong>手上附魔有击退效果时，击退与<strong>攻击者</strong>的<strong>yaw值有关</strong>。</p><p>我们多测试了如果是<strong>受害者yaw、pitch</strong>改变是否会影响击退，结果是<strong>受害者</strong>的朝向完全不影响击退，实验方式和上面差不多，篇幅原因，在此不列出实验详细过程。</p><p>测试<strong>攻击者</strong>疾跑对击退的影响，为了不改变坐标的值，写个插件欺骗服务器，<strong>攻击者</strong>在攻击时强制变成疾跑状态。测试结果是，疾跑状态攻击相当于手上拿着击退1的武器的效果。</p><p>因此我们可以推测，用击退1的武器疾跑着攻击对方，相当于行走状态或静止状态用击退2攻击对方一样。通过实验，证实了该推测。</p><p>我们再次推测，在击退与两个玩家的位置和<strong>攻击者</strong>的<strong>yaw值有关</strong>，且如果<strong>攻击者</strong>不在疾跑且手上武器没有击退附魔时，击退就只跟两名玩家的位置有关(除非去掉<code>if(i&gt;0)</code>代码块使<code>motY+0.1</code>强制生效，许多服务端都有这样做)。</p><p>用同样的方式，进行以下测试：</p><ul><li>测试<strong>攻击者</strong>与<strong>受害者</strong>所在位置存在高度差时，击退依然与上面一样，证明击退和高度差无关。</li><li>测试<strong>攻击者</strong>与<strong>受害者</strong>所在位置的距离不同时，击退依然和上面一样。</li><li>测试<strong>攻击者</strong>向<strong>受害者</strong>方向走动时攻击，击退依然和上面一样。</li><li>测试<strong>攻击者</strong>跳劈，发现无论是上升状态还是下降状态，击退依然和上面一样。</li></ul><p>当<strong>受害者</strong>在空中时受到攻击，一般击退距离会更远。我们通过编写插件，使玩家站在地上(坐标和上面一样)时欺骗服务器玩家在空中，结果发现击退依然和上面一样。推测因为在空中，在掉落到地面之前有更长的时间在空中滑行，造成的更远击退的感觉。由于方块有Friction属性，也就是当玩家落到地面时速度会迅速降低，而空气的<code>Friction</code>比方块的要低，所以玩家在空中能被击退得更远。</p><div class="admonition note"><p>这里所提到的方块<code>Friction</code>跟击退数值中的<code>Friction</code>不一样。</p></div><h2 id="各参数的作用"><a href="#各参数的作用" class="headerlink" title="各参数的作用"></a>各参数的作用</h2><p>回到参数上，如果不对原版击退的算法做出改变的话，仅修改算法中的几个参数，我们通常用感觉去判断击退的变化。通过了解上方原版击退的算法后，我们就可以知道那些参数的作用了。</p><p>原始击退是指在原始计算中得到的<code>motX</code>、<code>Y</code>、<code>Z</code>的值。目前市面上很多击退插件是在最终击退值上乘以某倍数。</p><h3 id="Friction"><a href="#Friction" class="headerlink" title="Friction"></a>Friction</h3><p>指在<strong>受害者</strong>受到攻击时，受到攻击前<strong>受害者</strong>的速度除以的值，一般大于1，这也是为什么它叫Friction(摩擦)的原因。如果该值等于1，那么此时玩家的速度将会加上击退赋予玩家的速度。如果小于1，则玩家的速度会变大再加上击退赋予玩家的速度。如果大于1，则玩家的速度会先缩短，再加上击退赋予玩家的速度。原版该值为2.0</p><h3 id="Horizontal"><a href="#Horizontal" class="headerlink" title="Horizontal"></a>Horizontal</h3><p>指<strong>原始</strong>击退参数的<code>motX</code>、<code>motZ</code>减去值的倍数，原版为0.4</p><h3 id="Vertical"><a href="#Vertical" class="headerlink" title="Vertical"></a>Vertical</h3><p>指<strong>原始</strong>击退参数的<code>motY</code>加上的值，原版为0.4</p><h3 id="SprintHorizontalBoost-SHB"><a href="#SprintHorizontalBoost-SHB" class="headerlink" title="SprintHorizontalBoost, SHB"></a>SprintHorizontalBoost, SHB</h3><p>指最终计算完毕的击退中的<code>motX</code>和<code>motZ</code>在<strong>攻击者</strong>水平面上所指位置(yaw值所对应位置)加上的，<strong>攻击者</strong>朝向的向量与x和z轴的投影距离，乘以击退附魔等级+若疾跑加一得到的倍数，再乘以的SHB，即原始数据再加上的击退距离的倍数，原版为0.5</p><h3 id="SprintVerticalBoost-SVB"><a href="#SprintVerticalBoost-SVB" class="headerlink" title="SprintVerticalBoost, SVB"></a>SprintVerticalBoost, SVB</h3><p>指最终计算完毕的击退中的<code>motY</code>再加上的值，原版为0.1</p><h3 id="VerticalLimit"><a href="#VerticalLimit" class="headerlink" title="VerticalLimit"></a>VerticalLimit</h3><p>原始击退计算中，最高达到的<code>motY</code>，若超过这个值，则设为这个值。原版为<code>0.4000000059604645</code></p><h2 id="对原版击退算法的理解-硬核慎入"><a href="#对原版击退算法的理解-硬核慎入" class="headerlink" title="对原版击退算法的理解(硬核慎入)"></a>对原版击退算法的理解(硬核慎入)</h2><p>注意，当玩家静止不动或者站在地面时，他的<code>motY</code>为<code>-0.0784</code>，虽然如此，玩家并没有往下掉，这可能是因为脚下有方块的时候就不往下掉，该值可能是为了制造重力。这也可以说明，为什么<code>Friction</code>调到很小(如0.01)的时候攻击玩家几乎无击退，因为这时<code>motY</code>除以<code>0.01</code>会变成<code>-7.84</code>，强力压在地上，导致地面对玩家的摩擦力较大，使玩家难以移动。如果玩家在水中踩到地面，该值为<code>-0.02</code>(也许是重力减去浮力？)</p><p>回到一开始，再次看到这个函数</p><p><img src="images/EntityLiving2.png" alt="EntityLiving2.png" loading="lazy"></p><p>首先<strong>受害者</strong>受到了<strong>攻击者</strong>的一次攻击。在计算击退之前，<strong>受害者</strong>目前的速度除以Friction以缩短目前的速度(见上方<code>Friction</code>)。通常该值只作用于玩家正在移动的过程中，比如疾跑或者正在被击退。如果玩家是静止的，那么<code>motX</code>和<code>motZ</code>都是0。如果玩家是在下落状态，则<code>motY</code>是负值，如果这个时候玩家受到攻击，<code>motY</code>会缩小，下落速度会变慢，这也是玩家在空中掉落的过程中受到攻击时会顿一下的原因。</p><p>我们知道：</p><ul><li>d0为<strong>攻击者</strong>位置的X值减去<strong>受害者</strong>位置的X值，即为从<strong>受害者</strong>到<strong>攻击者</strong>的向量的X值。</li><li>d1为<strong>攻击者</strong>位置的Z值减去<strong>受害者</strong>位置的X值，即为从<strong>受害者</strong>到<strong>攻击者</strong>的向量的Z值。</li><li>f1为从<strong>受害者</strong>到<strong>攻击者</strong>的向量在水平面投影的长度。</li></ul><p>因此将d0和d1都除以f1后，向量<code>(d0/f1, d1/f1)</code>的模为1。我们可以把一个长度为1的向量称为单位向量，它通常只为了表示方向。我们将把向量除以它的模的过程称为标准化向量，通常我们在只需要表示向量的方向，长度不重要，且要求该向量模为1的时候这样做。接着两个值再乘以<code>f2</code>，即乘以0.4，表示把向量乘以0.4，也就是说把向量的模改为 根号0.32 。此时，水平面上的击退原始数据就计算完毕了。</p><p>至于为什么<code>motX</code>和<code>motZ</code>是减去运算得出的数值，是因为上面算出来的向量是从<strong>受害者</strong>指向<strong>攻击者</strong>的向量，我们需要让<strong>受害者</strong>往后击退，而不是往<strong>攻击者</strong>飞过去，所以才是减去。</p><p>再看到竖直上的击退，直接是目前的<code>motY</code>加上f2。最后，如果<code>motY</code>超过一个限制值(每错，就是那个小数点后老长的)，就设为那个限制值。您可能会问，才加0.4可能会超过吗？确实会，因为上面说过，在<strong>受害者</strong>再一次受到伤害前，玩家是飞在空中的。如果是combo模式(即玩家受到攻击后的无敌时间很短)，<strong>受害者</strong>再一次受到攻击时<code>motY</code>还很大，除以Friction后可能依然很大，所以为防止玩家飞起来就设置了一个限制值。</p><p>再来看击退修正，</p><p><img src="images/EntityHuman1.png" alt="EntityHuman1.png" loading="lazy"></p><p><code>entity.g</code> 这个函数可以理解为原速度加上目标速度，如<code>entity.g(1, 2, 3)</code>就是<code>entity.motX += 1; entity.motY += 2; entity.motZ += 3; </code><code>yaw * π / 180</code>就是将玩家朝向的欧拉角yaw值(角度)转为弧度。在MC中，yaw的范围是<code>-180~179.9</code>。也就是说，这里的<code>-sin(yaw * π / 180)</code>和<code>cos(yaw * π / 180)</code>依然是生成一个模为1的矢量。为什么模为1？我们把<code>yaw * π / 180</code>设为θ，由sin²θ + cos²θ &#x3D; 1可知，该向量模为1。将该向量乘以<code>i</code> 再乘以<code>0.5</code>，即可得到水平上修正的向量。其中，<code>i</code>默认为<code>0</code>，如果玩家在疾跑状态则<code>+1</code>，如果玩家手上的物品有击退附魔，则再+击退附魔等级。最后，<code>motY</code>再加<code>0.1</code>。在原版中，如果<code>i&gt;0</code>，才会执行这段代码，如果<code>i=0</code>，则该代码不被执行，也就是说，<code>motY</code>也不会<code>+0.1</code>。在著名服务端mSpigot上，由于i默认为1，且疾跑不影响i的值，所以该代码永远会被执行。最后，把算到的击退交给事件触发器，由事件再次对向量进行更改(如果有的话)，最终将击退速度发送给客户端。</p><p>我们可以看到，在算击退原始数据时，击退的方向是以玩家间的位置关系决定的。而在修正的过程中，却由<strong>攻击者</strong>的yaw值决定。这是印证了上面的实验。所以，如果有个玩家开挂，拿着击退棒背对着打你(请使用不会转过头去打的祖宗级秒被ban外挂实验并关闭反作弊)，你并不会往后退反而往黑客的方向飞去，也是这个道理。</p><h2 id="如何抄袭猜测某服务器的击退"><a href="#如何抄袭猜测某服务器的击退" class="headerlink" title="如何抄袭猜测某服务器的击退"></a>如何<del>抄袭</del>猜测某服务器的击退</h2><p>如果该服务器的击退数值不是离散的(在相同情况下，击退总是相同，没有产生随机偏移)，且算法为MC原版算法，那么该服的击退数值将非常好猜。</p><p>如果击退数值是离散的，那么可以通过统计算出击退数值的分布，然后根据分布的情况模拟随机的数值。比如上方的<code>Math.random() - Math.random()</code>就是-1<del>1中呈金字塔形的分布，如果是<code>Math.random()-0.5</code>就是在&#96;-0.5</del>0.5<code>比较均匀的分布。除此之外，还有正态分布(</code>new Random().nextGaussian();&#96;)等常见分布方式。</p><p>我们需要的随机偏移一般不能太大，所以再乘以一个数如0.1缩小随机偏移量的范围。最后根据统计得出的分布规律猜测偏移的算法即可。</p><p>由于每次击退服务器只会给你发送一个速度矢量，不可能在击退的过程中持续修正你的速度(不然延迟高的话就会乱飘。速度给你造成的位移一般由客户端计算)。所以，我们只要得出在各种情况下每次服务器发来的击退赋予的速度即可反推击退数值。</p><blockquote><p>为了方便获取击退数值，我特意写了一个mod来辅助您获取某服务器的击退。版本: 1.8.9请使用最新版本forge运行以保证兼容性(我们使用的forge版本是forge1.8.9-11.15.1.2318)<s>当然，别对该mod抱有太大期望，比如按f3会挡住啥的</s>链接: <a href="https://pan.baidu.com/s/11BJ3Rtw-4YTDXECzIXWzAg">https://pan.baidu.com/s/11BJ3Rtw-4YTDXECzIXWzAg</a> 提取码: 77f3 </p></blockquote><p>这个mod看起来是这样的：</p><p><img src="images/mod-preview.png" alt="mod.png" loading="lazy"></p><p><s>什么？你被查端的时候因为这个太像挂端被封了？怪我咯</s></p><ul><li>Sprint: 你是否为疾跑状态</li><li>Sneak: 你是否为潜行状态</li><li>OnGround: 您是否站在地面<ul><li>站在地面，指是否落地并站在地面。</li><li>如果玩家被击飞、或者跳跃，该值为false。</li><li>不过，如果玩家是在飞行状态，即使他的坐标是贴合地面的，OnGround也一定为false。</li></ul></li><li>MotionX: 您的速度矢量的X值</li><li>MotionY: 您的速度矢量的Y值</li><li>MotionZ: 您的速度矢量的Z值</li><li>Target: 您正在攻击的玩家的名字</li><li>Distance: 您与您正在攻击的玩家的距离</li><li>ShadowDistance: 您与您正在攻击的玩家的连线在水平面上的投影的距离<ul><li>为什么需要水平面上的投影的距离？如果您有看上方原版击退的算法的话，您就会明白，击退的y值是另算的，玩家之间的位置关系只会决定x和z，y几乎不受玩家间位置影响。</li></ul></li><li>TargetSprint: 您正在攻击的玩家是否为疾跑状态</li><li>TargetSneak: 您正在攻击的玩家是否为潜行状态</li><li>TargetOnGround: 您正在攻击的玩家是否站在地面</li></ul><div class="admonition note"><p class="admonition-title">为什么不顺便列出对方的速度矢量？</p><p>这是因为对方速度是服务器决定的，服务器只要告诉您对方的位置就可以了。服务端没必要把跟您无关的数据一并发送给您，浪费服务器资源，所以对方的速度矢量无意义。</p><p>准备好后，您可以找一个小伙伴，一起装这个mod，然后进入您想测试击退的服务器。接着双方各开启录制~~(建议120帧)~~，模拟出各种情况，然后在视频剪辑软件中看每次攻击时赋予的速度即可。</p><p>一定要记住有Friction这个值，也就是每次击退的时候会先削减<strong>受害者</strong>的速度，再加上计算出来的击退，不然在combo的时候每次值都不一样别以为是random再作祟。</p></div><h3 id="算法区别"><a href="#算法区别" class="headerlink" title="算法区别"></a>算法区别</h3><p>你猜测kb的服务器的算法不一定是原版算法，所以当您暴力计算后没得出任何结果的话，您可以再分析总体数据的变化和产生数据对应的情况去猜测算法。即便算法不一定相同，但只要最终算出来的结果是一样的，您的击退和你在<del>抄</del>的服务器的击退就是一样的。</p><div class="admonition note"><p>syuu和kar都是使用了不同于原版的击退算法。</p></div><p>然后您可以写一个算法暴力算出误差小于0.0001的击退。</p><h3 id="如何防止自己服的kb被盗"><a href="#如何防止自己服的kb被盗" class="headerlink" title="如何防止自己服的kb被盗"></a>如何防止自己服的kb被盗</h3><p>使最终计算出来的kb离散化，加上一些微小的随机的偏移，且使用的随机算法也是随机的(不然容易被使用统计方法算出随机算法)。总之，尽量在不影响kb总体感觉的情况下提高猜测kb的难度。</p><hr><h2 id="关于本文档"><a href="#关于本文档" class="headerlink" title="关于本文档"></a>关于本文档</h2><p>文档的主要研究者与作者: LSeng</p><p>文档编写参与者: CarmJos</p>]]></content:encoded>
      <category>开发</category>
      <category>MineCraft</category>
      <category>经验总结</category>
    </item>

    <item>
      <title>国内原创新玩法生存服海暮礁！教程来啦~</title>
      <link>https://www.bilibili.com/video/BV1JE411N77z</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1JE411N77z</guid>
      <pubDate>Sat, 21 Mar 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[作为 真 · 自主开发 服务器，咱的东西有点小问题正常，视频中出现的所有问题都已经被修复。 服务器ip:sea.privatemc.cn 版本1.7-1.14 (最好使用1.8进入) 开发用了大概200个小时吧23333，熬了几夜写的。 感谢内测元老们的支持~ 服务器缺一位腐竹，我没时间管理呀233，如果这里有哪位dalao粉丝量大于5000，可以联系哦~]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1JE411N77z">点击此处查看本视频 &gt;&gt;</a></p><p>作为 真 · 自主开发 服务器，咱的东西有点小问题正常，视频中出现的所有问题都已经被修复。</p><p>服务器ip:sea.privatemc.cn 版本1.7-1.14 (最好使用1.8进入)<br>开发用了大概200个小时吧23333，熬了几夜写的。</p><p>感谢内测元老们的支持~<br>服务器缺一位腐竹，我没时间管理呀233，如果这里有哪位dalao粉丝量大于5000，可以联系哦~</p>]]></content:encoded>
      <category>视频</category>
      <category>MINECRAFT</category>
      <category>我的世界</category>
      <category>单机联机</category>
      <category>自主开发</category>
    </item>

    <item>
      <title>建议改成：给 你 脸 了 ？</title>
      <link>https://www.bilibili.com/video/BV1i7411f7F5</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1i7411f7F5</guid>
      <pubDate>Mon, 16 Mar 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[视频中所有使用外挂的都被VAC了。 我是Carm，和朋友三黑。 遇到对面暴力锁头，美其名曰“Skill！” 。 于是...我们这位大哥看不下去了。 “给你脸了？”]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1i7411f7F5">点击此处查看本视频 &gt;&gt;</a></p><p>视频中所有使用外挂的都被VAC了。</p><p>我是Carm，和朋友三黑。</p><p>遇到对面暴力锁头，美其名曰“Skill！” 。</p><p>于是...我们这位大哥看不下去了。</p><p>“给你脸了？”</p>]]></content:encoded>
      <category>视频</category>
      <category>电子竞技</category>
      <category>CS</category>
      <category>AK</category>
      <category>CSGO精彩集锦</category>
    </item>

    <item>
      <title>【英文书写】意外的发现了练习斜体的好工具!</title>
      <link>https://www.bilibili.com/video/BV1UJ411V7FU</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1UJ411V7FU</guid>
      <pubDate>Tue, 07 Jan 2020 00:00:00 GMT</pubDate>
      <description><![CDATA[自行百度搜索俄语练习本应该就有了叭。 我知道我写字不好看，请弹幕大神和评论大神手下留情，谢谢。 只是为了表达发现新物品的喜悦，见识短浅，手下留情，谢谢。 如果有帮助到你也欢迎给个三连丫。 傻傻的写了一大堆字，嘿嘿↑。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1UJ411V7FU">点击此处查看本视频 &gt;&gt;</a></p><p>自行百度搜索俄语练习本应该就有了叭。<br>我知道我写字不好看，请弹幕大神和评论大神手下留情，谢谢。</p><p>只是为了表达发现新物品的喜悦，见识短浅，手下留情，谢谢。</p><p>如果有帮助到你也欢迎给个三连丫。</p><p>傻傻的写了一大堆字，嘿嘿↑。</p>]]></content:encoded>
      <category>视频</category>
      <category>书法</category>
      <category>学习</category>
      <category>日常</category>
      <category>圆体</category>
      <category>练字</category>
    </item>

    <item>
      <title>【大合唱】 向往西藏 (纪念一二九运动合唱比赛) 江浦高级中学2019届合唱团</title>
      <link>https://www.bilibili.com/video/BV1iJ411F7U8</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1iJ411F7U8</guid>
      <pubDate>Sun, 06 Oct 2019 00:00:00 GMT</pubDate>
      <description><![CDATA[江浦高级中学2019届合唱团纪念一二九合唱比赛录制。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1iJ411F7U8">点击此处查看本视频 &gt;&gt;</a></p><p>江浦高级中学2019届合唱团纪念一二九合唱比赛录制。</p>]]></content:encoded>
      <category>视频</category>
      <category>音乐</category>
      <category>校园</category>
      <category>现场</category>
      <category>合唱比赛</category>
      <category>合唱团</category>
      <category>bilibili新星计划</category>
    </item>

    <item>
      <title>【墨瓷宣传片】六年磨一剑，自主开发的MC国内服！</title>
      <link>https://www.bilibili.com/video/BV1tJ41137Ci</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1tJ41137Ci</guid>
      <pubDate>Fri, 20 Sep 2019 00:00:00 GMT</pubDate>
      <description><![CDATA[感谢观看。 墨瓷目前由一群初中生、高中生与大学生维护，从使用他人插件到如今完全自主开发，已过六年。 服务器地址为 Mocimc.cn (MineCraft.net正版) 。 如果您是一位盗版玩家，也可以尝试使用“offline.mocimc.cn”进入。 请注意，我们有权拒绝为盗版玩家提供帮助，如果您有能力，请支持正版。 一切详情，尽在Wiki。 https://wiki.mocimc.cn/#!index.md --------------------------------------------------------------------------- 本宣传片由 小伊(IPlayForLover)、六神(668ms)制作，在此致谢。 --------------------------------------------------------------------------- 更多墨瓷相关视频： 《【墨瓷】 决心做中国MC服务器领头羊。请君莫辞。【60FPS】》 https://www.bilibili.com/video/av26958593 《玩自己写的UHCMEETUP是一种什么样的感觉？ 》 https://www.bilibili.com/video/av59986485 ---------------------------------------------------------------------------- 由Glorstal与EX涛制作的墨瓷首曲电音已发布至网易云音乐。 《墨路》 (Progressive House（Edit）/Future House（Edit）)]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1tJ41137Ci">点击此处查看本视频 &gt;&gt;</a></p><p>感谢观看。<br>墨瓷目前由一群初中生、高中生与大学生维护，从使用他人插件到如今完全自主开发，已过六年。<br>服务器地址为 Mocimc.cn (MineCraft.net正版) 。<br>如果您是一位盗版玩家，也可以尝试使用“offline.mocimc.cn”进入。<br>请注意，我们有权拒绝为盗版玩家提供帮助，如果您有能力，请支持正版。<br>一切详情，尽在Wiki。<br>https://wiki.mocimc.cn/#!index.md<br>---------------------------------------------------------------------------<br>本宣传片由 小伊(IPlayForLover)、六神(668ms)制作，在此致谢。<br>---------------------------------------------------------------------------<br>更多墨瓷相关视频：<br>《【墨瓷】 决心做中国MC服务器领头羊。请君莫辞。【60FPS】》<br>https://www.bilibili.com/video/av26958593<br>《玩自己写的UHCMEETUP是一种什么样的感觉？ 》<br>https://www.bilibili.com/video/av59986485<br>----------------------------------------------------------------------------<br>由Glorstal与EX涛制作的墨瓷首曲电音已发布至网易云音乐。<br>《墨路》 (Progressive House（Edit）/Future House（Edit）)</p>]]></content:encoded>
      <category>视频</category>
      <category>发现《Skyland》</category>
      <category>原创</category>
      <category>我的世界</category>
      <category>单机联机</category>
      <category>MineCraft</category>
      <category>自主开发</category>
      <category>墨瓷</category>
    </item>

    <item>
      <title>《1819(自由之路Remix)》JY 原创歌曲录制首发</title>
      <link>https://www.bilibili.com/video/BV1bt41147Pd</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1bt41147Pd</guid>
      <pubDate>Sat, 26 Jan 2019 00:00:00 GMT</pubDate>
      <description><![CDATA[作词： 杨子睿 Rap：杨子睿 混音后期： 卡姆姬]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1bt41147Pd">点击此处查看本视频 &gt;&gt;</a></p><p>作词： 杨子睿<br>Rap：杨子睿<br>混音后期： 卡姆姬</p>]]></content:encoded>
      <category>视频</category>
      <category>原创</category>
      <category>说唱</category>
      <category>帅哥</category>
      <category>高中</category>
    </item>

    <item>
      <title>如何轻松卸下小米手环3/4的米粒？</title>
      <link>https://www.bilibili.com/video/BV1jt411o7ue</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1jt411o7ue</guid>
      <pubDate>Sat, 20 Oct 2018 00:00:00 GMT</pubDate>
      <description><![CDATA[看到身边的人都是死扣才抠出来米粒，好难受哦。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1jt411o7ue">点击此处查看本视频 &gt;&gt;</a></p><p>看到身边的人都是死扣才抠出来米粒，好难受哦。</p>]]></content:encoded>
      <category>视频</category>
      <category>生活</category>
      <category>自制</category>
      <category>原创</category>
      <category>小技巧</category>
      <category>日常</category>
      <category>小米手环</category>
    </item>

    <item>
      <title>【墨瓷】 决心做中国MC服务器领头羊。请君莫辞。【60FPS】</title>
      <link>https://www.bilibili.com/video/BV1Ps411n7xF</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1Ps411n7xF</guid>
      <pubDate>Mon, 16 Jul 2018 00:00:00 GMT</pubDate>
      <description><![CDATA[感谢观看。墨瓷由私人组织制作，因此视频不含商业类型的推广。 服务器地址为 Mocimc.cn (MineCraft.net正版) 。 如果您是一位盗版玩家，也可以尝试使用“offline.mocimc.cn”进入。 请注意，我们有权拒绝为盗版玩家提供帮助，如果您有能力，请支持正版。 更多的消息，您可以访问我们的Wiki查看。 https://wiki.mocimc.cn/#!minecraft-network.md ---------------------------------------------------------------------------- 视频制作总时长(包含拍摄与预处理) 约40小时。 仿照Ultra服务器风格，当然，很明显就可以看出这个视频残了。 由 科莫、冬花、Gkz 、KUMR 录制，晨暮进行AE预处理和后期，KUMR善后。 本视频授权多位UP主发布。 ---------------------------------------------------------------------------- 更多墨瓷相关视频： 《不好意思，我们开服务器的真的可以为所欲为的。》 https://www.bilibili.com/video/av23029607 《拉坯。墨瓷正努力着。 (墨瓷片头) 》 https://www.bilibili.com/video/av22705492 ---------------------------------------------------------------------------- 由Glorstal与EX涛制作的墨瓷首曲电音已发布至网易云音乐。 《墨路》 (Progressive House（Edit）/Future House（Edit）)]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1Ps411n7xF">点击此处查看本视频 &gt;&gt;</a></p><p>感谢观看。墨瓷由私人组织制作，因此视频不含商业类型的推广。<br>服务器地址为  Mocimc.cn (MineCraft.net正版) 。<br>如果您是一位盗版玩家，也可以尝试使用“offline.mocimc.cn”进入。<br>请注意，我们有权拒绝为盗版玩家提供帮助，如果您有能力，请支持正版。<br>更多的消息，您可以访问我们的Wiki查看。<br>https://wiki.mocimc.cn/#!minecraft-network.md<br>----------------------------------------------------------------------------<br>视频制作总时长(包含拍摄与预处理) 约40小时。<br>仿照Ultra服务器风格，当然，很明显就可以看出这个视频残了。<br>由 科莫、冬花、Gkz 、KUMR 录制，晨暮进行AE预处理和后期，KUMR善后。<br>本视频授权多位UP主发布。<br>----------------------------------------------------------------------------<br>更多墨瓷相关视频：<br>《不好意思，我们开服务器的真的可以为所欲为的。》<br>https://www.bilibili.com/video/av23029607<br>《拉坯。墨瓷正努力着。 (墨瓷片头) 》<br>https://www.bilibili.com/video/av22705492<br>----------------------------------------------------------------------------<br>由Glorstal与EX涛制作的墨瓷首曲电音已发布至网易云音乐。<br>《墨路》 (Progressive House（Edit）/Future House（Edit）)</p>]]></content:encoded>
      <category>视频</category>
      <category>服务器</category>
      <category>中国</category>
      <category>我的世界</category>
      <category>网易</category>
      <category>Minecraft</category>
      <category>单机联机</category>
      <category>Kar</category>
      <category>墨瓷</category>
      <category>Soki</category>
      <category>Aries</category>
    </item>

    <item>
      <title>极度不适!!慎入!!!F网10刀翻6倍?! 我是托吧?!!</title>
      <link>https://www.bilibili.com/video/BV1Px411t7Br</link>
      <guid isPermaLink="true">https://www.bilibili.com/video/BV1Px411t7Br</guid>
      <pubDate>Tue, 29 Aug 2017 00:00:00 GMT</pubDate>
      <description><![CDATA[我开始怀疑我自己是托了。]]></description>
      <content:encoded><![CDATA[<p>此为视频内容，<a href="https://www.bilibili.com/video/BV1Px411t7Br">点击此处查看本视频 &gt;&gt;</a></p><p>我开始怀疑我自己是托了。</p>]]></content:encoded>
      <category>视频</category>
      <category>发现《Sex Apeal(Feat. Mike W.) (Max Farenthide Remix)》</category>
      <category>开箱</category>
      <category>CSGO</category>
      <category>F网</category>
      <category>极度不适</category>
      <category>FarmSkins</category>
    </item>
  </channel>
</rss>
