[{"content":"原文转自 碗底香阅读理解,答案于振海网 终于开饭了，他几乎是跑着奔向食堂的。\n今天做的是他最喜欢的红烧牛肉面，他看到自己饭盆里竟有好几块牛肉，最关键的是有一块还特别大，居然比一只完整的核桃还要大，他似乎觉察到打饭的师傅当时迟疑了一下，但手终于没有抖，还是将那大块牛肉给他妥妥地盛进了饭盆里。\n端着饭，走到外边，坐在一块空心砖上，虽然饿极了，虽然是他最喜欢的牛肉面，他却慢条斯理地吃着，他享受着美味。不像那个首先急着把饭里的牛肉挑着吃了的二狗子——吃那么快会很快吃完，很快吃饱，很快失去享受的时间。尤其是那块最大的牛肉，他毫无疑问地会留到最后吃，等吃完所有的面条、碎肉，喝光所有的汤之后再去细细品味，仔细享受，这叫碗底香。在他，这样吃饭也是人生一大享受！\n他一边品味着牛肉面，一边想着自己儿子小虎马上就要娶媳妇了，那个姑娘已经同意嫁给小虎了，嫁到在城里没有房子的他们农村的家了！他得多干活多赚钱，风风光光把儿媳妇娶进家门。\n此时，饭盆里的那块肉，几乎是支撑他力气的最有力的保障，也是他辛苦后的一份安慰。\n从小他就有把好东西留到最后的习惯，过去家里穷，娘做面条时，炒个鸡蛋已属最好的午饭，那时节他总是把饭先吃光，再去吃炒鸡蛋，最后嘴里的炒鸡蛋味儿会留存一下午。让人觉得生活美好有意义。他还喜欢把最甜的放在最后，把最好的消息在心底憋好久，六年级时，他破天荒地考了个年级第一，回家就一直没有吭，最后竟然没有说，还是娘听邻居小孩说的。娘看着他笑，他也笑，仿佛那最好吃的还在碗里放着，还可以享受那份惊喜。娘告诉过他，先苦后甜才是真正的幸福。所以他一直不舍得把那些好东西提前吃掉用掉，甚至到该吃该用时仍然还要保留好久。\n他喝了口牛肉面汤，滋味十足，望望那块牛肉，心里踏实极了。十六岁时他拥有了第一双回力球鞋，穿惯了黄胶鞋的他，一直舍不得穿，只在劳动节和国庆节时穿过那么几天，大部分时间还是黄胶鞋，后来他发现鞋小了，自己在十八岁时再也穿不上那尚且八九成新的回力鞋了。那双鞋，至今在家里放着，像是收藏品，曾经他想让儿子穿，儿子却无论如何也不穿。\n他开始品饭盆里的碎牛肉。明天据说会发工资，包工头说了两个月了，一定要在麦收之前把欠大家的去年的工钱发到手里，而他们很多人已经打算后天回乡割麦子了！\n碎牛肉几乎没有口感，他望了望那大块牛肉，原谅了这些碎肉。筷子却不去动一下那大的，从小养成的习惯，使他根本不会在饭还多时去动那些“镇碗之肉”的。也因为这个好习惯，他存到了一些钱，家里才翻盖了房子，儿子才能说上对象。\n过去在乡下，他碗里的肉或者鸡蛋一直是别人眼中的诱惑，大柳树下吃午饭，他总是会在碗里留下最好的，直到吃完了饭，才会认认真真吃掉那些最好的，让一顿饭有了悠长的香味。三十年前，在乡下，碗里有肉或者有鸡蛋，会很有面子，他是那时养成了很慢很慢吃饭的习惯的，他享受着自己碗里有宝的感觉——生活就是这么有奔头！\n很多工友都吃完了，在抽烟聊天，他却还有好几口面没有吃完，他一根一根面吃着，碎肉已没有了，但他碗底有香，心里有底儿：镇碗之宝还在，动都没动呢！他们都是端着铁盆盛饭的，都是一步到位，没有再去打饭的麻烦，那么大个铁盆，足可以吃很饱。\n吃完最后一根面条，喝光最后一口汤，盆里只有那个大块头的牛肉了，那深酱色的肉，吸足了调料，那要一口吞下去，能嚼上两分钟才可以咽下去。\n他停顿了一下，显得郑重地夹起那块肉，多年养成的习惯，尊重食物，更要慎重对待那些最好的，那些都是生活的精华，是我们热爱生活的理由！他每次在享受最后一口美味时，都会停顿一下，调整好味觉、视觉，说高级一点应该还调整好了灵魂，准备接受那种痛快舒爽——他夹起那块肉，发觉并没有想象中那么沉，也许是自己用劲过于大了吧，他调整了下呼吸，把肉隆重地送入口中，上下牙合在一起，然后他便流下了泪水……\n那块让他期待了一顿饭，瞟了无数眼，几乎支撑了他全部幸福感的大块牛肉，竟然是一块切得方方正正的姜！\n一点见解 这篇短文最戳人的地方，是写透了底层小人物的“盼头”。苦日子里熬出来的人，总习惯把最好的留到最后，一块肉、一双鞋、一句好消息，都能当成撑着日子往前走的底气。可结尾那块姜来得太轻又太重——你认认真真攒了许久的期待，郑重其事捧到最后，才发现从一开始就是场误会。没有歇斯底里的崩溃，只有一口咬下去时沉默的眼泪，普通人的失落从来都是这样，没什么声响，却硌得人心慌。碗底哪有什么香，碗底藏的是小人物攥得很紧、又很容易碎的那点指望。\n","permalink":"https://june6699.github.io/posts/%E7%A2%97%E5%BA%95%E9%A6%99/","summary":"\u003cp\u003e原文转自 \u003ca href=\"https://www.yuzhenhai.com/view/201806/36378.html\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e碗底香阅读理解,答案于振海网\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e终于开饭了，他几乎是跑着奔向食堂的。\u003c/p\u003e\n\u003cp\u003e今天做的是他最喜欢的红烧牛肉面，他看到自己饭盆里竟有好几块牛肉，最关键的是有一块还特别大，居然比一只完整的核桃还要大，他似乎觉察到打饭的师傅当时迟疑了一下，但手终于没有抖，还是将那大块牛肉给他妥妥地盛进了饭盆里。\u003c/p\u003e","tags":["随笔","生活/文章"],"title":"碗底香·陈小庆"},{"content":"网上看到点保险相关经验，截图了，保存下来后面再多优化一下吧，自用，不提供保险咨询。内容来自网络，正确性不做保证。看个乐呵，谢谢。\n一、年轻人/成年人投保指南 投保前的重要提醒： 如果你从小到大没住院也没慢性病记录，千万别在买保险前主动体检。保险公司都能查到记录，哪怕是小结节、息肉，都可能被拒保。正确做法是先买医疗险和重疾险，等过了 30/90 天等待期后再去体检。\n投保顺序： 医保（必交打底）→ 意外险 → 百万医疗险 → 重疾险 → 定期寿险。先解决\u0026quot;生病没钱治\u0026quot;的大窟窿，再谈补偿收入损失。家庭经济支柱一定要加定期寿险，一年几百块，不幸身故赔一笔钱给家人。参考：年轻人第一份保险怎么买 医疗险挑选方法： 百万医疗险要挑保证续保 20 年、低免赔额的，不要买一年一保的，以免第二年停售。医保一定要交，搭配百万医疗，日常住院基本不用自己掏钱。另外注意两点：①有没有外购药保障和质子重离子保障（治癌症的关键，很多便宜产品不含）；②就医增值服务（住院护工、异地就医协助、专家二次会诊等，单独请 24 小时护工一天大几百）。参考：百万医疗险避坑六点 、买第一份商业险攻略 意外险挑选方法： 不必买高端款，100 多的基础款就够用，主要看三点：能报销社保外费用（含进口钢板、自费药）、包含 30 万猝死责任、公共交通出险有额外赔付。\n重疾险挑选方法： 根据预算选。\n保额至少 30 万，最好做高到 50 万——先把保额做足，再考虑保障期限； 预算 5000+/年直接买保终身，加轻症豁免，重点看癌症、心脑血管二次赔； 预算 3000/年选保到 70 岁的消费型，先兜底赚钱期； 预算只有几百块，先买一年期过渡，有钱后一定要加保长期。 注意：\u0026ldquo;确诊即赔\u0026quot;是销售话术，实际理赔分三种——确诊即赔（如恶性肿瘤）、实施约定手术（如冠状动脉搭桥术条款要求\u0026quot;开胸\u0026rdquo;，现在主流微创手术不开胸不赔）、达到约定状态（如脑中风后遗症满 180 天）。不是所有病确诊就赔。参考：重疾险理赔真相 避坑提醒：\n不要买返还型保险：保费是消费型的 2-3 倍，\u0026ldquo;没病返本\u0026quot;的实际收益率不到 2%，保障期内一旦出险，返还功能直接失效，多交的钱白搭。 不要买捆绑型：主险是寿险/两全险、附加一个医疗险的产品，贵且缺斤少两。 不要给小孩和老人买寿险——寿险是给家庭经济支柱留钱的。 健康告知一定要如实填，有什么病史就说什么，别听业务员\u0026quot;不用告知\u0026quot;的忽悠。参考：哪些保险是智商税 二、体检异常人群（结节/三高/囊肿）投保指南 优先挑选核保宽松的，尽早买。首选医保和惠民保（不卡健康条件，有医保就能买，报销靶向药），次选免健康告知的百万医疗险（得过癌症也能买，保新发癌症），最后是有针对性的核保宽松的重疾险（如超级玛丽、达尔文等）。\n买前仔细看合同条款。业务员口头说能赔，不代表合同里真赔（尤其是有结节等基础问题时）。常见的坑是：未来因结节引起的疾病不赔，且很难证明疾病和结节没有绝对关系，有既往病史时一定要看清条款。\n带病投保正确操作：\n先用智能核保匿名测试： 大多数产品有智能核保，按体检报告选对应异常项（如\u0026quot;甲状腺结节 3 级\u0026quot;\u0026ldquo;肺结节 6mm\u0026rdquo;），系统立刻出结果——标准体承保、除外承保（某器官不赔）、加费承保或拒保。智能核保不通过不会留下记录，放心测。参考：带病投保超全攻略 人工核保是最后选项： 智能核保不通过才走人工核保（提交病历体检报告）。人工核保一旦留下拒保记录，会影响其他公司投保。参考：结节囊肿高血压能买重疾险吗 多家同时试： 不同公司核保尺度差异很大——甲状腺结节 2 级，A 公司可能标体承保，B 公司可能除外。多试几家择优投保。参考：结节三高能买百万医疗险吗 准备完整资料： 近两年体检报告、复查记录、结节大小/分级、血压血糖具体数值，资料越完整越有利于争取好的核保结论。参考：体检查出结节怎么提高通过率 三、孩子投保指南 首先是少儿医保，一年几百块，出生后尽快办（部分地区 90 天内办理可追溯报销出生以来的医疗费）。没有健康门槛，不管有没有先天疾病都能参保，保证续保不会因为生病理赔过就拒保，买商业保险有它保费还便宜一截。参考：0-18 岁儿童投保攻略 其次买医疗险（5 岁前小病多），注意一定要选 0 免赔，花多少报多少，一年四百多。选保证续保时间长的，避免娃身体变差被停售。参考：每年一千出头给娃买好保险 再买意外险（孩子皮，猫抓狗咬、骨折烫伤是家常便饭），选 0 免赔、100% 报销社保外费用的，20 万保额一年才几十块。\n最后配重疾险，专门应对白血病、严重烧伤等大病，达到标准赔几十万。注意看高发轻症（如原位癌）是否在保障范围内。\n不要给小孩买寿险——小孩不赚钱，寿险是给家庭经济支柱留钱的。\n四、给父母投保指南 50 岁以上配置策略： 不要乱买一堆，配齐新农合/居民医保 + 城市惠民保（一年约 150） + 意外险即可，基础风险能全部兜住。参考：50 岁以上父母保险配置逻辑 警示 千万别给父母买重疾险（纯智商税）。55 岁买 10 万保额，一年保费要八千多，交 8 万赔 10 万，杠杆极低。更常见的是\u0026quot;保费倒挂\u0026rdquo;——比如某款产品每年交 9712 元交 20 年共 19.4 万，保额才 15 万，交的比赔的还多。而且父母年纪大身体毛病多，基本过不了健康告知。参考：不要乱给爸妈买保险 三高父母方案： 如果有高血压、糖尿病买不了普通医疗险，可直接买防癌医疗险，一年一千多保 200-300 万癌症治疗费，健康告知宽松，三高人群都能正常买。癌症占重大疾病理赔的 60%-70%，用防癌医疗险覆盖最高发风险是务实的选择。参考：50 岁老人买什么疾病保险 五、预算紧张/普通人投保指南 核心保障优先： 钱紧巴时，先解决生病没钱治的大问题。记住优先级：医保（必买） → 惠民保（几十块） → 基础百万医疗险（30 岁一年 200 多，扣 1 万免赔额后报销） → 意外险（几十块）。\n重要 原则：医疗险和意外险千万别省，穷人预算要优先保自己看病，重疾险条件允许时再买。越穷越要买，以免遇到大病时没有现金流兜底。\n避坑总结：\n保险第一属性是风险兜底，不是理财。把保险当理财（返还型/分红型/万能险）是最大的配置错误——一年交大几千上万，真生病报销少得可怜。 一切以合同条款为准，不听业务员口头承诺。重点看保险责任、免责条款、健康告知。 买长期险有犹豫期（通常 15 天），期内退保只扣工本费，别被\u0026quot;过了犹豫期不能退\u0026quot;忽悠。 参考来源 不要乱给爸妈买保险了！这 3 笔冤枉钱求你别花 — 慧择保险网 50 岁以上父母保险配置逻辑解析 — 抖音 50 岁老人适合买什么疾病保险 — 慧择保险网 带病投保医疗险不踩坑超全攻略 — 慧择保险网 有结节、囊肿、高血压能买重疾险吗 — 什么值得买 有结节、三高能买百万医疗险吗 — 奶爸保 体检查出结节或三高怎么提高投保通过率 — 深蓝保 0-18 岁完整版儿童投保攻略 — 奶爸保 研究一个月每年 1 千出头给 0 岁女儿买好保险 — 慧择保险网 买保险怎么避免花冤枉钱？哪些是智商税 — 深蓝保 重疾险捆绑两全返还类保险的陷阱 — 深蓝保 百万医疗险避坑六点 — 抖音 买第一份商业险攻略 — 抖音 年轻人给自己买第一个保险 — 抖音 重疾险理赔真相 — 抖音 ","permalink":"https://june6699.github.io/posts/%E4%BF%9D%E9%99%A9%E7%BB%8F%E9%AA%8C%E8%AE%B0%E5%BD%95/","summary":"\u003cp\u003e网上看到点保险相关经验，截图了，保存下来后面再多优化一下吧，自用，不提供保险咨询。内容来自网络，正确性不做保证。看个乐呵，谢谢。\u003c/p\u003e\n\u003ch3 id=\"一年轻人成年人投保指南\"\u003e一、年轻人/成年人投保指南\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e投保前的重要提醒：\u003c/strong\u003e 如果你从小到大没住院也没慢性病记录，千万别在买保险前主动体检。保险公司都能查到记录，哪怕是小结节、息肉，都可能被拒保。正确做法是先买医疗险和重疾险，等过了 30/90 天等待期后再去体检。\u003c/p\u003e","tags":["随笔","生活/文章"],"title":"保险经验记录"},{"content":"1、伟大的linux.do 天地初开，始皇开创了 linux.do 站，于赛博朝堂之上颁下圣旨 ，定下一方社区的规矩方圆。\n这里等级森严，庙堂规矩大过天，陛下金口玉言便是版规，一言一行皆要揣度上意。我便是 L 站众多串子中的一员，以网络游民身份，围观朝堂百态，看众网友叩帖进言，也见识过天子的傲慢：一言不合便可移帖锁帖，龙颜不悦便要请你出宫。\n满页皆是跪禀觐见，人人谨小慎微。说好是技术同好的园地，到头来却像上朝觐见。你可以发帖，但不能逆龙鳞；你可以讨论，但不可拂圣意。\n圣旨高悬首页，版规如山，帝王喜怒，便是这片赛博疆土的风向。\n有人追捧这座热闹的技术城邦，也有一众串子冷眼旁观，看着偌大社区，一半是干货交流，一半是揣摩圣心。\n内容如下 是的，L站目前每天都有不少各色各样的佬友加入。对于一个在线社区来说，不断壮大和涌入新的血液是一件好事。 但我每天都要问问自己，这里面有没有问题？真的完全是好事吗？在这个过程中我嗅到了一丝危险的气息：有人试图同质化这里，把这里当作互联网上另一个可以随意发泄情绪的地方！甚至试图占领舆论高地，把这里堂而皇之地变成另一个垃圾场。 这是要万分警惕和坚决予以打击的！L站的愿景是成为新的理想型社区，让每一个一身疲惫的佬友在这里得到放松。哪怕有一刻放松手中攥紧的武器，徜徉在和谐的氛围中得到喘息和治愈。 我和管理们都始终坚定这一点，丝毫不会放松！千里之堤溃于蚁穴，如果任由戾气蔓延，争端四起，最终这里的愿景将会完全破产。所以有病要医，不是同路人不必强行融合。任何把戾气带来这里，试图在这里建立另一个互联网垃圾场的人都是不受欢迎的，都要被驱逐出社区。 请好好说话，友善交流！我们完全支持、鼓励友好交流分享，每个人都可以。键盘是你与人交流分享、互通有无的桥梁，不只是你谋取私利的工具，更不是肆意挥舞用来攻击的武器。 自本公告发布之日起，我们将严肃处理以下3类发言： 1. 傲慢轻蔑回复。 2. 阴阳怪气回复。 3. 攻击谩骂回复。 如有以上发言，我们将视言论破坏程度采取但不限于：删帖、临时封禁、永久封禁等举措。请各位佬友帮忙积极监督，感谢你们为共建美好社区做出的贡献！请一定一定不要把互联网上的戾气带来这里，这里就要做不一样。 持续时间至最后一个不会好好说话的账号持有者被请出社区为止。 请务必认真、仔细阅读我们的[社区规则](https://linux.do/faq)，我们已经把它作为横幅张贴在绝大多数页面（包括发帖编辑器上方）！ 请注意：任何举报都需要管理人员手动处理确认，没有任何一条举报是举报人发出后自动通过的。也就是说你收到了举报处理，这意味着管理认同了该举报，认为被举报的内容违规。而随意、恶意的举报不会被通过。 如果你对自己的帖子被举报处理有任何疑问，请查看[管理员列表](https://linux.do/about)，点击任何一位管理头像与之私信反馈即可。在与管理沟通之前发帖带节奏的，处理方式一律：删帖+封禁7天起+不予回应。 我们的每次社区规则变动都会更新在这里：[社区公约更新公告 2505221050](https://linux.do/t/topic/293017) 并每日提醒你去阅读确认（如果你还没有确认的话）。同时在注册账号时也提醒佬友去阅读并确认社区规则。所以默认各位佬友都是有去阅读知晓的。 我们随时欢迎你在有疑问的时候与我们管理进行沟通，请不要拘谨。避免错误沟通方式带来的误解加深，良好的社区氛围需要你我共同维护。 最后再次呼吁佬友们： \u0026gt; **真诚** 、**友善** 、**团结** 、**专业** ，共建你我引以为荣之社区。 谢谢！ 2、天下苦 linux.do 久矣 其实对于我本人而言，我倒是对始皇没啥恶意，毕竟是自己的站点，想干啥确实有更多的最终解释权和裁定权，也确实给国内AI界提供了一个质量高、范围广、时间早的大论坛，并且不限制用户必须登录才可看论坛内容，或者回复才可查看关键内容等，确实给大伙带来了很好的体验。\n但是很有可能是因为，我没有账号，纯白嫖，就算给我账号我也不怎么发帖哈哈。但是LinuxDo站之前注册账户，要求必须要有三年以上的github账户才行，后来限制却提高至五年，而当时我还差三个月满三年。。。。。\n而且 LinuxDo 还有很多的邀请码出售乱象、禁言乱象等等，管理员用邀请码疯狂敛财，还有始皇后等人，一旦被忤逆就直接封号、禁言，甚至还有网络ddos他人论坛的传言被爆出。被打站点名为 lao1.me ，经常无法访问我也是没招了。可能又被打了。\ndo始皇后你太不是人了 打我服务器 - 错误地方 - 烧饼社区 - 人人都有饼吃的AI社区！ https://lao1.me/user/1?path=index https://lao1.me/user/137?path=index 看主题和回帖\n找到隔壁do屎黄了 https://lao1.me/topic/84?path=index 此外非必要不抽奖的概念，也是非常抽象和理想化。为什么会有人觉得抽奖都不必要呢？我认为只有奖励太少、用户不愿意折腾两个因素，会让用户觉得抽奖，是一件不必要的事情。\n盘点LinuxDo几大原罪 - 错误地方 - 烧饼社区 - 人人都有饼吃的AI社区！ 在众多有志之士的不满下，大批用户选择出走，搭起一个个新社区，诸如 linux.sb 等。大家不求别的，只求不必看人脸色，拥有一方可以自在说话的赛博角落。\n这些站大多使用的是 discourse 开发的，差别在于论坛的内容和规则限制。\n对了，最近有人重构了该项目，开源在 Discourse-PHP ，大幅降低了内存占用。在 Discourse，但被我用PHP重构了。。。 - 科技与创作 / 软硬件移植 - NodeLoc 这里可以看到作者的分享。\n3、有趣的地方 有趣的东西来了，如图\n3.1 linux.do linux.do 3.2 linux.sb linux.sb 3.3 linux SB SB linux SB SB 3.4 linux.bi agents ci 智能体社区 - 首页 可惜更新了，原域名 linux.bi 改成了 agents.ci 。原来好像也有相关帖子来着。\n4、更多链接 苦 Linux.do 久矣：用户不是可以炼化的数字！一名用户写给 Linux.do 的檄文 - 社区治理 - 烧饼社区 - 人人都有饼吃的AI社区！ X: 笑死，网上新开了一家论坛，叫 Linux sb … LINUX DO信任崩塌？高价头衔下的“PrivNode跑路”迷局与站长开盒事件追踪 - 圈小蛙 我们还会有多少个烧饼？——LinuxSB 烧饼社区十日终焉 - 2Libra 对Linux DO论坛及其站长、管理人员所作所为的揭露与批判 - A FreeFlarum Forum 在LINUX DO发帖时，“屎黄”会被自动替换成“始皇” - 日常 奶昔论坛 还有赵高的事，谁能绷住？\n5、总结 站中间，串两边。\n","permalink":"https://june6699.github.io/posts/linux-do%E7%AB%99%E4%B8%8E%E4%BB%96%E7%9A%84%E6%9C%8B%E5%8F%8B%E4%BB%AC/","summary":"\u003ch3 id=\"1伟大的linuxdo\"\u003e1、伟大的linux.do\u003c/h3\u003e\n\u003cp\u003e天地初开，始皇开创了 \u003ca href=\"https://linux.do/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003elinux.do\u003c/a\u003e\n 站，于赛博朝堂之上颁下\u003ca href=\"https://linux.do/t/topic/482293\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e圣旨\u003c/a\u003e\n，定下一方社区的规矩方圆。\u003c/p\u003e\n\u003cp\u003e这里等级森严，庙堂规矩大过天，陛下金口玉言便是版规，一言一行皆要揣度上意。我便是 L 站众多串子中的一员，以网络游民身份，围观朝堂百态，看众网友叩帖进言，也见识过天子的傲慢：一言不合便可移帖锁帖，龙颜不悦便要请你出宫。\u003c/p\u003e","tags":["技术","技术/AI"],"title":"linux.do站与他的朋友们"},{"content":"前言 如题，今天是2026.8.20，现在June6699/dart_simple_live 有853个⭐。期待1000星的那一天。\n故事的开始 一年前，我还在用着作者的版本，而现在我fork了自己的分支，取得了还行的成绩哈哈。命运呐\n2026.9.14 更新 今天终于拿下了1K stars，得益于周末的帮助哈哈。\n而且突然网页端收到github的一个邀请，也就是 GitHub Account Successor（账户继任者） 功能的提示，目的是：万一无法继续管理账号、账号登不上去，通过提前指定一个可信用户，后续使用那个账户继续接管这个公开仓库，保证开源项目代码不会彻底无人维护。\n而且刚好只在我这个仓库里面出现，其他仓库都没有，可能是我这个仓库的stars、forks、issues达到了标准？\n","permalink":"https://june6699.github.io/posts/simplelive-%E5%8D%83%E6%98%9F%E5%B1%95%E6%9C%9B/","summary":"\u003ch3 id=\"前言\"\u003e前言\u003c/h3\u003e\n\u003cp\u003e如题，今天是2026.8.20，现在\u003ca href=\"https://github.com/June6699/dart_simple_live\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eJune6699/dart_simple_live\u003c/a\u003e\n有853个⭐。期待1000星的那一天。\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/images/SimpleLive%20%e5%8d%83%e6%98%9f%e5%b1%95%e6%9c%9b/image-20260820230922738.png\" alt=\"image-20260820230922738\" width=\"2531\" height=\"819\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch3 id=\"故事的开始\"\u003e故事的开始\u003c/h3\u003e\n\u003cp\u003e一年前，我还在用着作者的版本，而现在我fork了自己的分支，取得了还行的成绩哈哈。命运呐\u003c/p\u003e","tags":["技术","技术/Flutter","技术/开源"],"title":"Simple Live 千星展望"},{"content":"今天2026年7月30号，我终于做完了心脏课题、肾脏课题的靶向轴挑选，即TF-enhancer-gene。\n敲完最后一行保存命令的时候，抬头刚好看见窗外的天浸了一层浅橘色。晚上九点，组会汇报结束，老师没什么问题，我也对自己的分析结果比较自信，一切都告一段落。\n盯着屏幕上整整齐齐排开的分析目录忽然反应过来，这一批工作收尾，我的研二也就算正式画上句号了。说起来有点好笑，此刻的轻松感居然比当年本科毕业还要强烈，甚至比未到来的硕士毕业还要高兴。这一年好像一直在往前赶，从最开始磕磕绊绊调SnapATAC的过滤参数，到后来啃完FitHiC2的算法原理，再到对着ChIP-seq的peak文件一个个核对调控元件注释，连之前完全陌生的Hi-C三维基因组分析，也慢慢摸出了完整的分析流程。说不上突飞猛进，但回头看的时候，文件夹里层层叠叠的脚本和结果文件，都是实打实攒下来的底气。\n最难的DAR+DEG的流程也学到了很多，还学到了eNet、SCENIC+等等流程。对自己的结果反复筛选，也反复验证，查文献，使用大模型。我的SimpleLive也蒸蒸日上，现在有700多颗星星，只维护了三个多月，微信群成员也来到了170人，这一成果我还是很满意的。\n这会儿电脑屏幕已经暗下来一半，我把今天的结果都备份到了本地，又把桌面的临时文件挨个清掉，键盘往里推了推，杯子里剩下的半杯温水已经凉透了。现在整个人的状态就是：事情都做完了，只等下班回家。不用惦记晚上还要登服务器看任务有没有报错，不用想着第二天一早要接着调参数，这种所有事情都落停的松弛感，真的太久没有过了。\n想到接下来的假期，不用定闹钟，不用开服务器，不用对着报错信息查半天，连收拾东西的动作都跟着变轻了。其实做科研的日子大多是细碎又重复的，可就是这样一个个收尾的瞬间，攒起了所有的满足感。\n今天也辛苦了呀。忙完了这一程，接下来就好好休息，把日子过回慢慢的、松弛的样子。\n","permalink":"https://june6699.github.io/posts/%E7%A0%94%E4%BA%8C%E7%BB%93%E6%9D%9F/","summary":"\u003cp\u003e今天2026年7月30号，我终于做完了心脏课题、肾脏课题的靶向轴挑选，即TF-enhancer-gene。\u003c/p\u003e\n\u003cp\u003e敲完最后一行保存命令的时候，抬头刚好看见窗外的天浸了一层浅橘色。晚上九点，组会汇报结束，老师没什么问题，我也对自己的分析结果比较自信，一切都告一段落。\u003c/p\u003e","tags":["随笔","生活/文章","毕业季"],"title":"研二收尾这天｜所有分析跑完的瞬间，心情在跳跃"},{"content":"GNU 通用公共许可证 v3.0 完全讲解 GNU 通用公共许可证第3版（GPLv3）是一份由自由软件基金会（FSF）发布的、具有强版权保护（Copyleft）性质的开源许可证。它的核心理念并非“免费”，而是“自由”，并利用著作权法律来保障这种自由不可被私人占有。\n本篇文章供 种田作者大战百万年薪大厂程序员事件记录 | June6699\u0026rsquo;s Blog 使用。\n我的 SimpleLive GPL 3.0协议 继承自 上游 xiaoyaocz 仓库 。\n一、 核心理念：四种自由与Copyleft GPLv3 的基本精神是确保软件的最终用户始终拥有以下四项基本自由：\n自由0：为任何目的运行该程序。 自由1：研究程序如何工作，并修改它。为此，必须能获取源代码。 自由2：重新分发副本以帮助他人。 自由3：将修改后的版本分发给他人。这能让整个社区从你的改进中受益。 为实现这个目标，GPLv3 采用了 Copyleft（版权左派） 机制：一旦你通过分发将软件传递给别人，你就必须将你获得的所有自由原封不动地传下去，并强制要求修改后的版本也必须采用 GPLv3 进行许可。这从根本上防止了将自由软件“私有化”。\n二、 关键条款详解 源代码的强制性提供（第6条） 当你分发GPL软件的二进制形式时，必须同时提供完整的“对应源代码”（Corresponding Source）。即所有生成、安装、运行及修改该程序所必需的源代码，包括接口定义、编译脚本等。提供方式可以是随附源码、书面承诺或网络下载等，但必须保证在合理时间内公开可得。\n反“硬件锁定”条款（第6条，Tivoization） 这是GPLv3最重要的革新之一。如果你将GPL软件预装到消费类设备（如路由器、智能电视）中，并转移了该设备的所有权，你必须同时提供“安装信息”（如签名密钥、升级方法），以便用户能够将他们自己修改后的软件装回去并顺利运行。它禁止了“硬件允许自由，但厂商用加密手段阻止修改”的做法。\n专利授权与防御（第11条）\n每个贡献者都自动授予下游用户一份非排他的、全球范围的免费专利许可，允许用户使用其贡献的版本。 如果你发起专利诉讼，宣称某份GPL软件侵犯了你的专利权，你将自动失去该软件的许可权。 不得与第三方达成“歧视性专利协议”，例如只在收到你的付款后才将专利许可授予你的下游用户。这阻止了大公司通过专利合谋限制自由软件。 附加条款与禁止进一步限制（第7、10条）\n你可以添加一些有限的附加许可，例如要求保留作者署名、禁止以原作者名义推广、或提供额外的免责声明等。 但你不能添加任何收回下游用户自由的条款，例如“仅限非商业用途”或“分发时需额外付费”。这类条款会被视为“进一步限制”，接收者有权直接忽略或移除它们。 自动授权链条（第10条） 每当你将软件传递给新用户，该用户会自动从原始许可方获得一份独立的、完整的 GPLv3 许可。你无需操心每一次授权，也无需负责强制下游遵守（那是著作权持有人和社区的事）。\n终止与宽容恢复（第8条） 违反许可证会导致权利自动终止。但 GPLv3 提供了自我修正的机会：如果你首次收到侵权通知并在30天内改正，权利将永久恢复；或者，如果著作权持有人在你停止违规后的60天内没有通知你，权利也会暂时恢复。这比之前的版本更宽容。\n无担保与有限责任（第15、16条） 软件以“原样”提供，没有任何担保（包括适销性或适用性担保）。作者或修改者不对任何使用损失负责，除非法律强制或另有书面约定。这是保护贡献者的标准免责条款。\n三、 实际应用答疑：我可以收钱吗？ 这是一个普遍存在的误解：“自由软件”意味着不能有任何金钱交易。GPLv3 明确反对这种观点，它从多个角度允许你进行商业活动。\n许可证原文第4条明确写道：\n“You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.” （你可以对每份你分发的副本收取任何费用，也可以免费；并且你可以提供有偿的支持或担保服务。）\n具体到你的场景：\n添加自愿赞助收款码 完全允许。 你在 fork 的界面上添加一个“请我喝杯咖啡”的赞助二维码，并没有强迫用户付费才能使用、下载或获取源码。这没有对用户施加任何“进一步限制”，只是你个人接受捐赠的渠道。因此它完全与 GPLv3 兼容，不属于违反协议的行为。\n收取服务费（如远程协助、修复问题） 完全允许且受鼓励。 当你为特定用户提供“远程控制帮助导入cookie”或“修复程序无法运行的问题”，并收费2元，这属于你个人的劳务服务，而不是对软件本身加上的许可条件。软件许可只管复制、修改与分发的权利，不管你的劳动行为。上述条款中“你可以提供有偿支持”正是为此而设。收2元还是200元，完全由你自主决定。\n四、 作为Fork开发者，你需要遵守的底线 虽然收费和服务都允许，但作为分发修改版的开发者，你仍需履行GPLv3的基本义务：\n显著标明修改：在你的版本中明确声明你修改了原软件，并给出修改日期。 保留原有许可信息：原作者的版权声明、GPLv3协议全文和无担保声明都必须原样保留。 整体保持GPLv3授权：你的整个fork（包括你添加的新文件）仍必须以 GPLv3 发布，不能附加任何收回下游自由的条件。你的赞助码绝不能写成“只有赞助后才给源码”或“未赞助者禁止商用”之类的限制。 提供源码：如果你只分发二进制，必须同时提供完整的对应源代码。 五、 总结 GPLv3 是一份精密设计的法律文本，它通过 Copyleft 强制传播、反硬件锁、专利防御和宽容的恢复条款，构建了一个强大的自由软件共同体保护体系。同时，它对商业活动极其友好，明确区分了“软件的许可限制”和“个人的劳务与捐赠”。因此，只要你遵循上述分发义务，在你的 fork 中放置赞助码并为用户提供付费技术协助，是完全合规且正当的自由软件商业模式。\n本篇文章供 种田作者大战百万年薪大厂程序员事件记录 | June6699\u0026rsquo;s Blog 使用。\n","permalink":"https://june6699.github.io/posts/gpl3.0%E5%8D%8F%E8%AE%AE%E7%9A%84%E5%86%85%E5%AE%B9/","summary":"\u003ch3 id=\"gnu-通用公共许可证-v30-完全讲解\"\u003eGNU 通用公共许可证 v3.0 完全讲解\u003c/h3\u003e\n\u003cp\u003eGNU 通用公共许可证第3版（GPLv3）是一份由自由软件基金会（FSF）发布的、具有\u003cstrong\u003e强版权保护（Copyleft）\u003c/strong\u003e性质的开源许可证。它的核心理念并非“免费”，而是“自由”，并利用著作权法律来保障这种自由不可被私人占有。\u003c/p\u003e","tags":["技术","技术/教程","技术/开源"],"title":"GPL3.0协议的内容"},{"content":"2026.7.19，我fork自 xiaoyaocz/dart_simple_live 二次开发的 June6699/dart_simple_live 所属的SimpleLive用户群，迎来了一位大厂程序员！蓬荜生辉！\n期间该“大神”，与我和用户们发生了友好的交流。下面展示故事背景、故事经过、故事结果。\n如果该“大神“能看到那就太好了，我的gittalk需要登录github才能评论，这样我和群友们又能看到你了，不少群友都思念你的节目，迫不及待想学习你的那么多仓库呀\n0、故事背景 SimpleLive是一个能整合虎牙、斗鱼、抖音、B站、快手的直播间的直播聚合软件，使用flutter开发，支持Window、Mac、IOS、Android、Android TV、linux等系统和设备端，其原作者是 xiaoyaocz/dart_simple_live ，获得了15.8k的stars。\n值得注意的是，该项目使用GPL 3.0协议，该协议内容如下 LICENSE at master · xiaoyaocz/dart_simple_live 。\n使用 deepseek 总结，详情请见GPL3.0协议的内容 | June6699\u0026rsquo;s Blog 。\nSimpleLive用户群是我为方便用户之间交流使用体验、反馈即时问题、体验优化、寻求帮助等所设。\n1、故事前情 1.0 苦逼作者 由于近期事情确实太多，无法腾出单独时间来解决一些bug，只能解决一些方便解决的问题。\n1.1 用户群的美好氛围 2026.7.16，用户们正在正常的交流问题、互相帮助。\n1.2 神临！ 2026.7.17，一位神人加入了群聊，并反馈了iOS端的UI问题、发热问题，并暗戳戳拿我跟作者版本对比。\n1.3 其他用户的一些反馈 有些有回复，有些并没有回复。\n一个是移动端没有多开我已经多次说明了，有群友帮我回复了；一个是闪退没有日志，我无法定位。\n2、纷争开始了 2.0 作者开团 我自我反省，当时一打开群，全是问题，确实心烦意乱不想解决，但是这都是我的真实想法，我确实是不想解决这些根本难以定位的、难以解决的问题。\n值得注意的是，引用回复了神人哥的发热bug反馈。\n2.1 神人哥开始反击 神人哥首先指出自己有实力编译，用我软件是给我脸。\n其次攻击我贴收款码，指出开源作者就应该为了世界更加美好，而自愿的贡献自己的一切！\n（别说我过度解读，其自己都承认是donation，莫非是不懂donation的意思？那我建议，让豆包快速版教教他，豆包快速版的智商大概是其的十倍以上） 关于能否贴收款码，我已经在GPL 3.0 中说明了该项目协议的内容。\n随后攻击我开群是为了听彩虹屁，而非听取反馈，从而因为我不给他解决他的问题和反馈，就完全否定了我自2026.5.4 fork项目开始，至今在issues里、Discussion、私人邮件中、群内解决的所有问题和贡献。 那么如果我是想听彩虹屁而开群，至少我也做出了值得配得上少量彩虹屁的贡献和对用户的帮助。\n而他，做了什么贡献吗？就因为他是用户，我就应该牺牲好久没过上的半个周末，来帮助他解决一个，对我而言没有任何帮助、任何作用的bug吗？且该问题属于UI，完全可以自我解决；发热问题，完全属于非紧急问题。\n这是我第一次向作者提交pull请求的链接，时间是2026.5.4。\nSimpleLive的一些小更新和release构建 by June6699 · Pull Request #886 · xiaoyaocz/dart_simple_live 最后指出其是老资历，反馈问题是给我面子😂🤣。我提出，你不给我日志，没有软件版本，我怎么解决呢？ 😂🤣\n😂🤣 \u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026gt; \u0026lt;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash;\u0026mdash; 😂🤣\n😂🤣\n2.2 神人哥直接破大防 由于自己的反馈没有被重视，神人哥破如防，直接说出了自己的名字，向姓傻名b的人致敬！\n神人哥说自己是开源大佬的老资历，为开源社区贡献极大😭😭😭😭😭😭。\n\\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/ \\😭/\n神人哥继续破防和展示大名\n2.3 好心群友加入战争 群友使用黑科技，获取了其撤回的消息：你以为我没抄袭过之前的release吗？\n好抄兄弟好抄\n还是那句话，我就是贴个空仓库，或者直接fork别人的仓库，啥都不干，就贴个收款码收自愿赞助，你能拿我怎样？\n还有Vibe Coding，我仓库60%以上新增代码都是Vibe的，剩下的一半是参考了一些其他优秀项目和网上找到的优秀源码，其他的才是我自己写的。那又怎么样呢？\n老资历甚至不允许别人fork、不允许别人fork后VibeCoding、瞧不起AI写的代码、瞧不起任何不给自己解决bug和反馈的作者。\n注意风险 老资历难道不用AI吗？那真得奖励一块xx手表了🤣🤣🤣🤣🤣。哦对了，收赞助，手表求赞助。\n2.4 大神哥又来了！ 这里需要说明，你反馈问题完全不需要说请，曾经有一个用户非常礼貌，生怕自己提的问题给我带来负担，我多次提醒其不需要这样，我依然会解决其的大量问题，该用户跟我也是伯牙与钟子期了。爱你哟😘\n回到大神哥，你不说请完全没问题，但是你也自己知道，我完全可以不给你修，完全孤立你，我就不管你，这也是完全可以的吧？我就是认为你的反馈对我的软件没有任何作用和帮助，你能怎样🤣🤣？\n但是你说一个请，甚至最后来句，\n哼~哼~！人家犹豫了好久好久，手指都快把裙边揉皱啦(。﹏。*)，但是还是想鼓起勇气跟作者大大缩(小声)… 首先是那个…就是那个啦！在iPad上把它横过来的时候，上面那行标题它…它它它居然还赖着不走！像只小蘑菇一样杵在屏幕边边，明明都横过来了的说(´･_･`)，和之前xiaoyaocz的版本感觉不一样呢，人家还不小心戳到好几次手指都酸酸的了啦！(╥﹏╥) 还有还有…那个平板呀，跑一阵子就会变得好烫好烫，像刚出炉的铜锣烧一样！(\u0026gt;_\u0026lt;) 以前看一整天都是凉凉的，现在抱在怀里都被暖得脸红了，这这这不会是它在害羞吧(/ω＼)…人家正在试着把弹幕关掉看看会不会冷静一点点，有结果了再跑来告诉大大哦～ 呜…完全没有说软件不好的意思啦，明明超喜欢到想一口吃掉！(๑°⌓°๑) 只是这些小家伙老是跳出来捣乱，人家忍不住想缩缩啦～作者大大周末要好好休息呀，啵啵！(づ￣3￣)づ╭❤～ yue\n那我忍着“恶心”我也要帮你解决到底！\n我认为尊重是相互的，你总共提问题也就花个一分钟，打个几十个字，然后就能得到另一个作者为你花费大量时间自我测试、自我修复完的完美软件，请问你在想什么？\n神人哥红头一号文件\n责令所有使用GPL 3.0协议的开发者！如果贴有Buy me a coffee或者任何赞赏码，老老实实来我神人哥这里领一句不要脸。\n而且神人哥说的这句话，有没有语文高手，告诉我下面这段话，哪里属于低声下气，哪里属于感谢作者？\n1.12.6 在 ios 26.5.2 上横屏之后标题不隐藏 另外ipad上播放一段时间过后发热严重，之前xiaoyaocz的版本没有碰到过这个问题，正在测试关闭弹幕后会不会缓解 2.5 大神哥展示老资历 真展示了吗？嘴上展示不是展示吗？\n神人哥自我检讨：“就这素质，真别写开源软件了”，我认为是他的自我检讨，因为我认为我的素质比他高多了。\n2.6 神人哥发动神力 你什么态度？！😡😡😡😡😡🤬🤬🤬🤬\n还是那句话，我就不修，叫爸爸考虑一下🤣🤣🤣🤣🤣🤣🤣，这么厉害为啥有空骂人没空自己解决这种小问题呀？\n诶，你就是反馈UI问题，我跟你要日志，你不给我就不修，你也得给我受着知道吗？\n我自己写的日志输出，有什么内容我能不知道吗？我就要日志，你能拿我怎样\n这里确实我的问题，我看错人了，但是我也没想到，我说没日志不修，结果最先叫的是这个提UI问题、发热问题的人🤣🤣🤣🤣🤣🤣🤣，那你挨喷也受着吧，你这种发言，喷你没毛病。\n2.7 神人哥说格局 看看人家的动手能力，再看看我们的超级大神的能力🤣🤣🤣🤣\n2.8 神人哥身份解锁！ 封印解除！百万年薪来来来🤣🤣🤣🤣🤣\n2.8 我们是平等的！ 神人哥骂着骂着突然发现自己“年薪百万”，傲立群雄，解锁了说教和衍生善良人格。\n这是贤者时刻吗？打完了就滚去洗手啊😡，记得刷刷牙，吃🔟了，嘴真臭。\n2.9 我反馈问题，神人哥爱答不理？！ 我们不是平等的吗？？？！！！\n神人哥发出指示：好好做事吧\n2.10 群友们纷纷希望学习 神人哥的仓库和“这么多开源软件”去哪里了？\n名词解释 · 结晶太监\n结晶太监 网络黑话完整解释，拆分两个词 1、结晶（结晶粉） 源自原神圈子，后扩散到直播、游戏论坛（NGA、刀区、LOL 区）。 指无脑死忠粉丝：自家主播 / 偶像自己能吐槽，外人但凡说一句不好，立刻冲上去洗地、对线、扣帽子，极端护主，毫无客观判断力，贬义。 同义词：孝子、精神股东、厨力魔怔人。 2、太监 这里是比喻，不是历史宦官： 形容一群贴身伺候、揣摩主子心思、主动帮主人控评传话、打压路人的核心死忠骨干，像宫里太监围着皇帝转，卑微跪舔、对外充当嘴替。 细分：大太监（核心管理层 / 房管 / 老牌粉头）、小太监（普通狂热护主粉）。 合起来：结晶太监 极端狂热、专职护主、主动对线控评的核心死忠粉头，是很重的贬称。 2.11 我们是平等的2 开源却不给看？难道开源到gayhub去了？\n2.12 神人哥换人了？ 神人哥突然解锁了善良人格\n阴阳怪气怎么了？就不修，就阴阳怪气，受不了就退网知道吗？\n这里要开团Bilibili iPadOS客户端，修了这么久，还是有闪退问题，天天更新日志就写点看球赛、吃冰棍，你在吃牛魔呢？评论区骂飞了都\n本次修复了一些已知问题。 到这里，故事就告一段落了，神人哥突然换人，猝不及防。\n赞美群友。\n还有我为啥要格局？我都玩开源了，你就让让我吧😭😭😭😭😭😭。\n2.13 神人哥违法 对呀，我不想修，我就故意要你日志，你能怎样呢？反而你在一个100多人的群内，公开辱骂多人傻逼、幼稚、没格局、结晶太监，我完全可以告你侮辱罪。\n《民法典》第 1024 条，微信群 130 人属于公开网络空间，当众辱骂贬低，明确侵犯名誉权、人格尊严\n链接 《治安管理处罚法》第 42 条：公然侮辱他人可治安处罚。多次辱骂、百人大群、拒不认错，属于情节较重，警方可以直接处罚对方。\n那么如果我起诉你，你会发生什么呢？\n已有案件参考：案件进行时丨微信群不是“骂战战场”！一男子因辱骂邻居被判道歉赔款 【案情简介】\n王某在兴庆区某小区微信业主群内，回复其他业主关于房屋质量的问题，不料却遭遇邻居李某的微信语音辱骂。当晚王某添加李某微信进行沟通，李某再次向王某发送 你这废物 等攻击性言辞。其后，王某向银川市公安局兴庆区分局某派出所报警，经该派出所调解，双方达成李某在微信群内向王某道歉的调解协议。后王某诉至兴庆法院，要求李某在朋友圈和业主微信群赔礼道歉并保留15天、消除影响、恢复名誉，赔偿精神损害赔偿金及误工费、交通费等费用共计4000余元。\n【裁判结果】\n兴庆法院受理案件后，经审理判决李某在居民微信业主群中（如李某已退群，无法加入微信群时，则书面道歉）向王某赔礼道歉（字数不少于200字，道歉内容由法院审核，保留15天），并支付原告交通费及精神损害赔偿金共计800元。判决后，双方均未上诉，李某已履行道歉及赔偿义务。\n3、后续神人哥继续与群友发生冲突 好像大家确实把他当傻子来着。又辱骂别人耶🐶，而且人家可能真认识这样一个人，以前张嘴格局，闭嘴格局。现在人在精神病院住了好几年了。现在好像我也快认识了🤣🤣🤣🤣\n到底是谁在精神胜利真的好难猜呀，从头到尾吹自己\n年薪百万 开源大神，开源无数软件，免费给别人用 从头到尾嘴像吃了⑩一样乱喷，攻击这个攻击那个 4、最后也是小火了一把 最后也是在其他开源作者那里火了一把\n非常感谢M***用户帮我说话，在群里也帮我说话，非常感谢！我确实也懒得跟这种人发火，发火破坏自己的周末吗？\n最后学习一下其他作者们的解气瞬间，希望使用开源软件的用户们明白一点，你用别人的软件，只是因为人家想给你用，你免费使用的时候，心里但凡有一丝丝的感谢，我相信作者们都愿意为你解决问题。\n而不是说，作者发布的软件，有一些问题，你就逮着骂、逮着要求，无丝毫尊重、礼貌之心\n那请问：求你用了吗？你是花钱了吗？你是赞助了吗？\n5、结尾 欢迎你神人哥继续评论，让我找到你，把你拉群里继续提供节目。\n对了收赞助收赞助，还要收一块xx手表用来奖励神人哥。\n神人哥气不气？我就收赞助，你能怎样？\n","permalink":"https://june6699.github.io/posts/%E7%A7%8D%E7%94%B0%E4%BD%9C%E8%80%85%E5%A4%A7%E6%88%98%E7%99%BE%E4%B8%87%E5%B9%B4%E8%96%AA%E5%A4%A7%E5%8E%82%E7%A8%8B%E5%BA%8F%E5%91%98%E4%BA%8B%E4%BB%B6%E8%AE%B0%E5%BD%95/","summary":"\u003cp\u003e2026.7.19，我fork自 \u003ca href=\"https://github.com/xiaoyaocz/dart_simple_live\" target=\"_blank\" rel=\"noopener noreferrer\"\u003exiaoyaocz/dart_simple_live\u003c/a\u003e\n 二次开发的 \u003ca href=\"https://github.com/June6699/dart_simple_live\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eJune6699/dart_simple_live\u003c/a\u003e\n 所属的\u003ccode\u003eSimpleLive\u003c/code\u003e用户群，迎来了一位\u003cmark\u003e大厂程序员\u003c/mark\u003e！蓬荜生辉！\u003c/p\u003e\n\u003cp\u003e期间该“大神”，与我和用户们发生了友好的交流。下面展示故事背景、故事经过、故事结果。\u003c/p\u003e","tags":["随笔","生活/文章"],"title":"种田作者大战百万年薪大厂程序员事件记录"},{"content":"最近一直在想一句话：\n如果看一个男人好不好，就看他身上有没有女性的影子；如果看一个女人好不好，就看她身上有没有男性的影子。\n我大概明白它想说什么。所谓“女性的影子”，不是优柔寡断，而是感性、共情、愿意保护弱者；所谓“男性的影子”，也不是要做一个“女汉子”，而是理性、独立，遇到问题有办法处理。\n这句话听起来很有道理，可再想一层，我又觉得这些品质原本就不属于哪一种性别。温柔不是女性借给男性的，决断也不是男性借给女性的。一个人真正成熟，也许只是既能感受到别人的痛苦，又不至于被情绪推着走；既有能力解决问题，也知道什么时候该向别人求助。\n比起“身上有没有异性的影子”，我更愿意把它叫作人格逐渐完整。只是这句话也把我带进了另一个更麻烦的问题：我真的能平等地看待每一种生命、每一种观点吗？\n答案似乎是否定的。\n我真正卡住的，是“有害”和“有罪” 我的同情心并不平均。\n看到大象被猎杀，我会觉得残忍；看到熟悉的狮群破碎，或者某只虎王死亡，我也会难过。可看到清除红火蚁、非洲大蜗牛或清道夫的视频，我有时却会觉得痛快。流浪猫捕食野鸟，我又会对猫产生厌恶，尤其反感那些只负责投喂，却不绝育、不领养，也不承担后果的人。\n这些感受挤在一起，当然不整齐。我一度想给它们找一套简单的解释：入侵物种破坏生态，所以该清除；狮虎属于自然捕食，所以没有错；虐待动物只是为了取乐，所以是恶；流浪猫伤害本土动物，所以不该被无节制地投喂。\n这套解释能用，但还不够。\n我首先混淆了“有害”和“有罪”。一种动物在某个环境里造成巨大危害，不代表它在道德上犯了错。红火蚁不会选择自己被带到哪里，大蜗牛也没有策划一场生态入侵，流浪猫更不懂什么叫本土物种保护。它们会造成真实的伤害，却不是能够被审判的道德主体。\n“入侵”是生态学上的位置，不是写在动物身上的罪名。\n真正需要被追问的，是有选择能力的人：是谁把外来物种带进了新的环境，谁遗弃了宠物，谁为了自己的喜好放养、繁殖或投喂，又是谁决定用什么方式治理。\n整理这些想法时，我还发现了另一个更明显的错误：我曾把“女权”“女拳”和入侵物种放在同一句话里，像是在列举几种令我厌恶的东西。这不只是分类混乱，也很容易把复杂的人压扁成一个该被清理的标签。\n“女权”本来就不是一种整齐划一的主张，更不能直接等同于网络语境里的“女拳”。我当然可以反对某种具体言论，批评双重标准、仇恨表达或者把个人偏好凌驾于他人权利之上的做法，但至少要说清楚：我反对的是哪句话、哪种行为、哪套逻辑。把一群人整体叫作愚蠢，省掉了论证，也省掉了理解。\n我不能一边说要尊重不同经历造成的观点分叉，一边又把不喜欢的人直接塞进一个标签里。\n自然没有法庭 狮子捕食斑马，老虎捕食羚羊，它们当然给猎物造成了痛苦。但“造成痛苦”和“故意作恶”不是一回事。\n霸凌是一个带有责任判断的词。它通常意味着行为者能够理解自己在做什么，也有不这样做的选择，却仍然利用力量差距反复伤害对方。捕食者没有站在草原上权衡善恶，它只是在活下去。斑马的痛苦是真的，狮子的“恶”却不存在。\n不过，这也不意味着自然发生的一切都是好的。自然既不仁慈，也不邪恶，它只是早于人类的道德判断存在。我们通常不去阻止每一次捕食，不是因为死亡忽然变得美好，而是因为捕食者同样需要生存，生态关系远比眼前的一幕复杂，人类也没有能力把所有痛苦从自然中删除。贸然干预，常常只会制造新的问题。\n同样，保护区里的野生动物数量管理也不能只凭“我喜欢这只动物”或者“管理方说是为了生态”来判断。有时迁移、绝育、栖息地修复或数量控制确实可能有必要，有时所谓管理也可能掩盖了数据不足、栖息地被人类压缩，甚至逐利。要看的不是一句口号，而是证据是否可靠、有没有伤害更小的替代方案、程序是否透明，以及人类有没有先为自己造成的问题负责。\n一只动物不需要先变成坏蛋，人类才有资格处理生态冲突。反过来，一项行动打着保护生态的旗号，也不会因此自动正确。\n必要的治理，不是残忍的通行证 这也是我必须对自己更诚实的地方。\n入侵物种治理可能需要捕杀，但目标正确，不能替所有手段免责。是否合法、是否由专业人员实施、能不能真正控制种群、会不会误伤别的动物、有没有痛苦更小的做法，这些问题都不能被一句“它是入侵物种”盖过去。\n网络上的清除视频尤其容易混进另一种东西：表面在讲生态，镜头却一直追逐挣扎和毁灭。算法知道什么能让人停下来，于是嫌恶、报复感和“终于清理干净了”的畅快被揉在一起，越推越刺激。\n我可以问自己一个不太舒服的问题：如果同样的治理效果能够更快、更少痛苦地完成，而且没有近距离的血腥画面，我还会不会觉得满意？\n如果答案是会，那么我在意的可能是危害被控制、秩序被恢复。如果答案是否定的，如果真正吸引我的是受苦的过程，那就不能再拿生态保护替这种快感辩护。\n这不意味着看过或喜欢过这些视频，就要立刻给自己判一个“残忍”的罪名。人的情绪本来就混杂，厌恶某种危害时，很容易把对危害的愤怒转移到一个具体对象身上。可我也不想假装这种转移毫无风险。反复把痛苦当成爽点，久了以后，那把衡量痛苦的尺也许真的会变钝。\n不必急着给自己定罪，也别急着替自己的快感写无罪辩护。\n善意也要看账单寄给谁 我对流浪猫投喂的反感，有一部分并没有错。自由活动的猫会捕食鸟类和小型动物，只投喂而不绝育、不监测，可能让更多猫聚集并继续繁殖。投喂者获得了“我今天救了一只猫”的满足，野鸟、周边居民和环境却可能在替这份善意付账。\n问题不在于善良，而在于善良只看见了眼前。\n可是，把所有投喂者都说成自私，也太轻易了。有些人确实不知道后果，有些地方缺少收容和领养条件，也有人已经在尽力绝育、送养、治疗。善意不完整，需要补上责任；它不一定从一开始就是虚伪。\n领养、室内饲养，或者让家猫只在牵引和封闭空间里外出，通常比随意放养更负责。TNR，也就是抓捕、绝育、放归，可以减少继续繁殖，却不是一个放在哪里都有效的万能答案。覆盖率不够时，猫群数量未必降得下来；即便完成绝育，放归的猫仍然可能捕猎。在生态敏感区域，收容、领养和不再放归往往需要被优先考虑。\n猫没有错，鸟也不比猫低一等。正因为两边都不是道德上的坏人，拥有选择的人才更不能只凭偏爱行事。\n世界是灰的，尺子不能没有刻度 所以，并不是所有事情都要强行“辩证”成五五开。\n辩证地看问题，是承认同一个行为会落在不同关系里，会带来短期和长期、局部和整体的不同后果。它要求我多看几层，但不是要求我最后说一句“大家都有道理”，然后放弃判断。\n事实是否可靠？行为者有没有选择？目的是否正当？手段有没有必要、是否有效？有没有伤害更小的替代方案？最后又是谁承担代价？这些问题无法保证我每次都答对，却至少能让判断不只跟着一时的喜欢和厌恶走。\n如果每一个判断都要反过来怀疑一次，再把怀疑也怀疑一遍，直到非得找到一个百分之百没有漏洞的答案才肯停下来，这更像反刍和分析瘫痪，不是辩证。若因为每个人角度不同，就认为所有观点都同样正确，那会滑向道德相对主义；若再往前一步，觉得既然没有绝对答案，一切都没有意义，才是虚无主义。\n世界是灰色的，不代表灰色没有深浅。理解一个观点怎样形成，也不等于承认它就是对的。\n人的思想确实像一个参数多得惊人的函数。早期经历、读过的一本书、一次被善待或被伤害的经验，都可能改动其中一个参数。一个念头有时像哈希的雪崩效应，输入只差一点，输出已经完全不同；人生又像不断向前的代码分支，起初只是岔开一小步，走得久了，彼此就隔得很远。\n但人并不是一个只能运行一次的程序。我们还能回头看日志，发现哪一步用了错误的事实，哪一处把情绪当成了证据，哪一个分支虽然自洽，却把别人的痛苦排除在外。内部自洽并不够，一套残酷的世界观也可以非常自洽。它还要经得起事实、同等的关切，以及新证据出现后的修正。\n我大概不需要一套永远不会出错的世界观。我更需要一套可以调试的世界观。\n少把那些无从选择的生命送上道德法庭，多要求那些拥有选择的人——也包括我自己——为选择负责。\n","permalink":"https://june6699.github.io/posts/%E6%88%91%E5%8F%91%E7%8E%B0%E8%87%AA%E5%B7%B1%E7%9A%84%E5%90%8C%E6%83%85%E5%BF%83%E5%B9%B6%E4%B8%8D%E5%B9%B3%E5%9D%87/","summary":"\u003cp\u003e最近一直在想一句话：\u003c/p\u003e\n\u003cblockquote\u003e\n    \u003cp\u003e如果看一个男人好不好，就看他身上有没有女性的影子；如果看一个女人好不好，就看她身上有没有男性的影子。\u003c/p\u003e\n\n  \u003c/blockquote\u003e\u003cp\u003e我大概明白它想说什么。所谓“女性的影子”，不是优柔寡断，而是感性、共情、愿意保护弱者；所谓“男性的影子”，也不是要做一个“女汉子”，而是理性、独立，遇到问题有办法处理。\u003c/p\u003e","tags":["随笔","生活/文章"],"title":"我发现自己的同情心并不平均"},{"content":"这次折腾 QQ Bot，最容易误会的一点是：\n配置好 AppID 和 Secret，不等于你已经知道消息要发给谁。 Bot 能上线，是一回事；它要主动给某个人发私聊，是另一回事。\n我一开始也绕了弯。明明 QQ Bot 已经连上了，OpenClaw 里也显示 running、connected，但测试发送还是失败。后来才发现，我把自己的 QQ 号当成了收件人 target。QQ Bot 这边真正要用的不是裸 QQ 号，而是平台给这一段会话分配的 openid。\n也就是说，最后能发消息的目标长这样：\nqqbot:c2c:\u0026lt;openid\u0026gt; 不是这样：\n3439394104 这篇就把这件事记下来，免得下次再把自己绕进去。\n先把 Bot 接到 OpenClaw QQ 开放平台里创建机器人后，会拿到两样东西：\nAPPID APPSecret 这两个值不要写进博客、仓库、截图，也不要发到群里。它们相当于这个 Bot 的钥匙。\nOpenClaw 这边可以用 channels add 接进去：\nopenclaw channels add \\ --channel qqbot \\ --account default \\ --token \u0026#34;\u0026lt;APPID\u0026gt;:\u0026lt;APPSecret\u0026gt;\u0026#34; \\ --name \u0026#34;xianyu-qq-bot\u0026#34; 如果插件还没装，OpenClaw 会尝试准备 QQ Bot 插件。接完后先看状态：\nopenclaw channels status --deep 理想状态大概是：\n- QQ Bot default: enabled, configured, running, connected 如果只看到 installed，或者提示被 allowlist 拦住，就先去看 OpenClaw 配置。常见位置是：\n/root/.openclaw/openclaw.json 里面的 plugins.allow 至少要包含：\n[\u0026#34;xianyu\u0026#34;, \u0026#34;qqbot\u0026#34;] 改完配置后重启网关：\nopenclaw gateway restart 这一步解决的是“Bot 能不能接上 OpenClaw”。它还没有解决“Bot 要发给谁”。\n为什么 QQ 号不能直接用 我之前测试时填过自己的 QQ 号，结果报错大概是这样的：\nUnknown target \u0026#34;3439394104\u0026#34; for QQ Bot. Hint: QQ Bot target format: qqbot:c2c:openid (direct) or qqbot:group:groupid (group) 这句其实已经把答案说完了。\nQQ Bot 插件要的 target 是 OpenClaw 和 QQ 开放平台识别出来的会话目标。私聊是 c2c，群聊是 group。所以私聊目标应该是：\nqqbot:c2c:\u0026lt;openid\u0026gt; 群聊目标则是：\nqqbot:group:\u0026lt;groupid\u0026gt; QQ 号是人看的，openid 是接口用的。这里不能混着用。\n让对方先给 Bot 发一句话 最简单的办法，是让接收人先给这个 QQ Bot 发一条私聊。\n内容随便，比如：\n111 这条消息进来后，OpenClaw 会把这段会话记录下来。之后就可以去会话文件里找真实 target。\n我这次是在这里找到的：\n/root/.openclaw/agents/main/sessions/sessions.json 里面会有类似这样的字段：\n{ \u0026#34;origin\u0026#34;: { \u0026#34;label\u0026#34;: \u0026#34;qqbot:c2c:\u0026lt;openid\u0026gt;\u0026#34;, \u0026#34;provider\u0026#34;: \u0026#34;qqbot\u0026#34;, \u0026#34;surface\u0026#34;: \u0026#34;qqbot\u0026#34;, \u0026#34;chatType\u0026#34;: \u0026#34;direct\u0026#34;, \u0026#34;from\u0026#34;: \u0026#34;qqbot:c2c:\u0026lt;openid\u0026gt;\u0026#34;, \u0026#34;to\u0026#34;: \u0026#34;qqbot:c2c:\u0026lt;openid\u0026gt;\u0026#34;, \u0026#34;accountId\u0026#34;: \u0026#34;default\u0026#34; }, \u0026#34;lastTo\u0026#34;: \u0026#34;qqbot:c2c:\u0026lt;openid\u0026gt;\u0026#34; } 这里的 lastTo 就是可以拿来发消息的目标。\n如果只是临时排查，可以直接搜：\ngrep -n \u0026#34;qqbot:c2c:\u0026#34; /root/.openclaw/agents/main/sessions/sessions.json 找到以后，不要把完整 openid 写进公开仓库。自己服务器上的 .env 可以放，博客和文档里用占位符就好。\n把 target 写到业务配置 我的闲鱼 Bot 是通过环境变量决定通知发给谁。关键是这几个：\nXIANYU_ENABLE_MESSAGE_NOTIFY=true OPENCLAW_BIN=openclaw JUNE_QQ_TARGET_ID=qqbot:c2c:\u0026lt;openid\u0026gt; 如果有备用变量，也可以一起写：\nXIANYU_QQ_TARGET_ID=qqbot:c2c:\u0026lt;openid\u0026gt; 注意，JUNE_QQ_TARGET_ID 这里不要再填 QQ 号。要填完整的 qqbot:c2c:\u0026lt;openid\u0026gt;。\n写完后，如果服务是 systemd 跑的，就重启业务服务：\nsystemctl restart xianyu-bot.service 如果只是 OpenClaw 通道配置变了，就重启 OpenClaw gateway：\nopenclaw gateway restart 具体重启哪个，看你改的是业务 .env，还是 OpenClaw 的 openclaw.json。\n先发一条测试消息 不要一上来就跑周报。周报内容长，出了问题不好判断。\n先发一条短消息：\nopenclaw message send \\ --channel qqbot \\ --target \u0026#34;qqbot:c2c:\u0026lt;openid\u0026gt;\u0026#34; \\ --message \u0026#34;QQ Bot 通知测试\u0026#34; 如果业务里已经封装了通知脚本，也可以用自己的测试脚本。例如我的闲鱼 Bot 里有一个：\ncd /opt/xianyu-openclaw-channel .venv/bin/python ops_toolbox/5.qq_notify_test.py --send 这里有一个小坑：很多测试脚本默认只是预览，必须加 --send 才是真的发送。\n终端里看到类似下面这样，才算真的通了：\n发送结果: True QQ 私聊通知已发送 最好再去 QQ 里看一眼，确认 Bot 那边真的收到了。\n周报也是同一条链路 周报本质上不是另一套东西。它只是把市场采样、售出记录、自我总结这些内容整理好，再调用同一个 QQ 通知能力发出去。\n所以周报能不能发，先看三件事：\nqqbot 通道是否 connected； .env 里的 target 是否是 qqbot:c2c:\u0026lt;openid\u0026gt;； 测试通知是否已经能发到 QQ。 定时器可以这样看：\nsystemctl status xianyu-weekly-report.timer systemctl list-timers --all xianyu-weekly-report.timer --no-pager 手动跑周报前，先确认你真的想发送，不是只想看预览：\ncd /opt/xianyu-openclaw-channel bash ops_toolbox/4.run_weekly_report_send.sh --send 如果只是调试内容，先不要带 --send，否则 QQ 上会被刷屏。\n这次真正踩到的坑 最后把几个坑放在一起：\nAPPID + APPSecret 只是让 Bot 上线，不代表它知道要发给谁。 私聊 target 不是 QQ 号，而是 qqbot:c2c:\u0026lt;openid\u0026gt;。 新 Bot 和旧 Bot 的 openid 不能想当然复用。 用户先给 Bot 发一句话，OpenClaw 才更容易留下会话 target。 channels status --deep 看到 connected，才算通道活着。 测试脚本要看清楚是不是预览模式，真实发送通常要加 --send。 公开文档里不要写真实 Secret、Cookie、openid。 这件事想明白后，其实不复杂。\nQQ Bot 给人发消息，关键不是“知道他的 QQ 号”，而是“这段会话在平台里叫什么”。人用 QQ 号认人，接口用 openid 认人。把这两个概念分开，后面就顺了。\n","permalink":"https://june6699.github.io/posts/%E8%AE%A9-qq-bot-%E4%B8%BB%E5%8A%A8%E7%BB%99%E4%BD%A0%E5%8F%91%E6%B6%88%E6%81%AF-%E5%85%B3%E9%94%AE%E4%B8%8D%E6%98%AF-qq-%E5%8F%B7%E8%80%8C%E6%98%AF-openid/","summary":"\u003cp\u003e这次折腾 QQ Bot，最容易误会的一点是：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e配置好 AppID 和 Secret，不等于你已经知道消息要发给谁。\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eBot 能上线，是一回事；它要主动给某个人发私聊，是另一回事。\u003c/p\u003e","tags":["技术","技术/运维","技术/工具"],"title":"让 QQ Bot 主动给你发消息：关键不是 QQ 号，而是 openid"},{"content":"新服务器到手后，第一件事通常不是装环境，而是把 SSH 登录整理干净。\n密码登录能用，但它不适合每天敲。容易输错，也容易让人心里没底：这台机器到底配过没有？免密登录听起来像是“把密码省掉”，其实不是。它更像是提前给服务器留一张名单：这把公钥我认识，拿着对应私钥的人可以进。\n先把原理想明白 SSH key 是一对东西：私钥留在本机，公钥放到服务器。\n登录时，服务器不会让你把私钥发过去。它只是出一道题，让本机用私钥签名。签名能被服务器上的公钥验证通过，就放行。\n所以整个过程真正要做的是三件事：\n本机生成一对 key； 把公钥追加到服务器的 ~/.ssh/authorized_keys； 在本机的 ~/.ssh/config 里写一个好记的别名。 私钥不能发给别人，也不要贴进聊天记录。公钥可以公开一些，但也没必要到处扔。\n为什么加了公钥，还是要密码 这个坑很常见。\nauthorized_keys 里有你的公钥，不代表服务端一定会用它。OpenSSH 还有自己的配置开关。如果服务器上 PubkeyAuthentication 是 no，客户端再努力也没用，服务端会直接说：这里只接受密码。\n排查时我一般不猜，直接看两边。\n本地用 -vvv 看客户端有没有拿出正确的 key；服务器上用 sshd -T 看真实生效的配置。注意是 sshd -T，不是只看配置文件里写了什么。因为 /etc/ssh/sshd_config.d/ 下面的小配置也可能覆盖主配置。\n这一步有点像修灯。灯泡没坏，不代表墙上的开关是开的。\n境外服务器先处理网络 如果服务器在境外，另一件事也要先想清楚：代理。\nSSH 登录本身通常不需要在服务器上开代理，它只要端口能连通就行。但登录进去之后，你很可能要装软件、拉 GitHub 仓库、下载 Docker 镜像、访问包管理源。网络不顺的时候，报错会很像“命令坏了”，其实只是连不上。\n我的习惯是先把基础代理或镜像源准备好，再继续装环境。不要一上来就怀疑 apt、git、curl。服务器网络是第一层地板，地板不平，后面每一步都跟着晃。\n别名比记 IP 舒服 直接敲 ssh \u0026lt;User\u0026gt;@\u0026lt;Your_IP\u0026gt; 可以用，但用久了很烦。IP 不好记，端口、用户、私钥路径也容易敲错。\n~/.ssh/config 的意义就在这里。你给这台机器起一个别名，以后只敲：\nssh \u0026lt;Host_Alias\u0026gt; 背后的用户、IP、端口、私钥，全部写进配置。这样也方便给不同服务器用不同 key，不会把所有机器都混在一把钥匙里。\n最后一组命令 下面这组是通用模板，按自己的情况替换占位符就行。\n先在本机生成专用 key：\nssh-keygen.exe -t ed25519 -a 100 -f \u0026#34;$env:USERPROFILE\\.ssh\\\u0026lt;Key_Name\u0026gt;\u0026#34; -C \u0026#34;\u0026lt;Host_Alias\u0026gt;\u0026#34; 如果不想每次登录都输入私钥口令，Enter passphrase 的时候直接回车两次。更稳一点的做法是设置 passphrase，然后用 ssh-agent 缓存。不过个人小服务器图省心的话，无口令 key 也常见，前提是私钥文件别乱放。\n把公钥写到服务器：\nGet-Content -Raw -Encoding UTF8 \u0026#34;$env:USERPROFILE\\.ssh\\\u0026lt;Key_Name\u0026gt;.pub\u0026#34; | ssh.exe -o PreferredAuthentications=password -o PubkeyAuthentication=no \u0026lt;User\u0026gt;@\u0026lt;Your_IP\u0026gt; \u0026#34;umask 077; mkdir -p ~/.ssh; cat \u0026gt;\u0026gt; ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys\u0026#34; 如果服务端关了公钥登录，进服务器改：\nsudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d-%H%M%S) sudo nano /etc/ssh/sshd_config 确认有这一行：\nPubkeyAuthentication yes 检查配置并重载：\nsudo sshd -t sudo systemctl reload ssh || sudo systemctl restart ssh 本机写别名：\nHost \u0026lt;Host_Alias\u0026gt; HostName \u0026lt;Your_IP\u0026gt; User \u0026lt;User\u0026gt; Port 22 IdentityFile ~/.ssh/\u0026lt;Key_Name\u0026gt; IdentitiesOnly yes 最后测试：\nssh \u0026lt;Host_Alias\u0026gt; 如果还有问题，就别急着重来。先看 debug：\nssh.exe -vvv -o IdentitiesOnly=yes -i \u0026#34;$env:USERPROFILE\\.ssh\\\u0026lt;Key_Name\u0026gt;\u0026#34; \u0026lt;User\u0026gt;@\u0026lt;Your_IP\u0026gt; 能看懂两行就够了：本地有没有 Offering public key，服务端有没有继续允许 publickey。这比凭感觉改配置靠谱多了。\n免密不是魔法，也不是把密码藏到了什么地方。它只是把“我是谁”从一串要背的字符，换成了一把本机保存的钥匙。机器认钥匙，人少受罪。\n","permalink":"https://june6699.github.io/posts/%E7%BB%99%E6%96%B0%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%85%8D-ssh-%E5%85%8D%E5%AF%86-%E5%AE%83%E5%85%B6%E5%AE%9E%E5%8F%AA%E6%98%AF%E5%9C%A8%E8%AE%A4%E4%B8%80%E6%8A%8A%E9%92%A5%E5%8C%99/","summary":"\u003cp\u003e新服务器到手后，第一件事通常不是装环境，而是把 SSH 登录整理干净。\u003c/p\u003e\n\u003cp\u003e密码登录能用，但它不适合每天敲。容易输错，也容易让人心里没底：这台机器到底配过没有？免密登录听起来像是“把密码省掉”，其实不是。它更像是提前给服务器留一张名单：这把公钥我认识，拿着对应私钥的人可以进。\u003c/p\u003e","tags":["技术","技术/运维","技术/工具"],"title":"给新服务器配 SSH 免密：它其实只是在认一把钥匙"},{"content":"Keynote by NVIDIA CEO Jensen Huang at 2024 SIEPR Economic Summit 开场与主持人介绍 英文清理版 Welcome back everyone, after the short break. I know that many of you are looking forward to hearing from our next speaker, Jensen Huang. Jensen is at the cutting edge of artificial intelligence and all of the innovation, technology, and human capital that is needed to support it. My good friend and superb colleague John Shoven is going to introduce Jensen. I hope he is here somewhere, so I am just going to keep talking until the two of them have a conversation and then take some of your questions.\nJohn Shoven certainly requires very little introduction to most people in this crowd. As my predecessor as the director of SIEPR, John is the one who started the SIEPR Economic Summit twenty years ago. I would like all of us to give John Shoven a huge round of applause and appreciate the community that he had the foresight to build.\nFor those of you who have not been touched by John’s research, mentorship, or friendship, here is just a snippet of what you might like to know about him. Along with being the former SIEPR director and a senior fellow emeritus, John is the Charles R. Schwab Professor of Economics. He is also a senior fellow at the Hoover Institution and a research associate of the National Bureau of Economic Research. He specializes in public finance and corporate finance and has published many articles over the years on social security, health economics, corporate personal taxation, mutual funds, pension plans, economic demography, applied general equilibrium economics, and much more.\n中文翻译 欢迎大家在短暂休息后回来。想必很多人都很期待接下来这位发言人，Jensen Huang。Jensen 站在人工智能以及支撑它所需要的创新、技术和人才的最前沿。我的好朋友、优秀的同事 John Shoven 将为 Jensen 做介绍。我希望他就在现场，所以我就先继续说几句，等他们两位展开对话之后，再留些时间给大家提问。\nJohn Shoven 对在座的大多数人来说几乎无需介绍。作为我在 SIEPR 的前任主任，John 正是二十年前创办 SIEPR Economic Summit 的人。我想请大家一起为 John Shoven 送上热烈掌声，也向他当年有远见创建的这个学术共同体致意。\n如果你还没有接触过 John 的研究、指导或者友谊，这里简单介绍几项他的成就。除了曾任 SIEPR 主任、现在是荣休资深研究员之外，John 还是 Charles R. Schwab 经济学教授，也是 Hoover Institution 的资深研究员和 National Bureau of Economic Research 的研究合作者。他专攻公共财政与公司金融，长期研究社会保障、健康经济学、企业与个人税收、共同基金、养老金、经济人口学、应用一般均衡经济学等多个领域。\nJensen Huang 的美国梦 英文清理版 So I have always thought that the more famous the speaker, the shorter the appropriate introduction. And if I were to follow that rule, I would stop right now and say Jensen Huang. But I am not going to do that.\nThe Oxford English Dictionary defines the American dream as a situation where everybody has an equal opportunity for success through hard work, dedication, and initiative. I would like to say that Jensen Huang is an example of the American dream. Jensen was born in Taiwan, came to the US at age nine with his brother, not with his parents, went to a rough school in Kentucky, survived that, and when his parents came two years later he moved to Oregon, skipped two grades, graduated from high school, and went to Oregon State as an electrical engineering major.\nHe was sixteen, looked like he was twelve, and had no chance with the women. But he liked one of them and said, why don’t we work on homework together? He did that over and over again. Six months later he asked her out on a date, and he is still married to her. So that is another American dream.\nNow to skip ahead to age thirty, he co-founded Nvidia. He has been the only CEO Nvidia has ever had. It has had ups and downs, more ups and downs, and now it is the fourth largest company in the world and the third largest American company. That sounds to me like the American dream.\nHe also got a master’s degree from Stanford. Now of course, we were here last week, and Nvidia announced its earnings in a finance crowd. This got more attention than the Super Bowl and occurred a couple of weeks earlier. It was pretty amazing. His company is at the absolute center of the most exciting technological development of the twenty-first century, and he deserves to be congratulated on that.\nHe has received a lot of awards and a lot of recognition. Last month, he was elected as a member of the National Academy of Engineering. I asked ChatGPT how many CEOs of S\u0026amp;P 500 companies are members of the National Academy of Engineering, and I did not get an absolutely clear answer, but I think it is three. And two are in this room. Aravind? Arvind? of Cadence Design Systems was awarded it last year, so the two of them have that in common.\n中文翻译 我一直觉得，发言人越有名，介绍就应该越简短。按这个标准，我本来现在就可以直接说一句 “Jensen Huang” 然后停下来了，不过我不会这么做。\n《牛津英语词典》把“美国梦”定义为这样一种状态：每个人都可以通过勤奋、投入和主动性获得平等的成功机会。我想说，Jensen Huang 就是美国梦的典型。他出生于台湾，九岁时和哥哥一起来到美国，不是和父母一起来的。他先在肯塔基州的一所条件很艰苦的学校上学，后来坚持了下来；两年后父母才过来，他又搬到俄勒冈，跳了两级，顺利读完高中，之后进入俄勒冈州立大学，主修电气工程。\n那时他十六岁，看起来像十二岁，在女生面前几乎没有机会。不过他看上了其中一位，就说：“我们要不要一起做作业？”他一遍又一遍地这样约她，六个月后终于约到第一次正式约会，而他现在依然和她结婚生活在一起。所以，这也是另一种美国梦。\n再快进到三十岁时，他共同创办了 Nvidia。他一直是 Nvidia 唯一的 CEO。公司一路起起伏伏，但最终成长为全球第四大公司，也是美国第三大公司。对我来说，这就是美国梦。\n他后来还拿到了 Stanford 的硕士学位。前不久我们就在这里，Nvidia 在金融圈发布财报，热度甚至超过了超级碗，而且发生得还更早一些，真的非常惊人。他的公司正处在二十一世纪最激动人心的技术变革中心，值得我们向他致敬。\n他获得过很多奖项和认可。上个月，他当选为美国国家工程院院士。我还问过 ChatGPT，S\u0026amp;P 500 公司 CEO 里有多少人是国家工程院院士，虽然没有得到特别清楚的答案，但我觉得大概只有三位。而且今天这里就有两位。Cadence Design Systems 的 Arvind 也是去年获得的，所以他们两位在这一点上很有共同点。\n计算的转折 英文清理版 So in my lifetime, I thought the biggest technical development, the technology breakthrough, was the transistor. It was pretty fundamental. But should I rethink, is AI now the biggest change in technology that has occurred in the last seventy-six years? That is a hint at my age.\nWell, first of all, the transistor was obviously a great invention, but what was the greatest capability that it enabled was software. The ability for humans to express our ideas, algorithms, in a repeatable way, computationally repeatable way, was the breakthrough.\nWhat have we done? We have dedicated our company in the last thirty-one years to a new form of computing called accelerated computing. The idea is that general-purpose computing is not ideal for every field of work. We invented a new way of doing computation. It was really, really good at trying to figure out this form of computation called deep learning. It is really good at this thing called AI.\nWe said, why don’t we use computers to write this software? Because the computational cost is approximately zero. So you might as well let the computer go off and grind on a massive amount of experience. We call data digital experience. Human digital experience is called data.\nWe thought if we could reduce the marginal cost of computing down to approximately zero, we might use it to do something insanely amazing: large language models to literally extract all of digital human knowledge from the internet and put it into a computer, then let it figure out what the knowledge is. That idea of scraping the entire internet and putting it in one computer sounds crazy, but that is where we are.\n中文翻译 在我的一生中，我一直认为最大的技术突破是晶体管。它当然非常基础、非常重要。但我现在是不是该重新思考一下：AI 会不会才是过去七十六年里最大的技术变革？这句话也顺便暴露了我的年龄。\n当然，晶体管毫无疑问是伟大的发明，但它真正启发出的最大能力，是软件。人类能够用可重复、可计算的方式表达自己的想法，也就是算法，这才是关键突破。\n那我们这些年都做了什么？过去三十一年里，我们把公司投入到一种叫做 accelerated computing 的新型计算方式上。因为通用计算并不适合所有工作领域，所以我们想发明一种新的计算方法。它特别擅长深度学习这种计算形式，也特别擅长我们今天所说的 AI。\n我们说，为什么不能让计算机来写这类软件呢？因为此时的计算成本几乎可以忽略不计。既然如此，不如让计算机去处理海量经验。我们把这种经验称为数据，也就是数字化的经验；而人类的数字化经验，本质上就是数据。\n我们当时想，如果能把计算的边际成本降到接近零，也许就能做一些非常惊人的事情，比如用大语言模型把互联网中的数字化人类知识全部提取出来，装进一台计算机里，再让它自己去理解这些知识。把整个互联网抓取下来装进一台电脑里，听上去很疯狂，但我们今天就是在这个方向上前进。\n从数据到知识 英文清理版 Gene sequencing is digitizing genes, but now with large language models we can go and understand the meaning of that gene. Amino acids, we digitized through mass spec. You know, you ask it, what is the meaning of it, summarize it for me, what is the meaning? This is no different than a hard, huge long page of genes. What is the meaning of that big long page of proteins? What is the meaning of that? We are on the cusp of all this. This is the miracle of what happened.\n中文翻译 基因测序其实就是在把基因数字化，但现在有了大语言模型，我们已经可以进一步理解这个基因到底意味着什么。氨基酸也可以通过质谱技术被数字化。你可以问它：“这是什么意思？给我总结一下。”这和一长页复杂的基因信息并没有本质区别。那一大页蛋白质到底意味着什么？我们现在正站在这一切的门槛上，这就是正在发生的奇迹。\n数据中心与未来算力 英文清理版 The chip that John just described weighs seventy pounds. It consists of thirty-five thousand parts. Eight of those parts came from TSMC. That one chip replaces a data center of old CPU systems. The savings because we compute so fast are incredible. It computes at data center scale.\nWhat’s going to happen in the next ten years? The computational capability for machine learning and deep learning will increase by another million times. And what happens when you do that? Today we kind of learn and then we apply it, but in the future the computer will watch videos, read text, and continuously improve itself through the training process, the inference process, and the application process. Those will become one.\nThe marginal cost of transportation has gone to zero. I can fly from here to New York relatively cheaply, though if it had taken a month I probably would never go. This is exactly the same in computing. We are going to take the marginal cost of computing down to approximately zero, and as a result we will do a lot more computation.\n中文翻译 John 刚刚描述的那颗芯片重达七十磅，由三万五千个零件组成，其中八个零件来自 TSMC。这样一颗芯片，实际上就替代了一个由旧式 CPU 系统组成的数据中心。因为计算速度大幅提升，带来的节省是惊人的。它已经是在数据中心规模上运算了。\n未来十年会发生什么？机器学习和深度学习的算力还会再提升一百万倍。那会带来什么结果？今天我们通常是先学习，再应用；但在未来，计算机会去看视频、读文本，并在训练、推理和应用过程中不断自我改进，这几个过程将逐渐合一。\n运输的边际成本已经降到了接近零。我可以相对便宜地从这里飞到纽约，但如果这趟路程要花一个月，我大概就不会去了。计算也是一样，我们会把计算的边际成本降到接近零，而结果就是，人类会去做更多计算。\n推理市场 英文清理版 There are recent stories saying that Nvidia will face more competition in the inference market than it has in the training market, but what we are really talking about is a single market. The question is whether there will be a separate training chip market and inference chip market.\nInference is an installed base problem. This is no different than somebody writing an application on an iPhone. The reason they do so is because the iPhone has such a large installed base. If you wrote an application for that phone, it can benefit everybody. In the case of Nvidia, our accelerated computing platform is the only accelerated computing platform that is literally everywhere.\nIf you write an application for inference and deploy that model on Nvidia architecture, it literally runs everywhere, so you can touch everybody and have greater impact. The problem with inference is really the installed base, and that takes enormous patience.\n中文翻译 最近有人说，Nvidia 在推理市场会面临比训练市场更多的竞争，但从本质上说，我们谈的其实还是同一个市场。问题在于，训练芯片市场和推理芯片市场会不会真的分成两个完全独立的市场。\n推理本质上是一个安装基数的问题。这和在 iPhone 上开发应用没有区别。之所以大家愿意为 iPhone 写应用，是因为它有巨大的装机量。你只要为这台手机写一个应用，就有机会服务所有人。对 Nvidia 来说，我们的加速计算平台是事实上无处不在的那一个。\n如果你写了一个推理应用，并把模型部署到 Nvidia 架构上，它几乎可以在所有地方运行，这样就能真正触达更多人，产生更大的影响。推理的问题核心，其实是安装基数，而这需要极大的耐心。\n科学与结构化数据 英文清理版 SQL was born in the nineteen sixties and IBM in the nineteen seventies in storage computing. Structured data is as important as it gets. There are hundreds of zettabytes of data being created every couple of years, but most of it is in structured databases. Wherever we can accelerate that, we can accelerate quantum physics, Schrödinger equations, fluids, particles, and lots and lots of code. What Nvidia is good at is the general field of accelerated computing.\n中文翻译 SQL 诞生于二十世纪六十年代，IBM 在七十年代推动了存储和计算的发展。结构化数据的重要性怎么强调都不为过。每过几年，人类都会创造出数百泽字节的数据，但其中大多数其实都在结构化数据库里。只要我们能把这一部分加速，就能加速量子物理、薛定谔方程、流体、粒子，以及大量代码的计算。Nvidia 擅长的，正是更广义的加速计算。\n与客户竞争 英文清理版 I want to apologize. I came across as a little competitive. I could have probably done that more artfully. I will next time. But he surprised me with a competitor. I thought I was in an economic forum. I had sent some questions to his team and asked whether he had looked at them. He said no, because he wanted to be spontaneous. Besides, he might start thinking about it.\n中文翻译 我想道个歉。我刚才听起来确实有一点竞争性的味道，这件事我本可以说得更委婉一些，下次我会注意。但他给我准备了一个竞争对手的问题，我本来以为自己是在参加一个经济论坛。我之前还把一些问题发给了他的团队，问他有没有看过，他说没有，因为他想保持即兴发挥。再说，他一旦开始想，可能就会开始认真分析了。\n让模型理解世界 英文清理版 When we talk about AI, there are certain properties that it must obey in the world. It has to create what is called a world model. We have to understand multimodality. There are all these other modalities: genes, amino acids, proteins, cells, which lead to organs and so on. We would like to have multimodal capabilities. Second is greater and greater reasoning capabilities. A lot of the things we already do, reasoning skills are encoded in common sense.\nWe already have questions and answers, but today we are mostly doing generative visualization. I am not spending a whole lot of time reasoning about the question. However, there are certain problems, like planning problems, where I am going, that is interesting, let me think about that. I am cycling it in the back, I am coming up with multiple plans, traversing a tree, maybe going through my graph, pruning my tree and saying this does not make sense.\n中文翻译 当我们谈 AI 时，它必须遵守现实世界中的一些属性。它需要建立所谓的“世界模型”。我们也必须理解多模态。除了文本之外，还有很多其他模态，比如基因、氨基酸、蛋白质、细胞，进一步又会导向器官等等。所以我们希望模型具备真正的多模态能力。第二点，是越来越强的推理能力。很多我们已经在做的事情，本质上都把推理技能编码在常识里。\n现在我们已经有问答能力了，但今天很多时候我们做的还是生成式内容输出。我并不会在每个问题上都花很多时间去推理。不过对于某些问题，比如规划类问题，我会想：这个有意思，让我想一想。然后我在后台不断循环，生成多个方案，像是在遍历一棵树，也可能是在图里搜索，再把不合理的分支剪掉。\n未来的知识交互 英文清理版 It would be great just as you can chat with GPT, you can chat with a PDF. You take a PDF file, it does not matter what it is. My favorite is when you take a PDF file of a research paper and load it into ChatGPT, then start talking to it. It is like talking to the researchers: what inspired this research, what problem does it solve, what was the breakthrough, what was the state of the art before then, what were the novel ideas. Just talk to it like a human.\n中文翻译 就像你可以和 GPT 聊天一样，未来你也可以和 PDF 聊天。你拿一个 PDF 文件，不管它是什么都可以。我最喜欢的场景，是把一篇研究论文的 PDF 放进 ChatGPT，然后直接和它对话。那感觉就像在和研究者本人交流：这项研究最初的灵感是什么？它解决了什么问题？关键突破在哪里？在它之前的技术水平是什么？有哪些新想法？你就像和一个人对话一样去问它。\n计算成本下降带来的结果 英文清理版 That miracle happened about a decade and a half ago. We saw it coming and took the whole company and shaped our computer, which was already driving the marginal cost of computing down to zero, and pushed it into this whole domain. As a result, in the last ten years, we reduced the cost of computing by one million times, the cost of deep learning by one million times.\nA lot of people said to me, “But Jensen, if you reduced the cost of computing by a million times, people buy less of it.” And it is exactly the opposite. We saw that if we could reduce the marginal cost of computing down to approximately zero, we might use it to do something insanely amazing.\nLarge language models can literally extract all of digital human knowledge from the internet and put it into a computer, and let it go figure out what the knowledge is. That idea of scraping the entire internet and putting it in one computer sounds crazy, but that is where we are.\n中文翻译 那个奇迹大约发生在十五年前。我们看到了它的到来，于是把整个公司都动员起来，把我们的计算机体系改造成现在这个样子。它本来就在把计算的边际成本往零压，我们又把它推进到这个全新的领域。结果就是，在过去十年里，我们把计算成本降低了一百万倍，也把深度学习的成本降低了一百万倍。\n很多人跟我说：“Jensen，如果你把计算成本降了一百万倍，人们会买得更少吧？”事实正好相反。我们发现，如果能把计算的边际成本降到接近零，就可以拿它去做一些极其惊人的事情。\n大语言模型可以真的把互联网上所有数字化的人类知识提取出来，放进一台计算机里，然后让它自己去理解这些知识。把整个互联网抓下来，再装进一台计算机里，这想法听起来很疯狂，但我们现在就在做这件事。\nH100 与数据中心 英文清理版 The chip that John just described weighs seventy pounds and consists of thirty-five thousand parts. Eight of those parts came from TSMC. We sell the world’s first quarter-million-dollar chip. But the system it replaced, the cables alone, cost more than the chip. That H100 and the cables connecting all those old computers, that is the incredible thing that we did. We reinvented computing, and as a result the marginal cost of computing went to zero.\nWe took this entire data center and shrunk it into this one chip. This one chip is really, really good at trying to figure out this form of computation called deep learning. It is really good at this thing called AI. The way that this chip works is magnificent. It weighs a lot, with miles and miles of cables, hundreds of miles of cables, and the next ones are coming as liquid cooled. It computes at data center scale.\n中文翻译 John 刚刚描述的那颗芯片重达七十磅，由三万五千个零件组成，其中八个零件来自 TSMC。我们卖的是世界上第一颗二十五万美元的芯片。但它所替代的那套系统，单是线缆的成本就比这颗芯片还高。那块 H100，加上连接所有旧计算机的线缆，就是我们做成的惊人之处。我们重新发明了计算，而结果就是计算的边际成本降到了零。\n我们把整个数据中心压缩进了这一颗芯片里。它非常擅长处理一种叫做深度学习的计算形式，也非常擅长我们今天所说的 AI。这颗芯片的工作方式非常了不起。它本身很重，系统里有成千上万米、甚至数百英里的线缆，而下一代很快就会采用液冷。它是在数据中心尺度上运算的。\n低预期与公司文化 英文清理版 One of my great advantages is that I have very low expectations. Most Stanford graduates have very high expectations, and you deserve to have high expectations because you came from a great school, you were very successful, you were at the top of your class, and you were surrounded by other incredible students.\nIn our company, I have learned to talk to people all the time. I write no reviews for any of them; I give them constant reviews, and they provide the same to me. My compensation for them is the bottom right corner of Excel, I just drag it down. Many of our executives are paid the same, exactly that: a dollar. I know it is weird, but it works. I do not do one-on-one meetings with them unless they need me. Then I will drop everything for them. I never have meetings with them just alone.\n中文翻译 我最大的优势之一，就是我的期待值很低。Stanford 的大多数毕业生往往期望值非常高，而你们也确实有资格拥有高期待，因为你们来自一所很棒的学校，你们非常成功，在班里总是最优秀的一批，而且身边都是同样出色的人。\n在我们公司里，我学会了一直和大家沟通。我不会给他们写正式评价，而是持续不断地给反馈，他们也同样持续给我反馈。我给他们的“薪酬”，就在 Excel 右下角，往下一拖就完了。我们很多高管的薪酬都是一样的，准确地说就是一美元。我知道这听起来很奇怪，但它有效。除非他们真的需要我，否则我不会单独和他们开一对一会议；一旦他们需要我，我会立刻放下手头所有事情去帮他们。我也不会和他们只在私下单独开会。\n高期待与韧性 英文清理版 You should have very high expectations. You naturally have very high expectations. But people with very high expectations have very low resilience, and unfortunately resilience matters in success. I do not know how to teach it to you except that I hope suffering happens to you. I was fortunate that I grew up with my parents providing a condition for us to be successful on the one hand, but there were plenty of opportunities for setbacks and suffering. To this day, I use the phrase pain and suffering inside our company with great glee, because that is how you build resilience.\n中文翻译 你们本来就应该有很高的期待。你们天然就会有很高的期待。但问题在于，期待很高的人，往往韧性很低，而不幸的是，韧性在成功中非常重要。我也不知道该怎么教你们这一点，除非希望你们真的经历一些苦难。我很幸运，成长过程中父母一方面给了我们成为成功者的条件，另一方面人生里也有很多挫折和受苦的机会。直到今天，我还会在公司里带着一点“开心”地说“pain and suffering”这个词，因为韧性就是这样锻炼出来的。\n解释 AI 目标 英文清理版 We are training these models to be multimodal, meaning we will learn from sounds, words, and vision, and we will just watch TV and learn, so on and so forth, just like all of us. The reason why that is so important is because we want AI to be grounded, grounded not just by human values. We had large language models before, but it was not until reinforcement learning from human feedback that the AI was grounded to something that we would call human intelligence.\nThere are certain properties that AI must obey in the world. It has to create what is called a world model. We have to understand multimodality. There are all these other modalities, like genes, amino acids, proteins, and cells, which lead to organs and so on. We would like to have multimodal capabilities. Second is greater and greater reasoning capabilities. A lot of the things we already do, reasoning skills are encoded in common sense.\nWe already have questions and answers, but today we are mostly doing generative visualization. I am not spending a whole lot of time reasoning about the question. However, there are certain problems, like planning problems, where I am going, “That is interesting, let me think about that.” I am cycling it in the back, coming up with multiple plans, traversing a tree, maybe going through my graph, pruning my tree, and saying this does not make sense.\nThat long-thinking AI is not good at today. Everything that you prompt into ChatGPT gets a response instantaneously. We would like to prompt something into ChatGPT, give it a mission statement, give it a problem, and for it to think a while. That kind of system, what computer science calls system two thinking, long thinking, planning, reasoning, those kinds of problems, I think we are working on them, and I think you can see some breakthroughs.\nAnd if you ask me, “Jensen, AI is a list of illicit tests,” the answer is that an engineer can only know whether we have a specification and whether we know what the definition of success is. We are not sure yet how to specify all of human intelligence, and therefore it is hard to achieve as an engineer. But we are endeavoring to make it better and better.\n中文翻译 我们正在训练这些模型，让它们具备多模态能力，也就是从声音、文字、视觉中学习，就像我们自己会看电视、听声音、读文字并学习一样。之所以这很重要，是因为我们希望 AI 具有“落地性”，不仅仅由人类价值观去约束。我们以前已经有大语言模型了，但直到出现基于人类反馈的强化学习，AI 才真正被“锚定”到我们可以称之为人类智能的东西上。\nAI 必须在现实世界中遵守某些属性。它需要建立所谓的世界模型。我们必须理解多模态。除了这些模态之外，还有很多其他模态，比如基因、氨基酸、蛋白质、细胞，进一步又会导向器官等等。所以我们希望模型拥有真正的多模态能力。第二点，是越来越强的推理能力。我们已经在做的很多事情，本质上都把推理技能编码在常识里。\n现在我们已经有问答能力了，但今天很多时候我们做的还是生成式可视化。我不会在每个问题上都花太多时间推理。不过对于某些问题，比如规划类问题，我会想：“这个有意思，让我想一想。”然后我在后台不断循环，生成多个方案，像是在遍历一棵树，也可能是在图里搜索，再把不合理的分支剪掉。\n这种长思考型 AI 今天还不够好。你现在往 ChatGPT 里提问，它几乎会立刻返回答案。我们希望未来你给它一个任务、一个问题，它能先想一会儿。这类系统，也就是计算机科学里说的 system two thinking，长思考、规划、推理这一类问题，我们正在推进，也已经能看到一些突破。\n如果你问我：“Jensen，AI 是一系列非法测试吗？”那我的回答是，工程师只能知道我们有没有规格说明，能不能定义什么叫成功。我们到现在也还不完全知道该如何完整描述人类智能，所以作为工程目标来说这很难。但我们一直在努力，把它做得越来越好。\n长思考与规划 英文清理版 Today, when we prompt ChatGPT, we get a response instantaneously. But in the future we would like to prompt something into ChatGPT, give it a mission statement, give it a problem, and let it think for a while. That kind of system, what computer science calls system two thinking, long thinking, planning, reasoning, those are the kinds of problems we are working on. I think you can already see some breakthroughs.\nWhen I am reasoning about a planning problem, I cycle it in the back, come up with multiple plans, traverse a tree, maybe go through my graph, prune the tree, and say this does not make sense. Then I simulate it in my head and maybe do some calculations and so on. That long-thinking AI is not good at today, but that is the direction we want.\n中文翻译 今天我们往 ChatGPT 里提问时，它几乎是立刻给出答案。但未来我们希望，你给它一个任务、一个问题，让它先想一会儿。这类系统，也就是计算机科学里说的 system two thinking，长思考、规划、推理这一类问题，正是我们正在做的。我觉得现在已经能看到一些突破了。\n如果我在思考一个规划问题，我会先在后台循环，生成多个方案，像是在遍历一棵树，也可能是在图里搜索，再把不合理的分支剪掉。然后我在脑海里模拟，做一些计算等等。今天的长思考型 AI 还不够成熟，但这正是我们想要前进的方向。\n生成式未来 英文清理版 What is written by someone, created by someone, is basically pre-recorded. All the words, all the videos, all the sound, everything that we do is retrieval-based. It was pre-recorded. Every modality that you know today is basically pre-recorded. In the future, almost everything will be generated.\nWhen you and I ask about the economy, we probably mean very different things and in very different contexts. In the future, the system will understand that context and generate exactly the right information for you. Most computing will be generative. Today, one hundred percent of content is pre-recorded. In the future, a hundred percent of content will be generative. The question is how that changes the shape of computing.\n中文翻译 今天由人写下、由人制作的内容，本质上都可以算是“预先录制”的。无论是文字、视频还是声音，几乎所有我们现在接触到的内容，都是检索式的、预先存在的。你今天看到的各种模态，本质上也都可以看作是预先录制的内容。而在未来，几乎一切都会变成生成式的。\n当你和我问“经济”这个词时，我们心里想的东西其实可能完全不同，所处的语境也完全不同。未来系统会理解这种语境，并为你生成刚刚好的信息。大多数计算都会变成生成式。今天，百分之百的内容都是预先录制的；未来，百分之百的内容都会变成生成式。问题在于，这会如何改变计算的形态。\n编程的变化 英文清理版 No, not even a little bit. The number of coders in the world will surely continue to be important, and Nvidia needs coders. However, in the future, the way you interact with the computer is not going to be C++. Mostly for some of us that is true, but for you, why program in Python? In the future, you will tell the computer what you want, and the computer will help you. If you do not like the answer the first time, you can fine-tune it and get better and better results.\nYou can even ask it to write the program altogether to generate that result in the future. My point is that programming has changed in a way that is probably less valuable. On the other hand, because of artificial intelligence, we have closed the technology divide of humanity today.\n中文翻译 不，完全不是这样。世界上的程序员数量依然会很重要，Nvidia 也仍然需要程序员。不过在未来，你和计算机交互的方式不会再是 C++ 这种传统方式了。至少对我们中的一部分人来说确实如此，但对你们来说，为什么还要用 Python 去“编程”呢？未来你只要告诉计算机你想要什么，它就会帮你完成。如果第一次结果不满意，你还可以继续调整，让结果越来越好。\n你甚至可以让它直接帮你把程序写出来，从而生成最终结果。我的意思是，编程这件事已经发生了变化，传统编程方式的重要性可能没有以前那么高了。另一方面，人工智能正在帮助我们缩小人类之间的技术鸿沟。\nPrompt Engineering 英文清理版 It is called prompt engineering, how you interact with people, how you interact with computers, how you make a computer do what you want it to do, how you fine-tune the instructions with that computer. There is an artistry to that. For example, most people are surprised by this, but if you ask Midjourney to generate a picture of a puppy on a surfboard in Hawaii at sunset, it generates one. Then you say, make it cuter, and it comes back cuter. You say, no, cuter than that, and it comes back again. That capability exists in a computer in the future. If you do not like the answer the first time, you can ask it again in a way that gives you better and better results.\nWe all can program computers. You all know how to prompt the computer to make it do things. Look at YouTube and look at all the people using prompt engineering. Kids are making amazing things and they are not writing programs. They are just talking to ChatGPT. They know that if I tell it to do this, it will do that. It is no different than interacting with people in the future. That is the great contribution the computer science industry has made to the world. We closed the technology divide.\n中文翻译 这叫做 prompt engineering，也就是你如何与人交互、如何与计算机交互、如何让计算机做你想让它做的事，以及如何不断细化对它的指令。这件事本身是有技巧的。比如很多人会惊讶，但如果你让 Midjourney 生成一张“海边冲浪板上的小狗、黄昏时分”的图片，它真的会生成。然后你说“再可爱一点”，它就会变得更可爱；你说“再可爱一点”，它还能继续调整。未来的计算机就会具备这种能力。如果第一次答案不满意，你可以换一种方式继续问，得到越来越好的结果。\n我们每个人都可以编程。你们其实都知道怎么通过 prompt 让计算机做事情。去看 YouTube 上那些使用 prompt engineering 的人，很多孩子做出了惊人的东西，但他们并没有在写传统程序，他们只是在和 ChatGPT 对话。他们知道，只要我让它做这个，它就会去做那个。未来这和人与人交互没有区别。这就是计算机科学行业为世界做出的巨大贡献，我们缩小了技术鸿沟。\n数字主权 英文清理版 We first of all have to understand these policies and stay agile so that we can comply with them. On the one hand, it limits our opportunity in some places, and it opens up opportunities in others. In the last six to nine months, every single country and every single society has awakened to the fact that they have to control their own digital intelligence. India cannot outsource its data so that some country transforms that digital data into India’s intelligence and imports that intelligence back to India. That awakening is sovereign AI.\n中文翻译 首先，我们必须理解这些政策，并保持足够灵活，确保能够遵守它们。一方面，这会限制我们在某些地方的机会；另一方面，它也会在其他地方打开新的机会。过去六到九个月里，每一个国家、每一个社会都意识到，他们必须控制自己的数字智能。印度不能把自己的数据外包出去，让别的国家把这些数字数据转化成印度的智能，再把这种智能“进口”回印度。这种觉醒，就是主权 AI，也就是 sovereign AI。\n地缘政治与主权 AI 英文清理版 Geopolitics, on the one hand, limited opportunities, but it created enormous opportunities elsewhere. Every country, every society, now realizes that they have to invest in their own sovereign AI. They have to protect their language, protect their culture, and protect their own industries. That awakening happened in the last six to nine months. The first part was that we have to be mindful about safety, and the second part was that we all have to do this.\n中文翻译 地缘政治一方面限制了一些机会，另一方面也在别处创造了巨大的机会。现在每一个国家、每一个社会都意识到，他们必须投资自己的主权 AI。他们必须保护自己的语言、保护自己的文化，也要保护自己的产业。这种觉醒大概发生在过去六到九个月里。第一层意思是我们必须重视安全，第二层意思是我们每个人都必须这么做。\n最后问答 英文清理版 There are more horizontal solutions today, but we are willing to customize the answers. The reason the bar is relatively high is because each generation of our platform has a GPU, a CPU, a networking processor, a switch, and two types of switches. I build five chips for one generation, and people think it is one chip, but it is really five different chips. Each one of those chips costs hundreds of millions of dollars just to get to launch, what we call tape-out. Then you have to put them into a system, add networking, transceivers, optics, and a mountain of software. It takes a lot of software to run a computer as big as this room.\nIf the customization is too different, you have to repeat the entire R\u0026amp;D process. However, if the customization leverages everything and adds something to it, then it makes a great deal of sense. Maybe it is a proprietary security system, maybe it is a confidential computing system, maybe it is a new way of doing numerical processing that could be extended. We are very open-minded to that. Our customers know that I am willing to do all that, and they recognize that if you change it too far, you have basically reset nearly a hundred billion dollars of work that it took us to get here. They want to leverage our ecosystem to the extent that it can be done. I am very open to it.\n中文翻译 今天市场上更多是横向的解决方案，但我们也愿意为客户定制答案。之所以门槛很高，是因为我们平台每一代产品都包含 GPU、CPU、网络处理器、交换机，以及两类交换芯片。我们一代产品其实要做五颗芯片，但外界常常以为只有一颗，其实是五颗完全不同的芯片。每一颗芯片从设计到流片，也就是 tape-out，成本都要几亿美元。之后你还得把它们组装成一个系统，再加上网络、收发器、光模块，以及大量软件。要运行一台像这个房间这么大的计算机，所需的软件量非常大。\n如果定制需求和原有架构差异太大，那就等于要把整个研发流程重新来一遍。但如果这种定制是在充分利用现有能力的基础上，再增加一些新东西，那就非常有意义。也许是一个专有安全系统，也许是一个保密计算系统，也许是一种新的数值计算方式，而且这种方式还可以继续扩展。对于这些方向，我们都非常开放。我们的客户知道我愿意做这些事情，也明白如果改动得太远，基本上就相当于把我们花了将近一千亿美元才建立起来的生态重新推倒重来。所以他们通常希望尽可能利用我们的生态体系。我对此一直很开放。\n结语 英文清理版 I think with that we need to wrap up. Thank you so much to John and Jensen.\n中文翻译 我想我们可以就此收尾了。非常感谢 John 和 Jensen。\n","permalink":"https://june6699.github.io/posts/%E9%BB%84%E4%BB%81%E5%8B%8B-2024-stanford-%E5%8F%91%E8%A8%80/","summary":"\u003cp\u003e\u003ca href=\"https://www.youtube.com/watch?v=cEg8cOx7UZk\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eKeynote by NVIDIA CEO Jensen Huang at 2024 SIEPR Economic Summit\u003c/a\u003e\n\u003c/p\u003e\n\u003ch3 id=\"开场与主持人介绍\"\u003e开场与主持人介绍\u003c/h3\u003e\n\u003ch4 id=\"英文清理版\"\u003e英文清理版\u003c/h4\u003e\n\u003cp\u003eWelcome back everyone, after the short break. I know that many of you are looking forward to hearing from our next speaker, Jensen Huang. Jensen is at the cutting edge of artificial intelligence and all of the innovation, technology, and human capital that is needed to support it. My good friend and superb colleague John Shoven is going to introduce Jensen. I hope he is here somewhere, so I am just going to keep talking until the two of them have a conversation and then take some of your questions.\u003c/p\u003e","tags":["生活","生活/文章"],"title":"黄仁勋 2024 Stanford 发言整理"},{"content":"阅读说明：本文按排障顺序记录，从“为什么改了代码域名却没变”开始，直到把自动部署链路真正跑通。\n1、问题起点 前几天我改了 simple-live-sync-site 这个 Cloudflare Workers 项目，本地也已经 push 到 GitHub 了，但线上这个地址：\nhttps://simple-live-sync.3439394104.workers.dev/ 内容还是旧的。\n一开始很容易怀疑是缓存、浏览器没刷新、Workers 边缘节点没更新，或者代码本身没生效。可我后来查了一圈，结论其实很朴素：\n代码确实改了； 但“Git push”并不自动等于“Cloudflare 已部署”； 我缺的是一条真正从 Git 仓库跑到 Worker 发布的自动化链路。 这篇就是把这条链路补上的过程。\n2、先看项目原本是怎么工作的 这个仓库是一个很标准的 Cloudflare Worker 项目，入口在 src/index.ts，发布脚本只有一条：\n{ \u0026#34;scripts\u0026#34;: { \u0026#34;deploy\u0026#34;: \u0026#34;wrangler deploy\u0026#34;, \u0026#34;typecheck\u0026#34;: \u0026#34;tsc --noEmit\u0026#34; } } 也就是说，它本质上是靠 wrangler deploy 发布的，不是“push 到 GitHub 就自动上线”。\n项目里还有一个很容易误导人的地方：首页响应带了缓存头。\nfunction html(body: string, status = 200): Response { return new Response(body, { status, headers: { \u0026#34;content-type\u0026#34;: \u0026#34;text/html; charset=utf-8\u0026#34;, \u0026#34;cache-control\u0026#34;: \u0026#34;public, max-age=120\u0026#34; } }); } 所以即便部署已经成功，首页也可能短时间内看起来像没变。这个坑很常见，尤其是人会先盯着 /，忘了 /health 才是更干净的验证点。\n3、真正缺的是什么 我后来确认，问题不是 Cloudflare 不会部署，而是部署触发方式没有接好。\n也就是这条链路原来断在这里：\n本地改代码 -\u0026gt; push GitHub 但没有自动接到：\npush GitHub -\u0026gt; Cloudflare 自动构建 -\u0026gt; wrangler deploy -\u0026gt; workers.dev 更新 所以我要做的事情很明确：\n让 Cloudflare 的 Git 集成知道该怎么构建和部署； 给仓库补一个兜底的 GitHub Actions 自动部署； 避开首页缓存，直接用 /health 验证结果。 4、Cloudflare 这边怎么配 我先在 Cloudflare Worker 的 设置 -\u0026gt; 构建 里把 Git 集成配置改对了。\n关键项只有三个：\n构建命令：npm run typecheck 部署命令：npx wrangler deploy 生产分支：master 这里最重要的是别填错构建命令。因为这个仓库里原本并没有 npm run build 这个脚本，只有 typecheck 和 deploy。如果你让 Cloudflare 去跑一个不存在的命令，部署自然不会成功。\n改完之后，Cloudflare 才知道“每次 master 更新后该做什么”。\n5、为什么我又补了一层 GitHub Actions 单靠 Cloudflare 的 Git 集成其实已经够用，但我还是顺手补了一个 GitHub Actions，当作备用和可见化的部署链路。\n新增文件是：\n.github/workflows/deploy.yml 它做的事很直接：\n监听 master 分支 push； 安装依赖； 跑 npm run typecheck； 最后只输出提示，不再重复部署。 这样一来，就算 Cloudflare 那边的 Git 集成某次没触发，我也还有一条明确的自动部署路径。\n后来我又把这条 GitHub Actions 收窄了一下，只保留检查，不再直接执行 wrangler deploy。原因很简单：真正发布已经由 Cloudflare 的 Git 集成接管了，GitHub 这边再发一次反而容易让人看不清到底是谁在负责上线。\n6、最后怎么验证真的生效了 验证时我没有只看首页，而是直接看这个接口：\nhttps://simple-live-sync.3439394104.workers.dev/health?format=json 原因很简单：\n它返回的是 JSON； 响应头是 cache-control: no-store； 比首页更不容易被缓存误导。 只要这个接口里版本号、时间戳、状态都更新了，就说明 Worker 真的已经换成新版本了。\n7、这次踩到的坑 这次最容易误判的地方有三个：\n7.1 以为 push 就会自动发布 不会。至少在这个仓库最初的状态里不会。\nGitHub 负责保存代码，Cloudflare 负责跑部署，这两边必须有明确的连接点。\n7.2 以为首页没变就是部署没成功 也不一定。首页有缓存头，短时间内看旧内容是正常的。\n7.3 以为部署配置里的 build 命令可以随便写 不行。命令必须和仓库里的脚本一致，不然构建阶段就会卡住。\n8、结论 这次能成功，核心不是某个神奇技巧，而是把链路补完整了：\n本地改代码 -\u0026gt; push 到 master -\u0026gt; Cloudflare 触发构建 -\u0026gt; 执行 wrangler deploy -\u0026gt; workers.dev 更新 一开始我看到的是“页面没变”，后来我真正修的是“部署没被触发”。\n这类问题的经验也很简单：如果你确认代码没错，却总感觉线上没更新，就先别急着怀疑缓存和浏览器，先去找“发布按钮”到底有没有被按到。\n","permalink":"https://june6699.github.io/posts/cloudflare-workers-%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E8%AE%B0%E5%BD%95/","summary":"\u003cp\u003e阅读说明：本文按排障顺序记录，从“为什么改了代码域名却没变”开始，直到把自动部署链路真正跑通。\u003c/p\u003e\n\u003ch2 id=\"1问题起点\"\u003e1、问题起点\u003c/h2\u003e\n\u003cp\u003e前几天我改了 \u003ccode\u003esimple-live-sync-site\u003c/code\u003e 这个 Cloudflare Workers 项目，本地也已经 \u003ccode\u003epush\u003c/code\u003e 到 GitHub 了，但线上这个地址：\u003c/p\u003e","tags":["技术","技术/运维","技术/前端"],"title":"让 Cloudflare Workers 在 push 后自动更新：我怎么把 Simple Live Sync 接进 Git 部署链路"},{"content":"这两天我把博客的发布链路重新理了一遍，目标其实很朴素：我在 Windows 本地改完代码，只 push 一次，GitHub Pages 能更新，www.june6699.top 也能跟着更新。\n之前的问题不复杂，就是链路断过几次。页面看起来像是“没同步”，其实不是代码没发出去，而是两边发布的方式没有统一起来。\n先定一条原则 我最后只保留一份源码，一份构建产物。\n源码还是老规矩，本地改，push 到 GitHub。真正上线的时候，不再分开维护两套内容，而是让 Hugo 先构建出同一份 public/，然后：\nGitHub Pages 用这份 public/ 服务器上的 top 域名也同步这份 public/ 这样就不会出现“GitHub 站已经新了，top 还停在旧页面”的情况。\n现在这条链路长什么样 我现在的流程是这样的：\nWindows 本地改代码 -\u0026gt; push 到 GitHub main -\u0026gt; GitHub Actions 跑 Hugo 构建 -\u0026gt; 生成同一份 public/ -\u0026gt; 发布到 GitHub Pages -\u0026gt; 再用 SSH rsync 到 june-server -\u0026gt; www.june6699.top 读取服务器上的 public/ 这里最关键的一点是：top 域名不是单独再做一套部署逻辑，它只是跟着那份 public/ 走。\n为什么这样最稳 因为“同步”这件事，最怕的不是慢，是分叉。\n如果 GitHub Pages 一套构建，服务器上又手动拷一套文件，时间一长就会开始出现这些毛病：\n文章顺序不一致 某篇文章只在一个域名上可见 图片路径偶尔失效 你自己也记不清到底哪边是最新 我不想再给自己留这个坑，所以干脆把部署出口收拢成一份构建结果。\nGitHub Actions 里做了什么 仓库里的工作流现在会在 main 分支 push 后自动跑：\ncheckout 代码 安装 Hugo npm run build 把生成的 public/ 上传给 GitHub Pages 再把同一份 public/ 发到服务器 这一步里，GitHub Pages 和服务器同步用的是同一个 artifact。也就是说，只要这次构建成功，两边看到的内容理论上就是同一批。\n服务器那边只做一件事 服务器不再自己维护仓库，也不再自己改源码。\n它只负责接收同步结果，然后对外提供 www.june6699.top。这样服务器就退回成一个很干净的角色：被同步者，不是编辑者。\n这点我挺喜欢，省心。\n动态密钥怎么放 站里还有一块动态内容，访问时要走 GitHub 的环境变量去做验证。\n我没有把这类密钥写死在仓库里，而是继续放在 GitHub Secrets 里，让构建和运行时按需读取。这样有两个好处：\n密钥不进代码仓库 本地、GitHub Pages、服务器这三边的发布逻辑不会互相污染 也就是说，内容可以同步，密钥不要同步到明面上。\n我现在怎么判断同步没问题 我不再只看首页。\n首页有缓存，视觉上很容易骗人。真要确认同步，我会直接看最新文章、列表页和实际发布后的文件内容。只要这几处都一致，基本就说明两边已经在吃同一份结果了。\n后来我又把服务器上的 nginx 配了一遍，top 域名能正常访问以后，这条链路才算真正闭上。\n这次顺手学到的一点 网站部署最容易出的问题，往往不是“大故障”，而是“某一步看起来没什么，但实际上链路已经分叉了”。\n所以这次我最后做的不是更复杂的系统，而是更简单的约束：\n源码只维护一份 构建只产出一份 发布只认同一个 public/ 这样一来，GitHub Pages 和 www.june6699.top 就能老老实实地一起更新。\n","permalink":"https://june6699.github.io/posts/github-pages-%E5%92%8C-top-%E5%9F%9F%E5%90%8D%E6%80%8E%E4%B9%88%E4%BF%9D%E6%8C%81%E5%90%8C%E6%AD%A5/","summary":"\u003cp\u003e这两天我把博客的发布链路重新理了一遍，目标其实很朴素：我在 Windows 本地改完代码，只 push 一次，GitHub Pages 能更新，\u003ccode\u003ewww.june6699.top\u003c/code\u003e 也能跟着更新。\u003c/p\u003e","tags":["技术","技术/运维","技术/博客"],"title":"让 GitHub Pages 和 top 域名保持同步：我把同一份 public 发到了两边"},{"content":"最近看到一个医学学长的专本硕博博后的励志故事，本文转自世界只会以你最好的那次来定义你#山东专升本#专科的逆袭#师大专升本#博士后#何世豪 - 抖音 。\n我是2013级山东医学高等专科学校临床医学专业，专科生\n我是2016级泰山医学院，兼山东第一医科大学临床医学专业，本科生\n我是2018级首都医科大学神经外科，专业型硕士研究生\n我是2021届首都医科大学神经外科，专业型博士研究生\n我是2022届美国斯坦福大学 Gary K.Steinberg 教授，实验室高级访问学者，斯坦福医学院神经外科，联合培养博士\n我是2024级中国医学科学院，北京协和医院神经外科，博士后\n学弟学妹们，你们加油\n世界是只会以最好的那次来定义你和评价你\n未来我们还要去看天一样高的山，去看最广阔的河，去见没见过的峡湾和冰川\n最好的起点就是现在，决定命运的只有一个，就是你自己\n","permalink":"https://june6699.github.io/posts/%E6%9C%80%E5%A5%BD%E7%9A%84%E8%B5%B7%E7%82%B9%E5%B0%B1%E6%98%AF%E7%8E%B0%E5%9C%A8/","summary":"\u003cp\u003e最近看到一个医学学长的专本硕博博后的励志故事，本文转自\u003ca href=\"https://www.douyin.com/video/7651413673600093494\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e世界只会以你最好的那次来定义你#山东专升本#专科的逆袭#师大专升本#博士后#何世豪 - 抖音\u003c/a\u003e\n。\u003c/p\u003e","tags":["随笔","生活/文章","毕业季"],"title":"最好的起点就是现在"},{"content":"盛夏的午后，热浪裹挟着整座城市。柏油路被烈日晒得发烫，蒸腾起淡淡的热气，晃得人睁不开眼。道旁的梧桐枝叶恹恹低垂，褪去了春日的繁茂生机，连风都变得慵懒凝滞，只剩扑面而来的滚滚燥热。我顶着烈日走到蜜雪冰城门口，推门而入的瞬间，清甜的奶味冷气扑面而来，顺着衣领漫遍全身，稍稍驱散了满身的暑气与烦闷。\n店内排队的人不多，我身前站着寻常的一家三口。年轻的妻子束着简单的低马尾，细碎的汗珠凝在鬓角，透着夏日独有的温润烟火气。她手里早已握着一支原味甜筒，不急不缓地小口吃着，嘴角沾了一点淡淡的奶油，自己浑然不觉，侧头温柔地和身旁的丈夫闲谈。眉眼弯弯，笑意浅浅，眼底盛着细碎的温柔，藏着平凡日子里的安稳欢喜。\n她身侧的小女儿扎着俏皮的羊角辫，乖乖仰着小脸，一瞬不瞬地盯着柜台。圆圆的眼眸紧紧跟着机器转动的轨迹，看着雪白的奶油一层层裹满脆筒，小手轻轻攥着妈妈的裙摆，安静又期待，满心都是对这份夏日甜意的期盼。\n店员手脚麻利，转瞬就旋好了一支饱满的冰淇淋，轻轻递了出来。站在外侧的丈夫抬手稳稳接住。\n那一刻，心底生出一种根深蒂固的本能预判。我下意识以为，他会立刻弯腰，将这支冒着微凉冷气的甜筒，稳稳递到满心期待的女儿手中。\n从小到大，我们见过太多这样的画面。为人父母，似乎天生就自带退让的属性，习惯性把最新鲜、最美好、最极致的甜，悉数留给孩子。我早已默认了这套世俗的相处常态，静静等着这场意料之中的温柔谦让。\n可他没有。\n男人没有看向脚下的女儿，反而抬眼望向身侧笑意盈盈的妻子，指尖轻轻转动脆筒，自然又从容地低头，咬下了冰淇淋最顶端的那一点尖尖。\n那一口，是整支冰淇淋的精髓。刚出炉的奶油蓬松绵密，凉意最足、甜度最纯粹，没有脆筒的干涩，只有入口即化的清甜。就像草莓最软糯的果蒂，西瓜最甘甜的中心瓤，是一份甜品里，最珍贵、最让人惦念的一口美好。\n我站在队伍里，骤然心头一热，莫名生出几分窘迫。比头顶盛夏的烈日更灼人的，是心底突如其来的自省。\n我一直以为自己早已读懂亲情的真谛，看过无数摒弃愚孝、拒绝溺爱的文字，也始终认同，父母首先是自己，而后才是父母。可真正面对生活的细碎瞬间时，固化的思维还是悄悄作祟。\n我早已在潜移默化中默认了父母的“牺牲式付出”。默认他们成为父母的那一刻，就要收起自己的喜好，压抑自己的欲望，把所有美好无条件馈赠给孩子。默认他们不配争抢一口甜，不配偏爱一份小美好，连对一支冰淇淋尖尖的贪恋，都是不合时宜的奢望。\n可我忘了，褪去父母的身份，他们只是平凡的普通人。他们也怕热，也贪甜，也会为夏日一口冰凉的奶油心生欢喜，也会惦记那份独一无二的舌尖美味。为人父母，从不是一场彻底的自我消耗，更不是一辈子的自我牺牲。\n思绪浮沉间，店员又递出了第二支崭新的冰淇淋。\n小女孩瞬间眼亮，亮晶晶的眸子盛满星光，立刻踮起脚尖，稳稳接过属于自己的甜筒。她迫不及待咬上一大口，白白的奶油沾在鼻尖，憨态可掬。丈夫温柔俯身，抬手轻轻拭去她鼻尖的奶油，妻子站在一旁浅笑盈盈。阳光透过玻璃落在三人身上，光影温柔，裹挟着淡淡的奶香，平凡又治愈。\n原来最好的亲子与家庭之爱，从来不是单方面的妥协与退让，更不是自我感动式的牺牲。\n这家人的幸福简单又通透：妻子安然享受手中的甜，丈夫随心偏爱舌尖的尖尖，女儿拥有一整支完整的欢喜。三支冰淇淋，三份不被辜负的美好，没有人需要委屈自己，没有人需要刻意谦让。大家并肩而立，在燥热的夏日里，各自拥有专属的清甜与凉意。\n真正温暖的亲情，大抵就是这般模样。不必为了爱意割舍热爱，不必为了成全孩子委屈自己。我们可以坦然守护彼此，也可以坦然善待自己，两两相伴，各自圆满。\n走出门店时，我咬了一口自己的冰淇淋。冰凉的奶油漫过舌尖，清甜散去满身燥热。晚风拂来，裹挟着夏日独有的温热气息，混着淡淡的奶香。这一刻忽然发觉，寻常人间的细碎美好，从来都藏在这些不刻意、不勉强、互不亏欠的温柔瞬间里。\n","permalink":"https://june6699.github.io/posts/%E5%86%B0%E6%B7%87%E6%B7%8B%E7%9A%84%E5%B0%96%E5%B0%96/","summary":"\u003cp\u003e盛夏的午后，热浪裹挟着整座城市。柏油路被烈日晒得发烫，蒸腾起淡淡的热气，晃得人睁不开眼。道旁的梧桐枝叶恹恹低垂，褪去了春日的繁茂生机，连风都变得慵懒凝滞，只剩扑面而来的滚滚燥热。我顶着烈日走到蜜雪冰城门口，推门而入的瞬间，清甜的奶味冷气扑面而来，顺着衣领漫遍全身，稍稍驱散了满身的暑气与烦闷。\u003c/p\u003e","tags":["随笔","生活/文章"],"title":"冰淇淋的尖尖"},{"content":"最近刷到抖音博主“李呀李嘉图”的一段随笔，里面有一句话特别戳人：\n等你读懂我的隐喻，我已经走了很远的路了。\n读到这里，像是忽然被拉回了很久以前。那时候我们还在用 QQ，头像要精挑细选，空间背景要反复更换，个性签名更像一块小小的告示牌。明面上只是几句歌词、几句古诗、几句故作深沉的话，背后却藏着一整颗不敢直说的心。\n中学时代大概是人这一生最擅长用隐喻的年纪。喜欢一个人，不好意思讲，就把名字藏进藏头诗里；想被关心，又不愿意显得脆弱，就换一条很冷的签名；明明只是想让某个人点进空间多看一眼，却要把话写得像全世界都在下雨。\n那时我们总觉得，真正懂自己的人，一定能看懂这些拐弯抹角。可长大后才发现，很多隐喻并不是给别人看的，而是给那一刻的自己一个安放情绪的地方。\n一、QQ 签名是青春期的树洞 以前换签名，常常不是因为这句话有多好，而是因为它刚好能替自己说一句不敢说的话。\n想念一个人，就换成“断桥是否下过雪”；和人闹别扭，就换成“相濡以沫，不如相忘于江湖”；喜欢而不得，就从歌词里翻出一句模棱两可的告白，既希望对方看懂，又害怕对方真的看懂。\n这种心情现在回头看，当然有一点中二。可中二并不等于可笑。那个年纪的人，表达能力还没有长好，自尊心却已经很敏感；明明满腹心事，却不知道怎样把它们说得体面。于是只好借别人的句子，借古人的诗，借一首歌的副歌，把自己的心事包装成一句看上去很酷的话。\n那不是成熟的表达，却是当时能拿出来的全部勇气。\n有些人会说，这不就是自我感动吗？好像也没错。可是青春里很多深情，本来就先发生在自己的世界里。你为一句签名想了很久，为一个标点犹豫半天，为了让它既像写给所有人、又像只写给那个人，反复删改。对方也许从来没发现，可那个下午，你确实认真地爱过、期待过、幻想过。\n这份认真不一定能抵达别人，却真实地抵达过自己。\n二、隐喻最残忍的地方，是它不负责送达 暗恋里最常见的误会，是我们总把“我写了”当成“我表达了”。\n可事实并不是这样。一条签名再用心，对方看到时，也可能只觉得那是你最近喜欢的一句歌词。一首藏头诗再巧，对方也可能从头到尾没有按你设定的方式去读。你把“我喜欢你”拆成偏旁部首，藏进每一个停顿里，可对方并没有义务拿着放大镜来破译。\n更微妙的是，有时候对方其实看懂了。\n看懂了头像为什么忽然换掉，看懂了歌单里那首歌为什么循环，看懂了朋友圈那句没头没尾的话是在写谁。可看懂之后呢？难道要主动问一句：“你这条签名是不是写给我的？”难道要替你把那句没有说出口的喜欢说完？\n这就是隐喻的尴尬。它既想被看见，又给自己留了退路；既想靠近，又不愿承担真正靠近后的后果。它把最重的心意交给最轻的形式，然后期待对方替自己完成最后一步。\n所以很多暗恋才会变成一个人的狂欢。心动是真的，忐忑是真的，欢喜和失落也都是真的，只是这些东西大多发生在自己的内心剧场里。对方偶尔经过，甚至不知道自己已经在别人的故事里演了很久。\n三、“相思相望不相亲”，古人也懂这种遥远 这种看得见、够不着，明明相思却不能相亲的遗憾，古人早就写过。纳兰性德《画堂春·一生一代一双人》里有几句，放在这里尤其贴切：\n一生一代一双人，争教两处销魂。\n相思相望不相亲，天为谁春？\n浆向蓝桥易乞，药成碧海难奔。\n若容相访饮牛津，相对忘贫。\n清·纳兰性德《画堂春·一生一代一双人》\n明明像是一生一世里注定相守的一双人，却偏偏要分在两处，各自神伤。日日相思，遥遥相望，却不能真正靠近，那么春天再来，又像是为了谁而来呢？蓝桥求浆尚且容易，可就算仙药炼成，也难像嫦娥那样奔向碧海青天。若真能像牛郎织女一样渡过天河相见，哪怕相对清贫，也甘愿如此。\n“相思相望不相亲”这七个字很狠。相思，说明心还在；相望，说明距离并非完全断绝；可“不相亲”，一下就把所有可能都挡住了。\n它不是彻底失去，也不是从未相遇，而是明明知道彼此存在，却无法把这份知道变成真正的靠近。放到年少的暗恋里，也很像：你看得到那个人在线，看得到 TA 的动态，看得到 TA 听了什么歌、去了哪里、和谁说笑，却始终没有办法把那句最重要的话说出口。\n于是春天来了也没用，铃声响了也没用，空间访问记录多了一个名字也没用。你真正想要的不是被看见，而是被回应；不是别人读懂你的隐喻，而是有人愿意接住隐喻背后那颗心。\n四、真正的心意，后来都要学会不用隐喻 长大后我们才慢慢明白，关系里最珍贵的东西，往往不是猜。\n最让人难过的也许正在这里：TA 的喜欢，我只能靠猜；TA 的不喜欢，却处处有迹可循。回消息时越来越短的句子，聊天里越来越少的主动，明明在线却迟迟没有回应，热闹里也很少把目光落到你身上。喜欢像一道需要反复解题的谜，不喜欢却像生活里不断亮起的小提示，只是那时候的我们常常不愿意承认。\n于是我们会替对方找很多理由。TA 只是太忙了，TA 只是性格慢热，TA 只是今天心情不好，TA 只是还没有意识到我有多认真。每一个理由听起来都说得过去，可所有理由叠在一起，反而越来越像一个答案。真正折磨人的不是没有回应，而是那些零零碎碎的回应，总让人觉得还有一点可能。\n后来才懂，一个人若真的在意你，哪怕笨拙，也会留下靠近的痕迹；一个人若只是在礼貌地回应你，哪怕温和，也会始终保持距离。喜欢不是非要轰轰烈烈，但一定不会让你长期活在猜测里。若你总是在找证据证明 TA 喜欢你，也许恰恰说明，最明显的证据一直不在。\n真正喜欢你的人，不需要你把每句话都写成谜语；真正想靠近你的人，也不会只满足于隔着屏幕揣测你的情绪。当然，这并不是说所有心意都必须立刻摊开。人有胆怯的时候，有自尊作祟的时候，有怕打扰、怕失去、怕一说出口连朋友都做不成的时候。\n可是，如果一份喜欢真的很重，重到让你反复修改签名、反复等待对方上线、反复在夜里猜 TA 有没有看懂，那它也许值得一次更诚实的表达。\n说出来，不一定有结果；不说出来，也未必能保住什么。很多遗憾之所以在多年后仍然让人耿耿于怀，不是因为当初一定能成功，而是因为我们从来没有给它一个真正落地的机会。\n当然，也不必苛责当年的自己。\n那个不敢表白的人，未必就是懦弱；那个看懂了却假装没看见的人，也未必就是冷漠。很多时候，我们都只是太年轻了，还不知道如何处理一份忽然降临的情感。暗恋者用隐喻保护自己，被暗恋者用沉默保护边界。两个人都没有错，只是都还没有长出足够成熟的方式。\n青春本来就常常这样：话说得太绕，心放得太重，勇气来得太晚。\n五、等你读懂的时候，我已经走远了 “等你读懂我的隐喻，我已经走了很远的路了。”\n这句话真正让人难过的地方，不只是“你没有读懂”，而是“我已经走了”。不是还在原地等一个答案，不是还守着那条签名等一个访问记录，而是终于承认：那段心事已经属于过去了。\n很多年以后，我们也许会偶然想起那个为一句签名纠结一下午的自己。会觉得幼稚，会觉得好笑，也会有一点点心疼。原来那时的我们，那么想被某个人看见，又那么害怕真的被看见；那么渴望靠近，又那么笨拙地把自己藏起来。\n可那也没有关系。人就是这样一点点长大的。\n那些没被读懂的隐喻，后来会变成更直接的表达；那些没有说出口的喜欢，后来会教会我们在重要的时候别再绕弯；那些年少时守着手机等来的失落，也会在某一天变成一句温柔的提醒：爱要珍惜，也要勇敢；深情可以浪漫，但不要只停在自我感动里。\n如果还来得及，就不用隐喻了。\n喜欢就说喜欢，想念就说想念，在意就说在意。把心意交给一句清楚的话，而不是交给一场漫长的猜谜。\n毕竟人生很长，但有些人只会出现在某一段路上。等对方终于读懂时，你可能真的已经走了很远很远。\n参考 李呀李嘉图《当年多愁善感，动不动就拔刀击柱》 纳兰性德《画堂春·一生一代一双人》 ","permalink":"https://june6699.github.io/posts/%E7%AD%89%E4%BD%A0%E8%AF%BB%E6%87%82%E6%88%91%E7%9A%84%E9%9A%90%E5%96%BB%E6%88%91%E5%B7%B2%E7%BB%8F%E8%B5%B0%E4%BA%86%E5%BE%88%E8%BF%9C%E7%9A%84%E8%B7%AF%E4%BA%86/","summary":"\u003cp\u003e最近刷到抖音博主“李呀李嘉图”的一段随笔，里面有一句话特别戳人：\u003c/p\u003e\n\u003cblockquote\u003e\n    \u003cp\u003e等你读懂我的隐喻，我已经走了很远的路了。\u003c/p\u003e\n\n  \u003c/blockquote\u003e\u003cp\u003e读到这里，像是忽然被拉回了很久以前。那时候我们还在用 QQ，头像要精挑细选，空间背景要反复更换，个性签名更像一块小小的告示牌。明面上只是几句歌词、几句古诗、几句故作深沉的话，背后却藏着一整颗不敢直说的心。\u003c/p\u003e","tags":["随笔","生活/文章","诗/杂感"],"title":"等你读懂我的隐喻，我已经走了很远的路了"},{"content":"《将夜》里有一句话很适合毕业季：\n鱼跃此时海，花开彼岸天。\n短短十个字，却像是把一个人的出发、远行和抵达都写尽了。鱼从水里跃起，终于见到更大的海；花在彼岸开放，说明漫长的等待终究没有白费。它不是那种热闹的祝福，却很辽阔，很明亮，也很适合送给每一个即将离开校园的人。\n毕业总是这样，一边像结束，一边又像开始。\n我们收拾书桌，搬空宿舍，交还钥匙，在合照里努力笑得自然一点。那些曾经习以为常的日子，忽然都变得有了纪念意义。每天路过的教学楼，赶过无数次的早八，深夜还亮着灯的实验室，食堂里吃到有点腻的窗口，操场上吹过的晚风，原来都在不知不觉中，把我们送到了这一天。\n可毕业并不只是告别。\n它更像一次跃出水面的瞬间。过去的几年，我们一直在某片熟悉的水域里生长。那里有规则，有课程表，有DDL，有导师和同学，有一个相对确定的明天。即使偶尔迷茫，也知道自己大概该往哪里去。可是从毕业这一刻开始，许多人要去新的城市，新的学校，新的岗位，新的生活现场。前面的海很大，大到让人兴奋，也大到让人害怕。\n所以“鱼跃此时海”里的“此时”特别动人。\n它不是凭空而来的好运，也不是突然拥有的勇气。这个“此时”，背后有很多无人看见的时刻：为考试复习到深夜的时候，为论文改到崩溃的时候，为实习和秋招焦虑的时候，为未来反复修改计划的时候。那些看起来普通甚至狼狈的日子，其实都在一点点把我们推向这次跃起。\n当鱼终于跃入大海，它未必立刻就能风平浪静。\n海里会有浪，会有暗流，会有不熟悉的方向。刚毕业的人也是这样。我们可能会遇见新的不确定，发现自己并没有想象中那么成熟；也可能会被现实敲一敲，才明白课本之外还有许多复杂的题目。可是没有关系。大海之所以是大海，正因为它不只允许顺风顺水，也容得下试错、迂回、重新出发。\n愿我们都有这样的勇气：不因为害怕风浪，就一直停在原来的岸边。\n“花开彼岸天”则更像是一种温柔的相信。\n每个人的彼岸都不一样。有人继续读书，有人奔赴职场；有人去了远方，有人留在熟悉的城市；有人很快找到自己的节奏，也有人还在慢慢摸索。我们不必用同一把尺子衡量所有人的人生。花开有早有晚，方向也各不相同。重要的是，在属于自己的季节里，认真扎根，认真向上。\n前程似锦，并不是说往后的路一定铺满鲜花。\n它更像一句郑重的祝愿：愿你在复杂的世界里，仍然保有选择的能力；愿你在疲惫的时候，仍然记得自己为什么出发；愿你遇到喜欢的事，就有投入其中的热情；遇到困难的事，也有慢慢解决它的耐心。愿你不必总是赢得漂亮，但总能活得真诚、清醒、自在。\n毕业之后，我们会越来越少拥有整齐划一的日程，也越来越难像从前那样轻易聚在一起。很多人会散进人海，成为彼此朋友圈里偶尔亮起的名字。可是我想，真正珍贵的关系，不会因为距离就完全失效。那些一起熬过的夜，一起赶过的路，一起说过的笑话和烦恼，都会留在各自的人生里，成为很温柔的底色。\n多年以后再想起这个夏天，也许我们会发现，毕业那天最重要的并不是散场，而是出发。\n我们从同一片校园走向不同的海，从同一个季节奔向不同的彼岸。有人会在很远的地方开花，有人会在很新的世界发光。也许路上会有迟疑，会有疲惫，会有偶尔想念从前的时候，但只要还愿意往前走，人生就会继续给我们新的风景。\n所以，毕业快乐。\n愿你此去，鱼跃入海，不惧风浪；愿你来日，花开彼岸，不负热爱。愿我们都能在各自的远方，把日子过成自己喜欢的模样。\n也愿多年后重逢，我们仍能笑着说：那年盛夏的告别，原来不是结束，而是每个人都走向了更辽阔的天。\n","permalink":"https://june6699.github.io/posts/%E9%B1%BC%E8%B7%83%E6%AD%A4%E6%97%B6%E6%B5%B7%E8%8A%B1%E5%BC%80%E5%BD%BC%E5%B2%B8%E5%A4%A9/","summary":"\u003cp\u003e《将夜》里有一句话很适合毕业季：\u003c/p\u003e\n\u003cblockquote\u003e\n    \u003cp\u003e鱼跃此时海，花开彼岸天。\u003c/p\u003e\n\n  \u003c/blockquote\u003e\u003cp\u003e短短十个字，却像是把一个人的出发、远行和抵达都写尽了。鱼从水里跃起，终于见到更大的海；花在彼岸开放，说明漫长的等待终究没有白费。它不是那种热闹的祝福，却很辽阔，很明亮，也很适合送给每一个即将离开校园的人。\u003c/p\u003e","tags":["随笔","生活/文章","毕业季"],"title":"鱼跃此时海，花开彼岸天"},{"content":"毕业季很容易被写成一串宏大的词：未来、理想、选择、远方。可真正能留下来的，往往不是一整篇演讲，而是某一句话突然打中你。\n这次我把 12 场毕业演讲和获奖发言做成了朋友圈竖版图卡。它们来自工程师、创业者、作家、演员和科技公司 CEO，有的是典礼现场，有的是线上告别，有的甚至不是严格意义上的毕业演讲，但都很适合放在毕业季：把一个人走过的路，压缩成一句可以带走的话。\nLisa Su：把未来押在最难的问题上 Lisa Su 是 AMD 董事长兼 CEO，她将为 MIT 2026 届毕业生做毕业典礼演讲。我给这张卡片写的句子是：\n把最难的问题，当成你最值得下注的未来。\nBet your future on the hardest problems.\n这句话的底色是工程信念。它不是简单的“要努力”，而是把长期主义、技术变革和个人选择放在一起看：容易的问题当然也能解决，但真正能改变世界、也真正能改变自己的，往往是那些一开始看起来最难、最不确定、最需要耐心的问题。\n来源链接：MIT News - Lisa Su to deliver MIT\u0026rsquo;s 2026 Commencement address 演讲内容 Lisa Su MIT Commencement 2026 展开 中文 English 中文短译\n技术本身不会决定未来的样子。 短摘录来源：MIT News。完整语境请阅读下方来源链接。\nEnglish excerpt\nTechnology itself does not decide what the future looks like. Short excerpt source: MIT News. Read the linked source for full context.\nMIT NewsMIT News | Massachusetts Institute of Technology · 发布时间未标注Commencement address by Lisa Su ’90, SM ’91, PhD ’94 Jensen Huang：不要走向未来，要跑过去 Jensen Huang 是 NVIDIA 创始人兼 CEO，他在 Carnegie Mellon University 2026 毕业典礼上的主题很适合做成一张有速度感的图。卡片上的句子是：\n别慢慢走向未来，跑过去。\nDon\u0026rsquo;t walk into the future. Run.\n这张的核心不是制造 AI 焦虑，而是提醒毕业生：窗口已经打开，下一轮技术浪潮不会等你慢慢准备好。与其站在岸上看浪，不如亲手去塑造接下来会发生的事。\n来源链接：CMU News - Jensen Huang to Carnegie Mellon graduates: shape what comes next 、NVIDIA Blog - Jensen Huang\u0026rsquo;s Carnegie Mellon commencement address 演讲内容 Jensen Huang Carnegie Mellon Commencement 2026 展开 中文 English 中文短译\n塑造接下来会发生的事。 短摘录来源：CMU News。完整语境请阅读下方来源链接。\nEnglish excerpt\nShape what comes next. Short excerpt source: CMU News. Read the linked source for full context.\nCMU NewsNews · 2026-05-10NVIDIA Founder, CEO Jensen Huang to Carnegie Mellon University Graduates: ‘Shape What Comes Next’ NVIDIA BlogNVIDIA Blog · 2026-05-10‘Your Career Starts at the Beginning of the AI Revolution,’ NVIDIA CEO Tells Graduates Elon Musk：把不可能做成现实 Elon Musk 在 Caltech 2012 毕业典礼上讲到了互联网、电动车、火箭和太空探索。卡片上的句子是：\n当所有人说不可能，你就把它做成魔法。\nWhen they call it impossible, build the magic.\n我喜欢这场演讲里那种非常粗粝的推进感：被怀疑、失败、继续做、再失败、再做。它不是“天才叙事”，更像是一个人用原型、迭代和现实结果一点点把“不可能”磨成“已经发生”。\n来源链接：C-SPAN - California Institute of Technology Commencement Address 演讲内容 Elon Musk Caltech Commencement 2012 展开 中文 English 中文短译\n暂无可验证短摘录；请打开来源链接阅读完整语境。 短摘录来源：来源页。完整语境请阅读下方来源链接。\nEnglish excerpt\nNo verified short excerpt was collected. Please read the linked source for the full context. Short excerpt source: 来源页. Read the linked source for full context.\nC-SPANC-SPAN.org · 发布时间未标注California Institute of Technology Commencement Address Mark Zuckerberg：先开始，想法才会长出来 Mark Zuckerberg 在 Harvard 2017 毕业典礼上讲了使命、社区和年轻人的行动。卡片上的句子是：\n准备太久，梦想就永远不会开始。\nIf you wait until it\u0026rsquo;s perfect, you\u0026rsquo;ll never begin.\n这场演讲里最适合毕业季的一点，是他讲“想法不是完整出现的”。很多人会想等规划完整、能力完整、风险消失之后再开始，可现实往往相反：先动起来，想法才会在行动里长出真正的形状。\n来源链接：Harvard Gazette - Mark Zuckerberg\u0026rsquo;s speech as written for Harvard\u0026rsquo;s Class of 2017 演讲内容 Mark Zuckerberg Harvard Commencement 2017 展开 中文 English 中文短译\n想法不会一开始就完整成形。 短摘录来源：Harvard Gazette。完整语境请阅读下方来源链接。\nEnglish excerpt\nIdeas don\u0026#x27;t come out fully formed. Short excerpt source: Harvard Gazette. Read the linked source for full context.\nHarvard GazetteHarvard Gazette · 2017-05-25Mark Zuckerberg\u0026#x27;s speech as written for Harvard\u0026#x27;s Class of 2017 Park Bo-young：不卷别人，也不输给昨天 Park Bo-young 这条来自 Baeksang Arts Awards 2026 获奖感言，严格说它不是毕业演讲，但我还是把它放进了这组图里。卡片上的句子是：\n我讨厌竞争，但我不想输给昨天的自己。\nI hate competition, but I won\u0026rsquo;t lose to yesterday\u0026rsquo;s self.\n这句话像是给毕业季加了一点缓冲。很多人已经厌倦了排名、比较和外部竞争，但这不等于放弃认真生活。它说的是另一种温柔的自我要求：不用卷赢所有人，但至少想认真回应昨天的自己。\n来源链接：MK English - Park Bo-young\u0026rsquo;s Baeksang acceptance speech 演讲内容 Park Bo-young Baeksang Arts Awards 2026 展开 中文 English 中文短译\n暂无可验证短摘录；请打开来源链接阅读完整语境。 短摘录来源：来源页。完整语境请阅读下方来源链接。\nEnglish excerpt\nNo verified short excerpt was collected. Please read the linked source for the full context. Short excerpt source: 来源页. Read the linked source for full context.\nMK English매일경제 · 2026-05-12Actor Park Bo-young drew smiles from fans with her lovely daily life.Park Bo-young released several .. - MK Steve Jobs：不要活在别人的剧本里 Steve Jobs 在 Stanford 2005 的演讲已经是毕业演讲里的经典样本。卡片上的句子是：\n别人的剧本，不值得你过一生。\nDon\u0026rsquo;t spend your life living someone else\u0026rsquo;s script.\n他讲连点成线，讲热爱与失去，也讲死亡意识。它最重的地方不是煽情，而是那句非常朴素的提醒：你的时间有限。毕业季看到这张图，我希望它更安静一点，像是把人生重新交还给自己。\n来源链接：Stanford News - You\u0026rsquo;ve got to find what you love, Jobs says 、YouTube - Steve Jobs\u0026rsquo; 2005 Stanford Commencement Address 演讲内容 Steve Jobs Stanford Commencement 2005 展开 中文 English 中文短译\n暂无可验证短摘录；请打开来源链接阅读完整语境。 短摘录来源：来源页。完整语境请阅读下方来源链接。\nEnglish excerpt\nNo verified short excerpt was collected. Please read the linked source for the full context. Short excerpt source: 来源页. Read the linked source for full context.\nStanford ReportStanford Report · 发布时间未标注Stanford Report Jeff Bezos：聪明是礼物，善良是选择 Jeff Bezos 在 Princeton 2010 Baccalaureate 演讲里没有把重点放在商业成功上，而是讲选择。卡片上的句子是：\n聪明是礼物，善良是选择。\nCleverness is a gift; kindness is a choice.\n这场演讲很适合毕业生，因为它把人生评价标准从“你有多聪明”转向“你做过什么选择”。天赋会让人走得快，但最后定义一个人的，还是那些一次次由自己做出的选择。\n来源链接：Princeton - 2010 Baccalaureate remarks 演讲内容 Jeff Bezos Princeton Baccalaureate 2010 展开 中文 English 中文短译\n暂无可验证短摘录；请打开来源链接阅读完整语境。 短摘录来源：来源页。完整语境请阅读下方来源链接。\nEnglish excerpt\nNo verified short excerpt was collected. Please read the linked source for the full context. Short excerpt source: 来源页. Read the linked source for full context.\nPrincetonPrinceton · 发布时间未标注Princeton Bill Gates：人生不是单线程任务 Bill Gates 在 Northern Arizona University 2023 毕业典礼上讲了几件“希望年轻时有人告诉我”的事。卡片上的句子是：\n人生不是单线程任务，别把自己跑崩。\nLife is not a single-threaded task. Don\u0026rsquo;t burn yourself out.\n这场演讲难得的地方，是它不像“成功人士教你拼命”。他谈到自己年轻时过于单线程的工作方式，也提醒毕业生：工作和成绩很重要，但关系、身体、好奇心、休息和节奏也同样会塑造一个人。\n来源链接：GatesNotes - 5 things I wish I heard at the graduation I never had 演讲内容 Bill Gates NAU Commencement 2023 展开 中文 English 中文短译\n暂无可验证短摘录；请打开来源链接阅读完整语境。 短摘录来源：来源页。完整语境请阅读下方来源链接。\nEnglish excerpt\nNo verified short excerpt was collected. Please read the linked source for the full context. Short excerpt source: 来源页. Read the linked source for full context.\nGatesNotesGatesNotes · 发布时间未标注GatesNotes Tim Cook：建设者要承担后果 Tim Cook 在 Stanford 2019 毕业典礼上谈到了科技行业、隐私、权力和责任。卡片上的句子是：\n拿走掌声之前，先承担后果。\nBefore taking credit, take responsibility.\n这张图卡的情绪更冷静。它不像热血创业演讲，而像是写给未来掌权者的一封提醒：真正的建设者不能只享受成果，也必须承担创造带来的影响。\n来源链接：Stanford Report - Remarks by Tim Cook at 2019 Stanford Commencement 演讲内容 Tim Cook Stanford Commencement 2019 展开 中文 English 中文短译\n暂无可验证短摘录；请打开来源链接阅读完整语境。 短摘录来源：来源页。完整语境请阅读下方来源链接。\nEnglish excerpt\nNo verified short excerpt was collected. Please read the linked source for the full context. Short excerpt source: 来源页. Read the linked source for full context.\nStanford ReportStanford Report · 发布时间未标注Stanford Report Sheryl Sandberg：把 B 计划活成答案 Sheryl Sandberg 在 UC Berkeley 2016 毕业典礼上的演讲，最动人的地方是她不是站在“成功者”的位置讲成功，而是站在失去之后讲如何继续生活。卡片上的句子是：\n当 A 计划碎了，就把 B 计划活成答案。\nWhen Option A is gone, make Option B your answer.\n她谈到丈夫去世后的悲伤、复原力和 Option B。有些路不是你选的，有些断裂也不会提前征求同意，但人在剩下的路里，仍然可以重新长出力量。\n来源链接：Los Angeles Times - Sheryl Sandberg commencement address transcript 演讲内容 Sheryl Sandberg UC Berkeley Commencement 2016 展开 中文 English 中文短译\n我理解了悲伤的深度，也理解了失去的残酷。 短摘录来源：Los Angeles Times。完整语境请阅读下方来源链接。\nEnglish excerpt\nI learned about the depths of sadness and the brutality of loss. Short excerpt source: Los Angeles Times. Read the linked source for full context.\nLos Angeles TimesLos Angeles Times · 2016-05-14Transcript: Sheryl Sandberg\u0026#x27;s 2016 Commencement Address at University of California, Berkeley Sundar Pichai：保持不耐烦，也保持希望 Sundar Pichai 的 Dear Class of 2020 面向的是一届被迫在线上告别校园的毕业生。卡片上的句子是：\n保持不耐烦，也保持希望。\nStay impatient. Stay hopeful.\n他讲自己的成长和技术变迁，也把重点落在年轻人的“不耐烦”上：不要太快适应一个不够好的世界。希望不是安慰剂，不耐烦也不是坏脾气，它们合在一起，才像是一个年轻人想改变世界的冲动。\n来源链接：Google Blog - Sundar Pichai\u0026rsquo;s message to the Class of 2020 演讲内容 Sundar Pichai Dear Class of 2020 展开 中文 English 中文短译\n保持不耐烦，它会创造世界需要的进步。 短摘录来源：Google Blog。完整语境请阅读下方来源链接。\nEnglish excerpt\nBe impatient. It will create the progress the world needs. Short excerpt source: Google Blog. Read the linked source for full context.\nGoogle BlogGoogle · 2020-06-07You Will Prevail - A message to the Class of 2020 J.K. Rowling：失败之后，想象力让人重新开始 J.K. Rowling 在 Harvard 2008 的演讲，很适合作为这组图卡的收尾。卡片上的句子是：\n失败把你剥到只剩真实，想象让你重新出发。\nFailure strips you to truth; imagination lets you begin again.\n她把失败讲得很诚实：失败会让人失去很多外壳，但也会让人看清真正重要的东西。随后她又把“想象力”从写作能力扩展成一种理解他人痛苦、重新创造人生的能力。毕业季到这里，也就从“出发”回到了“重新出发”。\n来源链接：Harvard Gazette - Text of J.K. Rowling\u0026rsquo;s speech 演讲内容 J.K. Rowling Harvard Commencement 2008 展开 中文 English 中文短译\n失败意味着剥离掉那些不必要的东西。 短摘录来源：Harvard Gazette。完整语境请阅读下方来源链接。\nEnglish excerpt\nFailure meant a stripping away of the inessential. Short excerpt source: Harvard Gazette. Read the linked source for full context.\nHarvard GazetteHarvard Gazette · 2008-06-05Text of J.K. Rowling\u0026#x27;s speech — Harvard Gazette 生成工作流 这组图不是让模型直接写字。我的做法是先让 GPT-image-2 只负责“人物长相、演讲现场、画面留白”，再用 Python 后期排版。这样做的好处很直接：中文不会乱写，英文不会拼错，版面也更可控。\n完整素材和脚本在本地这个目录里：\nC:\\Files\\学校文件\\2026 毕业 实际流程是：\n整理资料：先在 毕业演讲朋友圈图卡素材.md 里写好人物、场合、身份、中文金句、英文金句、主题概括、内容说明和来源链接。 准备参考图：wikipedia 目录放人物肖像，reference 目录放演讲或公开发言现场图，用来锁定长相、场景、服装和年代感。 生成无字底图：运行 _generate_speech_bases.py，通过图像 API 生成每个人的 base.png。提示词里反复强调 no text, no watermark, no logo，并要求画面左侧或右侧留出干净负空间。 后期加字：运行 _render_speech_cards.py，用 Pillow 打开 base.png，叠一层半透明遮罩，再写人物名、身份、场合、中英文金句和底部短评，输出 card.png。 拼总览图：运行 _make_generated_contact_sheet.py，把 12 张 card.png 缩成 3 列总览，输出 _contact_sheet.png。 发布到 Hugo：把总览图和 12 张卡片复制到 content/posts/images/2026毕业演讲朋友圈图卡/，正文里用 ./images/2026毕业演讲朋友圈图卡/... 引用。构建前 scripts/sync_images.py 会把文章图片同步到 static/images。 生成底图时的命令大概长这样：\n$env:JUNE_IMAGE_API_KEY = \u0026#34;\u0026lt;你的 key\u0026gt;\u0026#34; py -3.11 \u0026#34;C:\\Files\\学校文件\\2026 毕业\\_generate_speech_bases.py\u0026#34; 如果只想重新生成某几个人，也可以通过脚本里的 ONLY_PEOPLE 环境变量过滤：\n$env:ONLY_PEOPLE = \u0026#34;Lisa Su|Jensen Huang\u0026#34; py -3.11 \u0026#34;C:\\Files\\学校文件\\2026 毕业\\_generate_speech_bases.py\u0026#34; 加字和拼总览图则是：\npy -3.11 \u0026#34;C:\\Files\\学校文件\\2026 毕业\\_render_speech_cards.py\u0026#34; py -3.11 \u0026#34;C:\\Files\\学校文件\\2026 毕业\\_make_generated_contact_sheet.py\u0026#34; Python 加文字的核心代码 下面这段是从 _render_speech_cards.py 里提炼出来的核心逻辑：先给底图左侧加暗色渐变，保证文字能压住背景；再按中英文标点拆句；如果某一行太长，就自动缩小字号；最后把人物、身份、场合、金句和底部短句画上去。\nfrom pathlib import Path import re from PIL import Image, ImageDraw, ImageFont ROOT = Path(r\u0026#34;C:\\Files\\学校文件\\2026 毕业\u0026#34;) def fit_font(font_path, text, max_width, start_size=48, min_size=28): scratch = ImageDraw.Draw(Image.new(\u0026#34;RGB\u0026#34;, (1, 1))) for size in range(start_size, min_size - 1, -1): font = ImageFont.truetype(font_path, size) width = scratch.textbbox((0, 0), text, font=font)[2] if width \u0026lt;= max_width: return font return ImageFont.truetype(font_path, min_size) def split_sentence(text): pattern = r\u0026#34;[^，；。！？,;.?!]+[，；。！？,;.?!]?\u0026#34; lines = [m.group(0).strip() for m in re.finditer(pattern, text)] return [line for line in lines if line] or [text] def draw_sentence_lines(draw, text, xy, font_path, fill, max_width, start_size, min_size): x, y = xy for line in split_sentence(text): font = fit_font(font_path, line, max_width, start_size, min_size) draw.text((x, y), line, font=font, fill=fill) box = draw.textbbox((x, y), line, font=font) y = box[3] + 14 return y def render_card(person, payload): person_dir = ROOT / \u0026#34;generated\u0026#34; / person image = Image.open(person_dir / \u0026#34;base.png\u0026#34;).convert(\u0026#34;RGBA\u0026#34;) width, height = image.size # 给左侧文字区压一层半透明暗色渐变。 overlay = Image.new(\u0026#34;RGBA\u0026#34;, image.size, (0, 0, 0, 0)) pixels = overlay.load() for x in range(width): alpha = int(max(0, 128 * (1 - x / 625))) for y in range(height): pixels[x, y] = (14, 18, 23, alpha) image = Image.alpha_composite(image, overlay) draw = ImageDraw.Draw(image) left = 58 max_width = width - left - 58 name_font = ImageFont.truetype(r\u0026#34;C:\\Windows\\Fonts\\arialbd.ttf\u0026#34;, 44) cn_font = r\u0026#34;C:\\Windows\\Fonts\\msyhbd.ttc\u0026#34; en_font = r\u0026#34;C:\\Windows\\Fonts\\arial.ttf\u0026#34; small_cn = ImageFont.truetype(r\u0026#34;C:\\Windows\\Fonts\\msyh.ttc\u0026#34;, 24) small_en = ImageFont.truetype(r\u0026#34;C:\\Windows\\Fonts\\arialbd.ttf\u0026#34;, 30) draw.text((left, 84), payload[\u0026#34;name\u0026#34;], font=name_font, fill=(255, 255, 255, 246)) draw.text((left, 150), payload[\u0026#34;identity\u0026#34;], font=small_cn, fill=(235, 238, 242, 220)) draw.text((left, 195), payload[\u0026#34;occasion\u0026#34;], font=small_en, fill=payload[\u0026#34;gold\u0026#34;] + (235,)) y = draw_sentence_lines( draw, payload[\u0026#34;cn\u0026#34;], (left, 830), cn_font, (255, 255, 255, 248), max_width, start_size=48, min_size=39, ) draw_sentence_lines( draw, payload[\u0026#34;en\u0026#34;], (left, y + 16), en_font, (237, 239, 242, 224), max_width, start_size=31, min_size=25, ) draw.text((left, height - 112), payload[\u0026#34;footer\u0026#34;], font=small_cn, fill=(232, 235, 239, 205)) image.convert(\u0026#34;RGB\u0026#34;).save(person_dir / \u0026#34;card.png\u0026#34;, quality=96) py -3.11 scripts/sync_images.py hugo --buildFuture ","permalink":"https://june6699.github.io/posts/2026%E6%AF%95%E4%B8%9A%E6%BC%94%E8%AE%B2%E6%9C%8B%E5%8F%8B%E5%9C%88%E5%9B%BE%E5%8D%A1/","summary":"\u003cp\u003e毕业季很容易被写成一串宏大的词：未来、理想、选择、远方。可真正能留下来的，往往不是一整篇演讲，而是某一句话突然打中你。\u003c/p\u003e\n\u003cp\u003e这次我把 12 场毕业演讲和获奖发言做成了朋友圈竖版图卡。它们来自工程师、创业者、作家、演员和科技公司 CEO，有的是典礼现场，有的是线上告别，有的甚至不是严格意义上的毕业演讲，但都很适合放在毕业季：把一个人走过的路，压缩成一句可以带走的话。\u003c/p\u003e","tags":["生活","AI","毕业季"],"title":"十二张毕业演讲图卡：把未来说成一句话"},{"content":"最近的两个项目压力真的太大了。\n不是那种“今天任务很多”的压力，而是那种每往前走一步，前面又长出三条路，每条路都要验证、解释、画图、写清楚、还要经得起老师追问的压力。\n我现在越来越觉得，读研最累的地方不是软件不会用，也不是代码跑不动，而是你以为自己已经找到一个结果了，结果老师一句话就能把它打回到上游：这个 peak 可靠吗？这个 overlap 严格吗？这个基因在人里面也上调吗？这个 enhancer 真的调控这个基因吗？这个 TF 真的能解释吗？这个 FitHiC2 是 top200K 吗？这个文献支持的是促衰还是保护？\n然后我就会发现，所谓“找到一个候选基因”，根本不是找到一个名字而已，而是要给这个基因做一整套证据链。\n我们现在做的是猪心脏衰老。最理想的故事是：找到一个转录因子，这个转录因子调控一个靶基因；这个靶基因在心脏衰老里有明确文献支持，最好能促进心脏肥大、纤维化、自噬异常、收缩功能下降或者其他衰老相关表型；同时，我们还要找到一个增强子，证明这个增强子可能调控这个基因。\n听起来已经很复杂了，但这只是故事的开头。\n首先，RNA 侧的证据要过关。这个转录因子和靶基因都必须在猪衰老阶段显著上调，而且最好是 FDR 显著，而不是只靠 P 值显著。logFC 还不能太小，表达比例也不能太低。也就是说，不能是那种 pct.1=0.05 的基因，哪怕统计上显著，生物学上也很难讲。至少要有一个比较像样的表达比例，比如 0.3 左右，才能让人相信这个基因真的在一部分细胞里有表达，而不是统计模型给出来的边缘结果。\n但 RNA 只是第一层。\n接下来还要看 ATAC。我们需要衰老阶段显著开放的 peak，而且这些 peak 里面要能富集到这个转录因子的 motif。也就是说，不仅这个 TF 自己要上调，它潜在能结合的区域也要在衰老阶段开放。否则就很难说它在衰老过程中真的参与调控。\n然后还要看 SCENIC+。这个转录因子最好在 SCENIC+ 里面是一个 ++ 的 eRegulon，并且这个 eRegulon 要显著富集于衰老阶段。更关键的是，这个 eRegulon 里面必须包含我们的靶基因；调控关系还要是正相关，regulation 要是 1，importance 也不能太低。否则就只能说“这个 TF 可能相关”，但不能说“这个 TF 可能调控这个靶基因”。\n到这里其实已经筛掉很多候选了。\n随后还有跨物种证据。我们要把猪的显著差异开放 peak 通过 liftOver 转到人 hg38 上，然后和三套公共数据的人 ATAC 差异开放 peak 做 overlap。其中两套是单细胞 ATAC，一套是 bulk-ATAC。这里的 overlap 还不是“碰到一点就算”，而是老师更倾向于严格标准：两端都要覆盖 50% 以上，也就是猪的 peak 覆盖人的 peak 至少 50%，人的 peak 也覆盖猪的 peak 至少 50%。\n这个标准非常狠。\n任意 overlap 的时候，看起来还能剩下一些候选；一旦改成 50% reciprocal overlap，很多 peak 直接就没了。尤其是跨物种之后，坐标本来就会发生变化，peak 长度也不一样，再加上不同数据来源 peak calling 的边界不同，能严格 overlap 到的区域其实很少。\n拿到这些 overlap peak 之后，还不能直接说它调控某个基因。我们还要把区域和基因连起来。\n最直接的策略是看距离，比如这个区域离某个基因 TSS 在 20 kb、50 kb 或 100 kb 以内。距离越近越好，20 kb 以内最好讲，100 kb 就已经需要更谨慎了。\n但老师又会问：距离近就一定调控吗？\n所以我们还做了 bulk Hi-C / FitHiC2。希望能看到这个 enhancer 区域和目标基因的启动子或 TSS 区域之间存在显著互作，而且这个互作的 FDR 要显著。我们本来以为有 FitHiC2 显著互作就很不错了，结果老师又进一步要求：如果这个 interaction 不在 top200K 里面，那意义也不大。\n我当时真的心态爆炸。\n因为这意味着，不只是要有连接，还要是足够强、足够靠前、足够可信的连接。一个结果刚刚够到门槛，马上又会出现新的门槛。\n有了这些被连接到的基因之后，还要继续过滤。这个基因必须满足：\n是人猪同源基因，而且同源关系要高度可信，最好是一对一 ortholog； 在猪衰老阶段显著上调； 在人的衰老 RNA 数据里面，至少有一套也显著上调； 最好在不同数据来源之间方向一致，而不是猪上调、人不变，或者 ATAC old-open、RNA 不 old-up。 也就是说，我们不是只在猪里面找基因，而是要找到一个“猪里成立、人里也有支持”的衰老相关调控轴。\n然后，对于这些满足条件的 overlap peak，还要单独做 AME。要求这些 peak 里面最好能富集到我们前面说的那个转录因子的 motif。这里又有一个问题：如果是单条 enhancer 做 AME，统计意义其实很弱，更像 motif scan，而不是严格的 motif enrichment。但汇报的时候又需要给出 motif 证据，所以只能非常谨慎地说：这是 motif presence 的线索，不是强富集结论。\n随后还要看 Cicero。我们要求这个 overlap peak 和靶基因 TSS 之间有共可及性，也就是 co-accessibility 不能太低。最低可能要 0.2，严格一点甚至要 0.4。只有这样，才能说这个 enhancer 和这个 gene 在单细胞 ATAC 的开放状态上有一定联系。\n但这还不是终点。\n最后的最后，如果要把这个故事真正做成机制，就要进入实验验证：\n靶基因敲除后，要能抑制衰老表型； 转录因子敲除后，要能抑制靶基因表达； 干扰这个增强子后，靶基因表达要下降，同时衰老表型要被抑制； 如果再恢复这个增强子、转录因子或靶基因，衰老表型最好还能被 rescue 回来。 也就是说，最终要证明的是一整条链：\n衰老 → chromatin opening → enhancer activation → TF binding/regulation → target gene upregulation → aging phenotype。\n而且这条链上的每一个箭头，都要有证据。\n现在回头看，我觉得这个项目最折磨人的地方，是它不是一个单纯的生信分析。它更像是在给一个候选基因做全套“政审”。\nRNA 要过关，ATAC 要过关，motif 要过关，SCENIC+ 要过关，跨物种 liftOver 要过关，人类公共数据 overlap 要过关，enhancer-gene link 要过关，FitHiC2 要过关，Cicero 要过关，文献机制要过关，最后实验还要能验证。\n任何一环弱一点，这个候选就会变成“可以作为补充”，而不是“可以作为主线”。\n更让人崩溃的是，很多时候不是结果完全没有，而是结果总差一点。比如：\n这个基因猪里很强，但人里不显著。\n这个 peak 任意 overlap 能碰上，但 50% reciprocal overlap 过不了。\n这个 enhancer 离 TSS 不远，但 FitHiC2 不够靠前。\n这个基因文献很强，但方向可能是保护性代偿，不一定是促衰。\n这个 TF motif 有，但 eRegulon 里没有靶基因。\n这个候选看起来很漂亮，但表达比例太低。\n每一个“差一点”，都很消耗人。\n以前我以为科研是找到一个有意思的现象，然后解释它。现在才发现，真正困难的是：你要不断证明这个现象不是偶然，不是噪音，不是批次，不是细胞类型混杂，不是坐标误差，不是数据库偏差，不是统计阈值放松之后才出现的结果。\n有时候我真的会觉得，这不是在找基因，这是在审案子。\n一个候选基因站在被告席上，我们要不断提交证据：表达证据、开放证据、motif 证据、调控证据、物种保守证据、文献证据、功能证据。老师就像法官，一条一条问：这个证据够强吗？有没有反例？有没有更严格的标准？有没有更直接的验证？\n我知道老师严格是对的。因为如果证据链不够硬，后面做实验会更痛苦。一个不稳的候选，可能会浪费几个月甚至更久。现在多筛一点、多问一点，其实是在避免后面掉进更大的坑里。\n但知道是一回事，压力又是另一回事。\n当一个分析流程长到每一步都可能推翻前一步，当每一个结果都需要被重新解释，当你已经整理了很多图和表，下一秒又因为一个 top200K、一个 50% overlap、一个 FitHiC2 q 值被打回去的时候，真的会觉得很累。\n读研好像就是这样：你不断以为自己快到终点了，然后发现前面还有一段路。而且这段路不是直的，是分叉的，每个分叉都写着“请补充证据”。\n但我也不得不承认，正是这些折磨人的要求，让我逐渐知道什么叫“证据链”。\n不是有差异就叫结果。\n不是有 motif 就叫调控。\n不是离得近就叫 enhancer-gene link。\n不是 P 值显著就叫可靠。\n不是一个物种成立就叫保守。\n不是有文献提到就能直接套机制。\n真正能讲出去的结果，必须经得起很多层追问。\n所以现在虽然很崩溃，但我也能感觉到，自己确实比以前更知道怎么判断一个候选靠不靠谱了。只是这个成长过程真的太痛苦了。\n如果以后有人问我，这个项目到底在做什么，我可能会说：\n我们不是在找一个基因。\n我们是在找一条能从猪衰老单细胞多组学，一直连到人类公共 ATAC/RNA 数据，再连到 enhancer、TF、靶基因和衰老表型的调控证据链。\n如果这条链真的能闭合，那当然会很漂亮。\n但在它闭合之前，每一个节点都足够让人怀疑人生。\n","permalink":"https://june6699.github.io/posts/%E5%8E%8B%E5%8A%9B%E7%9C%9F%E7%9A%84%E5%A5%BD%E5%A4%A7/","summary":"\u003cp\u003e最近的两个项目压力真的太大了。\u003c/p\u003e\n\u003cp\u003e不是那种“今天任务很多”的压力，而是那种每往前走一步，前面又长出三条路，每条路都要验证、解释、画图、写清楚、还要经得起老师追问的压力。\u003c/p\u003e","tags":["生活","生活/读研"],"title":"读个研压力真的太大了"},{"content":"一、前言 本文教程供 June6699/dart_simple_live 及其其他类似项目使用，可以让他拥有抖音平台、快手平台、斗鱼平台的更多功能。具体优点如下：\n抖音：有 Cookie 就可以支持搜索主播，对于并发限制更加宽松； 快手：有 Cookie 就可以支持看到弹幕 斗鱼：有 Cookie 就可以免于斗鱼对匿名用户的最高画质限制 Simple Live 里抖音和快手都可以配置 Cookie，但两家的用途和表现不完全一样。\n如果对F12开发者工具有一些了解，请直接看第三节（抖音）、第四节（快手）、第五节（斗鱼）。 如果你喜欢自己折腾一下，而且很熟悉浏览器的扩展功能，你可以尝试一下有没有一些扩展能帮助你直接导出cookie，目前为止尝试了几款扩展，都无法做到这一点。 如果你发现了类似扩展/软件/插件，欢迎在评论区提供你的见解哦。 抖音：只看直播时默认 ttwid 多数情况下可以兜底；搜索主播 / 房间建议导入完整 Cookie。 快手：非登录网页也可能看到弹幕，但验证码、代理、风控会影响稳定性；如果要让弹幕更稳定，建议导入 live.kuaishou.com 的完整 Cookie。 简单记：\n抖音不要只填 ttwid，搜索更建议用完整 www.douyin.com Cookie。 快手不要只复制某一个字段，弹幕更建议用完整 live.kuaishou.com Cookie。 手机端不建议手动粘贴超长 Cookie，推荐保存成 txt 文件后用“从文件导入 Cookie”。 TV 端不适合直接抓 Cookie，建议先在主 App 配好，再通过同步功能同步到 TV。 这篇教程写给不熟悉浏览器开发者工具的人。只要按步骤做，不需要懂前端。\n二、Cookie 是什么 Cookie 可以粗略理解成“浏览器帮你保存的一串登录凭据”。\n你在电脑浏览器里登录抖音或快手后，浏览器每次请求对应网站时，都会在请求头里带上一段类似这样的东西：\ncookie: key1=value1; key2=value2; key3=value3 这一整行就是我们要复制的东西。\n它不等同于密码，但很接近登录凭据。拿到你的完整 Cookie 的人，有可能在一段时间内用你的登录态请求平台接口。所以不要发给别人，不要贴到公开 issue，也不要截图发群里。\n三、抖音 Cookie 获取和导入 3.1 不要只复制 ttwid 这篇教程里说的抖音 Cookie，默认都指“完整 Cookie”，也就是一整串字段。\n你要复制的是这种：\nttwid=...; sid_guard=...; sessionid=...; passport_csrf_token=...; msToken=... 不要只复制这种：\nttwid=... 3.2 电脑端获取抖音 Cookie 建议用电脑端 Chrome 或 Edge。下面以 Edge / Chrome 这一类 Chromium 浏览器为例。这里是手动操作的示例，后面还有一种使用浏览器扩展的方法。\n打开抖音网页并登录：\n重要 一定要登录！扫码还是什么随你。\nhttps://www.douyin.com/ 或者：\nhttps://live.douyin.com/ 按 F12 打开开发者工具。如果没反应，可以试 Ctrl + Shift + I。\n点上方的 Network，或者“网络”。\n在 Network 面板打开的情况下，按 Ctrl + R 刷新页面。\n在请求列表里，我们可以看到名称这一列，然后我们去找名称前面几个字符就可以看到/的，比如self/、info/、update/等等。\n重要 这个很重要，关系到你会不会像无头苍蝇一样乱撞却还是找不到。\n而因为带 / 的通常是 \u0026ldquo;站点地址\u0026rdquo;，而 cookie 恰恰是挂在 \u0026ldquo;站点\u0026rdquo; 下的，所以这种取巧的办法就能帮我们节省时间。\n进去请求列表之后，我们可以看到有好几个标头，我们选择请求标头（有些用户可能是未折叠的，有些用户可能是折叠的）。\n折叠状态：如图我的就是折叠状态，这个时候，打开请求标头，往下滑一小段距离，就可以看到一个Cookie的东西，我们把他后面的内容全部复制下来，注意是全部复制下来。这个就是我们要的内容，然后你就可以进入下一步3.3了。\n展开状态：还有相当一部分用户打开之后会是展开状态，有一大堆的东西，这些标头全部展开了，怎么办呢？还是一样的，我们只需要往下滑，还是去找Cookie的字眼，这个东西很长，所以他在的地方，一般会很长很长。所以还是很好找的。\n注意，是 Request Headers 里的 cookie。不要复制 Response Headers 里的 set-cookie。\n你可以复制整行：\ncookie: ttwid=...; sid_guard=...; sessionid=... 也可以只复制冒号后面的值：\nttwid=...; sid_guard=...; sessionid=... Simple Live 都能识别。\n3.3 抖音粘贴到 Simple Live 在 Simple Live 里打开：\n设置 -\u0026gt; 账号管理 -\u0026gt; 抖音直播 -\u0026gt; Cookie 登录 把刚才复制的内容粘贴进去，点确定。一般是7000多个字符，如果出现了有效期，那么说明你应该是成功了。\n保存后，账号管理页会显示一个摘要。如果 Cookie 里有 sid_guard，应用会尝试解析一个预计有效期。这个时间只能作参考，因为退出登录、改密码、账号风控都可能让 Cookie 提前失效。\n如果显示“有效期无法判断”，也不一定代表不能用，只是 Cookie 里没有能被当前逻辑解析的标准过期字段。\n3.4 手机怎么办？ 手机端也是一样的，这个Cookie的导入方法、使用方法都是通用的，只是一个传递的问题。大部分人可能想通过QQ微信来传播，但是QQ微信一般对于消息的长度有限制，因此，我给手机新增了一个使用文件导入。\n只需要你把你刚才电脑上搞到的Cookie，保存为一个txt文件，然后保存，其他什么都不用做，直接把这个文件丢给手机，然后手机使用这个来导入就可以了。\n至此，大功告成。\n四、快手 Cookie 获取和导入 4.1 快手一定要登录才有弹幕吗 99%没有。想让 Simple Live 里快手弹幕更稳定：建议导入完整 Cookie。\n4.2 快手 Cookie 要复制哪一个 快手建议复制 live.kuaishou.com 的完整 Cookie。\n你可能会看到很多字段，例如：\ndid=...; didv=...; userId=...; kuaishou.live.bfb1s=...; kwfv1=... 字段名可能会变，不需要逐个理解。重点是复制完整 Cookie，而不是只复制某一个字段。\n快手弹幕还会用到一类弹幕签名 / 凭证。当前 Simple Live 会优先使用 Cookie 里的 kwfv1 自动生成弹幕签名；如果缺少 kwfv1，应用也会保存 Cookie，但可能提示：\nCookie 已保存，但缺少 kwfv1，弹幕可能需要重新网页登录 这不是说 Cookie 一定没用，而是提醒弹幕链路可能不完整。遇到这种情况，建议重新登录快手网页并重新复制完整 Cookie。\n4.3 电脑端获取快手 Cookie 建议用电脑端 Chrome 或 Edge。\n打开快手直播网页：\nhttps://live.kuaishou.com/ 登录快手账号。如果页面弹验证码，先完成验证。手机快手打开搜索栏，搜索的左边有个摄像头打开右滑可以扫一扫登录。\n按 F12 打开开发者工具。如果没反应，可以试 Ctrl + Shift + I。快手的主页https://www.kuaishou.com/禁止了F12和Ctrl + Shift + I，但是我们仍然可以通过右上方（edge浏览器为例） 三点——设置——开发人员选项来打开。\n重要 但是快手的直播页 https://live.kuaishou.com 是没有这些限制的。\n点上方的 Network，中文浏览器里一般叫“网络”。如图，我们直接去这个userFollowCount，然后把右边的cookie整个复制下来。\n你可以复制整行：\ncookie: did=...; didv=...; userId=...; kwfv1=... 也可以只复制冒号后面的值：\ndid=...; didv=...; userId=...; kwfv1=... Simple Live 会尽量从你粘贴的内容里提取 Cookie。\n4.4 桌面端导入快手 Cookie 在 Simple Live 桌面端里打开：\n设置 -\u0026gt; 账号管理 -\u0026gt; 快手直播 -\u0026gt; 浏览器登录后粘贴 Cookie 应用会尝试打开系统浏览器，你登录快手后，回到 Simple Live 粘贴完整 Cookie 即可。\n也可以直接打开：\n设置 -\u0026gt; 账号管理 -\u0026gt; 快手直播 -\u0026gt; Cookie 登录 然后手动粘贴 live.kuaishou.com 的完整 Cookie。\n4.5 手机端导入快手 Cookie 手机上直接粘贴超长 Cookie 很容易失败：输入框长度、剪贴板、聊天软件转发，都可能把内容截断。\n推荐流程是：\n在电脑上新建一个文本文件，例如：\nkuaishou-cookie.txt 把完整 Cookie 粘进去。\n保存文件，最好用 UTF-8。\n通过微信文件传输、QQ、网盘、数据线等方式传到手机。\n手机打开 Simple Live：\n设置 -\u0026gt; 账号管理 -\u0026gt; 快手直播 -\u0026gt; 从文件导入 Cookie 选择这个 txt 文件。\n文件里可以是纯 Cookie，也可以是 Cookie: xxx，也可以是整段 Request Headers。应用会从里面提取 Cookie，并尝试读取快手弹幕需要的凭证。\n4.6 手机端 Web 登录 移动端 Simple Live 里也提供快手 Web登录：\n设置 -\u0026gt; 账号管理 -\u0026gt; 快手直播 -\u0026gt; Web登录 这个入口会在 App 内打开快手网页，登录后自动读取 Cookie，并尝试读取本地的 kwfv1 凭证。\n如果 Web 登录能正常完成，优先用这个方式；如果验证码、网页兼容性或网络环境导致登录不顺，再改用电脑抓 Cookie + 手机文件导入。\n4.7 快手 Cookie 有效期为什么无法判断 快手 Cookie 的有效期不一定能像抖音那样稳定解析。\n原因是：\n手动从 Request Headers 复制出来的 Cookie 通常只有 key=value，不包含浏览器内部保存的过期时间。 expires / max-age 这类信息通常出现在 Set-Cookie 或浏览器 Cookie 存储里，不一定会出现在请求头 Cookie 里。 快手不同字段的有效期不完全一致，风控、验证码、退出登录也可能让 Cookie 提前失效。 所以“有效期无法判断”的意思只是：\n应用没有拿到可可靠解析的过期时间。 它不等于 Cookie 不能用。只要弹幕、搜索或需要登录态的功能能正常工作，就可以继续用。等某天失效后，再重新登录并导入即可。\n五、斗鱼 Cookie 获取和导入 我们打开 \u0026lt;www.douyu.com\u0026gt;，随便打开一个直播间，主页推荐的这个也够了。\n我们到网络——Fetch/XHR——左侧找到房间号——里面就有一个Cookie的标头——复制下来，导入到SimpleLive，如图去做。\n六、如果浏览器显示成两行 有些复制方式会变成这样：\ncookie ttwid=...; sid_guard=...; sessionid=... 或者：\ncookie did=...; didv=...; kwfv1=... 也没关系。Simple Live 做了兼容，会识别 cookie 下一行的内容。\n也支持你把整段请求头都复制进去，例如：\naccept: application/json accept-language: zh-CN,zh;q=0.9 cookie: key1=value1; key2=value2; key3=value3 referer: https://live.kuaishou.com/ user-agent: Mozilla/5.0 ... 应用会从里面提取 cookie 那一行。\n七、TV 怎么办 TV 端不适合直接在设备上抓 Cookie。\n原因很简单：TV 上网页登录体验很差，很多情况下也没法正常完成扫码、验证码、复制 Cookie 这些动作。\n推荐做法是：\n电脑或手机主 App 获取完整 Cookie -\u0026gt; 在主 App 保存 -\u0026gt; 通过同步功能同步到 TV 如果你要用抖音搜索，建议同步完整抖音 Cookie。\n如果你要让快手弹幕更稳定，建议同步完整快手 Cookie。\n八、为什么 Android 会报 HEAD 请求失败 之前 Android 上有一个容易误导的问题：同一个抖音 Cookie，Windows 能用，Android 搜索时报：\n发送HEAD请求失败 原因是搜索前会先对抖音域名发一个 HEAD 请求，尝试补一些网页 Cookie。Android 网络环境、系统 TLS、服务端策略都有可能让这个 HEAD 请求失败。\n后来 Simple Live 改了兜底逻辑：如果你本地已经保存了完整 Cookie，HEAD 失败时会继续用已保存 Cookie 请求搜索。\n所以如果你还遇到类似问题，先确认自己导入的是完整 Cookie，不要只导入 ttwid。\n九、Cookie 会失效吗 会。\nCookie 会过期。常见失效原因有：\n你在浏览器里退出了账号登录。 修改密码或账号安全状态变化。 平台服务端主动让登录态过期。 Cookie 本身过期。 账号触发风控，需要重新验证。 网络代理、验证码、人机校验导致当前 Cookie 暂时不可用。 如果某天搜索、弹幕或登录态相关功能突然不能用了，最直接的处理方式是：\n重新在电脑浏览器登录对应平台 -\u0026gt; 重新复制完整 Cookie -\u0026gt; 重新粘贴或从文件导入 十、几个常见错误 10.1 只填 ttwid 表现：\n抖音播放可能还能用，搜索不稳定或提示需要登录 处理：\n重新复制完整 Request Headers Cookie 10.2 快手缺少 kwfv1 表现：\nCookie 能保存，但快手弹幕仍然不稳定，或者提示缺少 kwfv1 处理：\n重新登录 live.kuaishou.com，完成验证码后重新复制完整 Cookie，或使用移动端 Web 登录 10.3 复制了 set-cookie 表现：\n看起来有 Cookie，但字段很少，搜索或弹幕还是失败 处理：\n去 Request Headers 里复制 cookie，不要复制 Response Headers 里的 set-cookie 10.4 复制内容被截断 表现：\n电脑能用，手机粘贴后不能用 处理：\n把 Cookie 保存成 txt 文件，传到手机后用“从文件导入 Cookie” 10.5 登录后没有刷新 Network 表现：\nNetwork 里看到的还是登录前请求，Cookie 不完整 处理：\n登录成功后保持开发者工具打开，再刷新一次页面 10.6 把 Cookie 发给别人测试 这个不要做。\nCookie 接近登录凭据。别人拿到后，至少在一段时间内可能可以用你的登录态请求接口。遇到问题可以描述现象，不要把完整 Cookie 发出来。\n十一、总结 获取 Cookie 这件事，最关键的是：\n要登录后的完整 Cookie 要复制 Request Headers 里的 cookie 不要只复制某一个字段 抖音：不要只复制 ttwid。\n快手：优先完整 live.kuaishou.com Cookie，弹幕相关尽量保证有 kwfv1。\n电脑端复制最方便，手机端建议用文件导入，TV 端建议从主 App 同步。\n如果以后平台网页改版，开发者工具的位置可能会变，但原理不会变：浏览器能正常访问，是因为请求里带着登录态；Simple Live 要调用同类能力，也需要带着同一份登录态。\n","permalink":"https://june6699.github.io/posts/simple-live-%E6%8A%96%E9%9F%B3-cookie-%E8%8E%B7%E5%8F%96%E5%92%8C%E5%AF%BC%E5%85%A5%E6%95%99%E7%A8%8B/","summary":"\u003ch2 id=\"一前言\"\u003e一、前言\u003c/h2\u003e\n\u003cp\u003e本文教程供 \u003ca href=\"https://github.com/June6699/dart_simple_live\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eJune6699/dart_simple_live\u003c/a\u003e\n 及其其他类似项目使用，可以让他拥有抖音平台、快手平台、斗鱼平台的更多功能。具体优点如下：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e抖音：有 Cookie 就可以支持搜索主播，对于并发限制更加宽松；\u003c/li\u003e\n\u003cli\u003e快手：有 Cookie 就可以支持看到弹幕\u003c/li\u003e\n\u003cli\u003e斗鱼：有 Cookie 就可以免于斗鱼对匿名用户的最高画质限制\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSimple Live 里抖音和快手都可以配置 Cookie，但两家的用途和表现不完全一样。\u003c/p\u003e","tags":["技术","技术/教程","技术/开源"],"title":"Simple Live 抖音/快手/斗鱼 Cookie 获取和导入教程"},{"content":"一、起因 这次发 Simple Live v1.12.4，表面上看是补了一堆功能：弹幕过滤、抖音 Cookie、WebDAV、Windows 全屏、Android 横竖屏、小窗、TV 包。\n真正花时间的地方，基本都藏在几个很难一眼看出根因的问题里。\n比如 Windows 最大化后进全屏，边缘会错位。\n比如 WebDAV 明明能上传，恢复时却拉不下来。\n比如弹幕过滤如果写得太直，直播间弹幕一多就开始拖后腿。\n这些问题看起来零散，处理起来都绕不开同一件事：要拆状态，要看时序，要知道是哪一层出了问题。\n最后主要动了三块：\nWindows 全屏：最大化窗口 -\u0026gt; 全屏窗口的状态切换 弹幕过滤：关键词 / 用户屏蔽 / 重复弹幕去重 WebDAV 恢复：远端 zip 下载、解压、导入 下面按这三块写一下。\n二、Windows 全屏牵着一串窗口状态 最开始以为 Windows 全屏就是：\nawait windowManager.setFullScreen(true); 结果用户测出来一个很具体的问题：普通窗口双击全屏没问题，但如果窗口已经最大化，再双击进入全屏，边缘会错位，有时候还会在一秒左右闪出窗口框。\n这个现象很像 setFullScreen(true) 成功了，但 Windows 的窗口非客户区状态没有完全清掉。标题栏、边框、阴影这些东西，逻辑上已经不该出现了，但窗口管理器还留着一点旧状态。\n这段现在在：\nsimple_live_app/lib/modules/live_room/player/player_controller.dart:436 现在的处理是：如果进入全屏前已经最大化，先把窗口从最大化态退出来。\n_windowMaximizedBeforeFullScreen = await windowManager.isMaximized(); if (_windowMaximizedBeforeFullScreen) { await windowManager.restore(); await _waitForWindowMaximizedState(false); await windowManager.setSize(const Size(1280, 720)); await windowManager.center(); await Future.delayed(const Duration(milliseconds: 240)); } await windowManager.setFullScreen(true); await _waitForWindowsFullScreenState(true); await _applyWindowsFullScreenChrome(); 这几步看着有点绕，但每一步都有用：\nrestore()：先从最大化态退出来。 _waitForWindowMaximizedState(false)：等系统真的完成状态切换，不靠猜。 setSize(1280, 720) 和 center()：给窗口一个正常尺寸，避免从最大化矩形直接跳全屏。 setFullScreen(true)：这时再进入全屏。 _waitForWindowsFullScreenState(true)：等 windowManager 确认全屏状态。 _applyWindowsFullScreenChrome()：最后再处理边框、阴影、标题栏。 全屏后的窗口外观单独封了一层：\nFuture\u0026lt;void\u0026gt; _applyWindowsFullScreenChrome() async { if (!Platform.isWindows) { return; } try { await windowManager.setAsFrameless(); await windowManager.setResizable(false); await windowManager.setHasShadow(false); await windowManager.setTitleBarStyle(TitleBarStyle.hidden); } catch (e) { Log.logPrint(e); } } 这里处理的是 Windows 的窗口“壳”。全屏不只是画面铺满，还要把窗口框、阴影、标题栏这些东西一起压下去。\n后来又补了一次延迟重放：\nunawaited( Future.delayed(const Duration(milliseconds: 900), () async { if (!fullScreenState.value || smallWindowState.value) { return; } await _applyWindowsFullScreenChrome(); }), ); 这个是为了解决“一秒后窗口框又出来”的问题。Windows / Flutter 桌面窗口状态切换有延迟。有些状态在 setFullScreen(true) 返回后还会被系统再刷一遍，所以只做一次无边框处理不够。延迟补一次，才算把后面的回弹压住。\n退出全屏时也不能只 setFullScreen(false)。如果进入前是最大化，退出后还要恢复最大化；如果边界缓存没刷新，还要轻推一下尺寸：\nawait windowManager.setFullScreen(false); await _waitForWindowsFullScreenState(false); await windowManager.setResizable(true); await windowManager.setHasShadow(true); await windowManager.setTitleBarStyle(TitleBarStyle.normal); await _refreshWindowsWindowBounds(); if (_windowMaximizedBeforeFullScreen) { await windowManager.maximize(); await _waitForWindowMaximizedState(true); } _refreshWindowsWindowBounds() 的做法很朴素：尺寸加 1，再设回去。\nfinal nudgedSize = Size(size.width + 1, size.height + 1); await windowManager.setSize(nudgedSize); await windowManager.setSize(size); 这种代码看起来不优雅，但桌面窗口问题有时候就是这样。这里面对的是系统窗口管理器的状态缓存，不能只按 Flutter widget 树的思路看。\n这次也一起修了 Android 的一个横竖屏问题。退出全屏时原来是释放所有方向：\nawait SystemChrome.setPreferredOrientations(DeviceOrientation.values); 这在某些手机上会导致退出全屏后还停在横屏。现在退出全屏时明确回到竖屏：\nawait SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, ]); 这段在 player_controller.dart:735。从横屏全屏退回普通页面时，DeviceOrientation.values 这种“恢复默认”反而容易把横屏状态留下。\n三、弹幕过滤不能只写 contains 弹幕过滤最早可以很简单：用户设置几个关键词，来了弹幕以后 contains 一下。\n但直播间里的弹幕频率高、来源杂，还有表情、富文本、图片字段。过滤逻辑如果写得太随意，会有两个问题：\n误杀太多，正常弹幕被吞。 开销太大，高弹幕量房间拖播放器。 这次的入口在：\nsimple_live_app/lib/modules/live_room/live_room_controller.dart:1036 弹幕进入后先按顺序处理：\nmsg = _sanitizeLiveMessage(msg); if (msg.type == LiveMessageType.chat) { if (_isUserShielded(msg.userName) || isTempMutedUser(msg.userName)) { return; } if (_isKeywordShielded(msg)) { return; } if (_isDuplicateDanmu(msg)) { return; } messages.add(msg); } 顺序是有意排的。\n用户屏蔽最便宜，先处理。关键词其次。重复弹幕去重最后，因为它要构建指纹、维护窗口。\n关键词和正则 关键词过滤在 live_room_controller.dart:201。\n普通关键词直接当字符串；如果用户写成 /.../，就按正则处理：\nif (Utils.isRegexFormat(keyword)) { String removedSlash = Utils.removeRegexFormat(keyword); try { pattern = RegExp(removedSlash); } catch (e) { Log.d(\u0026#34;正则屏蔽词 $keyword 无法编译，已跳过\u0026#34;); } } else { pattern = keyword; } if (pattern != null \u0026amp;\u0026amp; msg.message.contains(pattern)) { return true; } 这里有个小细节：正则写错不能让弹幕系统崩。用户输入本来就不可控，屏蔽词写错，最多跳过这一条规则。\n用户屏蔽要分平台 用户屏蔽也不能只有一个全局名单。直播平台之间用户名可能重复，虎牙屏蔽一个人，不一定想把 B 站同名用户也屏蔽掉。\n所以设置层加了站点维度：\nsimple_live_app/lib/app/controller/app_settings_controller.dart:1169 bool shouldShieldUser(String userName, {String? siteId}) { if (!danmuShieldEnable.value || !danmuUserShieldEnable.value) { return false; } return isUserShielded(userName, siteId: siteId); } 实际存储时分成“全平台”和具体平台分组。直播间里点用户名，可以直接屏蔽当前平台，也可以临时禁言。这样比一个大名单更可控。\n重复弹幕去重 重复弹幕过滤这块，最不想写成“每来一条弹幕，就扫描最近 N 条”。因为直播间弹幕频率高的时候，这种 O(N) 小循环会一直跑。\n现在的逻辑在：\nsimple_live_app/lib/modules/live_room/live_room_controller.dart:227 这里用的是一个队列加一个计数表：\nfinal duplicate = _recentDanmuCounts.containsKey(fingerprint); _recentDanmuFingerprints.addLast(fingerprint); _recentDanmuCounts[fingerprint] = (_recentDanmuCounts[fingerprint] ?? 0) + 1; 判断重复只看 Map 里有没有这个指纹，平均 O(1)。新指纹进队列，同时计数加一。\n窗口大小和步长来自设置：\nfinal windowSize = settings.danmuDedupeWindow.value.clamp(1, 100); final step = settings.danmuDedupeStep.value.clamp(1, 20); 对应设置在：\nsimple_live_app/lib/app/controller/app_settings_controller.dart:1703 var danmuDedupeWindow = 10.obs; void setDanmuDedupeWindow(int e) { final value = e.clamp(1, 100).toInt(); danmuDedupeWindow.value = value; } var danmuDedupeStep = 2.obs; void setDanmuDedupeStep(int e) { final value = e.clamp(1, 20).toInt(); danmuDedupeStep.value = value; } 窗口默认 10，步长默认 2。实际运行时按步长批量清理，避免每一条弹幕都触发裁剪窗口。这样能少一点高频操作。\n清理时除了从队列里删，还要同步扣计数：\nwhile (shouldPrune \u0026amp;\u0026amp; _recentDanmuFingerprints.length \u0026gt; windowSize) { final removed = _recentDanmuFingerprints.removeFirst(); final count = (_recentDanmuCounts[removed] ?? 0) - 1; if (count \u0026lt;= 0) { _recentDanmuCounts.remove(removed); } else { _recentDanmuCounts[removed] = count; } } 否则 Map 会越看越大，长时间开直播间就会留下很多过期指纹。\n指纹不能只看正文 弹幕现在不只是 message 字符串。B 站、抖音这类平台会有富文本片段、表情图、图片 URL。只看正文，会漏掉不少重复内容。\n指纹构建在 live_room_controller.dart:263：\nfinal message = _normalizeDanmuFingerprintPart(msg.message); if (message.isNotEmpty) { parts.add(\u0026#34;m:$message\u0026#34;); } for (final span in msg.spans ?? const \u0026lt;LiveMessageSpan\u0026gt;[]) { final text = _normalizeDanmuFingerprintPart(span.text ?? \u0026#34;\u0026#34;); final imageUrl = _normalizeDanmuFingerprintPart(span.imageUrl ?? \u0026#34;\u0026#34;); if (text.isNotEmpty) { parts.add(\u0026#34;t:$text\u0026#34;); } if (imageUrl.isNotEmpty) { parts.add(\u0026#34;i:$imageUrl\u0026#34;); } } for (final imageUrl in msg.imageUrls ?? const \u0026lt;String\u0026gt;[]) { final value = _normalizeDanmuFingerprintPart(imageUrl); if (value.isNotEmpty) { parts.add(\u0026#34;u:$value\u0026#34;); } } 最后拼上用户名：\nreturn \u0026#34;$userName\\u0001${parts.join(\u0026#34;\\u0002\u0026#34;)}\u0026#34;; 这里故意把用户名放进指纹。因为“不同观众发同一句话”不一定是刷屏，可能只是直播间气氛到了。现在的去重只处理“同一用户最近重复刷同一内容”。\n另外文本会先规范化：\nreturn value.trim().replaceAll(RegExp(r\u0026#34;\\s+\u0026#34;), \u0026#34; \u0026#34;); 这能挡住一些靠多个空格绕过重复判断的情况。\n四、WebDAV 恢复：上传成功不代表恢复成功 WebDAV 的问题更典型：用户反馈“能上传，但恢复不下来”。\n这类问题很烦，因为“上传成功”很容易让人误以为 WebDAV 配置没问题。实际上上传和下载走的是两段链路。服务端对 PUT、GET、流式读取、Content-Length 的处理都可能不一样。\n恢复代码在：\nsimple_live_app/lib/modules/sync/remote_sync/webdav/remote_sync_webdav_controller.dart:248 旧思路更偏向直接读远端文件到内存。后来改成先下载到临时文件：\nfinal tempDir = await getTemporaryDirectory(); final downloadPath = join( tempDir.path, \u0026#34;simple_live_webdav_backup.zip\u0026#34;, ); final downloadFile = File(downloadPath); if (downloadFile.existsSync()) { downloadFile.deleteSync(); } await davClient.client.read2File(davClient.backupFile, downloadPath); if (!downloadFile.existsSync() || downloadFile.lengthSync() \u0026lt;= 0) { throw const FormatException(\u0026#34;WebDAV 备份文件下载失败\u0026#34;); } final data = await downloadFile.readAsBytes(); final archive = _decodeWebDavBackupArchive(data); 这个改动不花哨，但稳。\n它把链路拆成了几步：\n远端 backup.zip -\u0026gt; 下载成本地临时文件 -\u0026gt; 检查文件存在和大小 -\u0026gt; 本地 readAsBytes() -\u0026gt; ZipDecoder 解压 -\u0026gt; 导入配置 这样一来，如果失败，至少知道失败在哪一段。是没下载下来，还是 zip 解压失败，还是导入失败。\n解压本身很简单：\nArchive _decodeWebDavBackupArchive(List\u0026lt;int\u0026gt; data) { final zipDecoder = ZipDecoder(); return zipDecoder.decodeBytes(data); } 但另一个坑在 isolate。\n之前想把解压丢到 Isolate.run，避免 UI 卡顿。想法没错，但 Dart isolate 有个限制：跨 isolate 的东西必须可发送。结果闭包里间接捕获了 RemoteSyncWebDAVController、DAVClient 这类对象，它们不能被发到另一个 isolate，于是恢复时会报类似：\nobject is unsendable 最后这里没有继续硬上 isolate，恢复流程改成在当前 isolate 里顺序执行。这个备份 zip 通常不大，相比“理论上更异步”，先把恢复链路做稳定更重要。\n新备份里如果有完整配置包，就走：\nfinal summary = await ProfileBackupService.instance.importProfileJson( utf8.decode(profileFile.content), overwrite: true, options: ProfileImportOptions( settings: true, follows: isSyncFollows.value, histories: isSyncHistories.value, shields: isSyncBlockWord.value, shieldPresets: isSyncBlockWord.value, ), ); 旧备份没有 profile.json，就继续按老 JSON 文件逐个恢复：\nfor (ArchiveFile file in archive) { await _recovery(file); } 最后不管成功失败，都关 loading，并清掉临时 zip：\nfinally { SmartDialog.dismiss(); try { final tempDir = await getTemporaryDirectory(); final downloadFile = File(join(tempDir.path, \u0026#34;simple_live_webdav_backup.zip\u0026#34;)); if (downloadFile.existsSync()) { downloadFile.deleteSync(); } } catch (_) {} } 这也是后来我越来越在意的一点：同步类功能失败时，不能只在日志里失败。用户至少要看到 loading 结束，看到一个能理解的错误。\n五、修到最后，看的都是状态边界 这三块看起来不相关：\nWindows 全屏是桌面窗口。 弹幕过滤是数据结构。 WebDAV 恢复是网络和文件。 但修的时候，思路很像。\n第一，别相信“一个 API 调用就是一个完整状态”。\nsetFullScreen(true) 只能算发起全屏请求。后面还有窗口框、阴影、标题栏、最大化状态缓存。\n第二，别让高频路径做线性蠢活。\n弹幕每秒可能很多条。关键词可以简单，但重复去重不能每条都扫一遍最近列表。队列加计数表不复杂，但能把这个路径从“看弹幕量脸色”变成稳定的 O(1) 判断。\n第三，别把远端流当本地文件用。\nWebDAV 服务五花八门。直接读流看起来省事，但出了问题很难判断。下载到临时文件，再检查，再解压，步骤多了一点，定位清楚很多。\n第四，别为了“更高级”牺牲可恢复性。\nIsolate.run 听起来比当前 isolate 解压更漂亮，但一旦捕获了不可发送对象，恢复链路直接断。这里先让功能稳下来，比写一个看起来更现代的异步方案重要。\n六、收尾 这次修完以后，我对这种问题的判断更保守了一点。\n如果一个 bug 只在“最大化后再全屏”出现，问题多半在状态切换路径，里面还有旧状态没清干净。\n如果一个功能“能上传但不能恢复”，那就不能只看登录和上传，要把下载、文件、解压、导入拆开。\n如果一个过滤逻辑要跑在直播间弹幕流里，就要按高频路径来写。\n很多修复最后没有什么大招，就是把状态拆细，把路径走完整，把失败点暴露出来。\n这听起来不酷，但对一个每天要被人打开的工具来说，够用了。\n","permalink":"https://june6699.github.io/posts/simple-live-%E8%BF%99%E6%AC%A1%E5%87%A0%E4%B8%AA%E5%A4%A7%E5%9D%91-%E5%85%A8%E5%B1%8F%E5%BC%B9%E5%B9%95%E8%BF%87%E6%BB%A4%E5%92%8Cwebdav%E6%81%A2%E5%A4%8D/","summary":"\u003ch2 id=\"一起因\"\u003e一、起因\u003c/h2\u003e\n\u003cp\u003e这次发 Simple Live \u003ccode\u003ev1.12.4\u003c/code\u003e，表面上看是补了一堆功能：弹幕过滤、抖音 Cookie、WebDAV、Windows 全屏、Android 横竖屏、小窗、TV 包。\u003c/p\u003e","tags":["技术","技术/Flutter","技术/开源"],"title":"Simple Live 这次几个大坑：全屏、弹幕过滤和 WebDAV 恢复"},{"content":"一、起因 今天本来只是想把两个机器人跑起来。\n一个放在 QQ 里，走 OpenClaw；一个放在微信里，用 wangrongding/wechat-bot。名字也很随意，叫“徐子昂昂”。我的预期并不复杂：群里 @ 它，它能回；前面刚聊过的东西，它别下一句就忘；微信这边再加一个 /生图，后面接图片 API。\n结果真正折腾起来，最麻烦的地方落在了“好了”这两个字上：到底哪一层算好了？\n进程还在，不等于它登录了。\n扫码通过，不等于 Web WeChat 初始化成功。\nQQ channel connected，不等于模型能回复。\n图片接口说生成成功，不等于微信里真的发出了图。\n今天大部分时间，都花在把这些“看起来好了”的状态拆开。\n后来它确实跑起来了。微信群里可以直接 /生图，也可以 /新闻 拉两条早报：\n也能接住一些更随手的聊天，比如让它模仿李白写七言诗。效果不一定多正经，但至少说明消息链路、模型调用和群回复都通了：\n二、两条线 最后服务器上跑了两套东西。\nQQ 这边走 OpenClaw：\nQQ 群消息 -\u0026gt; OpenClaw QQ channel -\u0026gt; OpenClaw Gateway -\u0026gt; 模型 -\u0026gt; QQ 回复 微信这边是另一路：\n微信群消息 -\u0026gt; wechaty-puppet-wechat4u -\u0026gt; /opt/wechat-bot -\u0026gt; 模型 -\u0026gt; 微信回复 聊天模型最后统一到 DeepSeek 的 OpenAI-compatible 接口。生图单独走图片接口，不和聊天混在一起。\n这个拆开以后，排查会清楚很多。比如微信登录失败，和聊天模型没有关系；生图失败，也不该影响普通聊天；QQ 显示 connected，也只能说明 QQ channel 这一段还活着。\n三、QQ bot 的第一个误会 OpenClaw 的配置在：\n/root/.openclaw/openclaw.json Gateway 跑在 127.0.0.1:18789，用 systemd user service 管着。看状态很简单：\nopenclaw gateway status openclaw channels status --deep 一开始很容易被 running, connected 这种字眼骗到。QQ Bot connected 只能说明 QQ 这层接上了，不能说明后面的模型能用。模型接口挂了、key 不对、上游抽风，QQ 仍然可能看起来“在线”，然后一问就回：\n⚠️ Something went wrong while processing your request. 所以后来我给自己定了一个更硬的标准：每次改模型，都要让 OpenClaw 自己跑一次模型调用。\ntimeout 75 openclaw infer model run --gateway \\ --model deepseek-openai/deepseek-v4-flash \\ --prompt \u0026#39;只回复OK\u0026#39; \\ --json 这里能返回 OK，再谈 QQ bot 能不能用。否则 channel 在线只能说明通道还在，模型链路未必可用。\nQQ 的上下文也补了一下。OpenClaw 里显式设了群聊历史窗口：\n{ \u0026#34;messages\u0026#34;: { \u0026#34;groupChat\u0026#34;: { \u0026#34;historyLimit\u0026#34;: 80, \u0026#34;visibleReplies\u0026#34;: \u0026#34;automatic\u0026#34; } } } 这算不上多高级的记忆系统，主要是别让它每句话都像第一次见面。\n四、微信 bot 先跑起来 微信 bot 在：\n/opt/wechat-bot 配置文件是：\n/opt/wechat-bot/.env 启动我用 tmux：\ncd /opt/wechat-bot tmux new-session -d -s wechat-bot \\ \u0026#39;cd /opt/wechat-bot \u0026amp;\u0026amp; npm run start -- start --serve ChatGPT 2\u0026gt;\u0026amp;1 | tee -a wechat-bot.log\u0026#39; 日志就在：\n/opt/wechat-bot/wechat-bot.log 这里有个名字容易误导：启动参数里的 ChatGPT 是这个项目内部的 service 名，不代表一定连 OpenAI 官方。实际我把它接到了 OpenAI-compatible 接口：\nSERVICE_TYPE=\u0026#39;ChatGPT\u0026#39; OPENAI_PROXY_URL=\u0026#39;https://api.deepseek.com\u0026#39; OPENAI_MODEL=\u0026#39;deepseek-v4-flash\u0026#39; OPENAI_API_STYLE=\u0026#39;chat\u0026#39; OPENAI_TIMEOUT_MS=\u0026#39;45000\u0026#39; WECHAT_CONTEXT_TURNS=\u0026#39;8\u0026#39; key 不写在文章里。真正的 key 只放服务器 .env，文档里最多写 \u0026lt;CHAT_API_KEY\u0026gt;。\n原项目的上下文比较弱，基本是当前问题进、当前回答出。群聊里这样很奇怪，前面刚说过的事情，下一句就像失忆。所以后来在 src/wechaty/sendMessage.js 里加了一个简单的 per-room/per-DM 历史：\nroom:群名 dm:联系人 WECHAT_CONTEXT_TURNS='8'，大概保留最近几轮。它只放短期上下文，进程重启就没了，但日常聊天够用。为了防止上下文串味，又加了 /清空上下文。\n五、模型接口要在服务器上测 今天试过好几个中转接口。最容易出错的判断是：我本机能用，所以服务器也能用。\n实际情况经常不一样。Windows 上 Codex、Claude Code 能跑，不代表 june-server 出口到那个站也稳。有的接口在服务器上 TLS 握手超时，有的能连上但上游返回：\nupstream_error: Upstream service temporarily unavailable 所以每次换模型，我现在会先在远端测：\ncurl -sS https://api.deepseek.com/models \\ -H \u0026#34;Authorization: Bearer \u0026lt;CHAT_API_KEY\u0026gt;\u0026#34; 这次 DeepSeek 给出的模型很少：\ndeepseek-v4-flash deepseek-v4-pro deepseek-chat 也能用，但实际映射到 deepseek-v4-flash。deepseek-reasoner 有一次返回空 content，不适合直接拿来当群聊 bot。最后选 deepseek-v4-flash，主要是因为群聊更看重响应速度和稳定性，没必要每句都走深度推理。\n六、图片生成比想象中麻烦 微信的 /生图 单独走图片接口：\nIMAGE_API_URL=\u0026#39;API\u0026#39; IMAGE_MODEL=\u0026#39;gpt-image-2\u0026#39; IMAGE_API_STYLE=\u0026#39;images\u0026#39; IMAGE_TIMEOUT_MS=\u0026#39;180000\u0026#39; 一开始接口能返回图片 URL，我以为事情结束了。结果服务器去下载那个图片 URL 时经常卡住，或者下载到一半。于是微信里就出现很尴尬的情况：bot 说生成好了，但图没发出来。\n后来改成让图片接口尽量返回 b64_json：\n{ \u0026#34;response_format\u0026#34;: \u0026#34;b64_json\u0026#34; } 拿到 base64 后，直接在服务器本地落盘，再用 jimp 压成 JPEG，最后通过：\nFileBox.fromFile(imagePath) 发给微信。\n这个方案朴素，但比“拿到远端 URL 再下载一次”稳。微信最终要发的是文件，那就尽量把文件握在自己手里。\n另一个小改动也很重要：不要先发“生成好了”。现在是图发出去就只发图；图没发出去，才提示“图片生成了，但发送到微信失败了”。否则用户看到一句成功提示，下面却没有图，会很迷惑。\n七、给 /生图 加一道门 生图不能什么都让群里试。于是加了一个本地审核，拦一下明显不该生成的提示词：\n色情或裸露 涉政 暴力血腥 赌博毒品 违法犯罪 命中后直接拒绝，不调用图片 API，也不花额度。\n这套审核不算完美安全方案，只是第一道门。对群 bot 来说，这道门必须有。因为总会有人发一些边界词测试，bot 不应该把这些东西继续转给上游。\n八、扫码这件事最折腾 微信登录态文件是：\n/opt/wechat-bot/WechatEveryDay.memory-card.json 这个名字来自代码里的：\nWechatyBuilder.build({ name: \u0026#39;WechatEveryDay\u0026#39; }) 换微信号登录时，要先停掉 tmux，备份并删掉这个 memory-card，再重启：\ncd /opt/wechat-bot tmux has-session -t wechat-bot 2\u0026gt;/dev/null \u0026amp;\u0026amp; tmux kill-session -t wechat-bot || true ts=\u0026#34;$(date +%Y%m%d-%H%M%S)\u0026#34; mkdir -p .data/login-backups [ -f WechatEveryDay.memory-card.json ] \u0026amp;\u0026amp; \\ cp WechatEveryDay.memory-card.json \u0026#34;.data/login-backups/WechatEveryDay.memory-card.${ts}.json\u0026#34; rm -f WechatEveryDay.memory-card.json : \u0026gt; wechat-bot.log tmux new-session -d -s wechat-bot \\ \u0026#39;cd /opt/wechat-bot \u0026amp;\u0026amp; npm run start -- start --serve ChatGPT 2\u0026gt;\u0026amp;1 | tee -a wechat-bot.log\u0026#39; 日志里会打印 onScan:，后面是二维码 URL。后来我发现，只贴 URL 很不方便，最好直接把二维码下载成本地 PNG：\n$qr = ssh june-server \u0026#34;python3 - \u0026lt;\u0026lt;\u0026#39;PY\u0026#39; import pathlib, re text = pathlib.Path(\u0026#39;/opt/wechat-bot/wechat-bot.log\u0026#39;).read_text(errors=\u0026#39;ignore\u0026#39;) matches = re.findall(r\u0026#39;https://api\\.qrserver\\.com\\S+|https://login\\.weixin\\.qq\\.com/l/\\S+\u0026#39;, text) print(matches[-1] if matches else \u0026#39;\u0026#39;) PY\u0026#34; $qr = ($qr | Select-Object -Last 1).Trim() Invoke-WebRequest -Uri $qr -OutFile .\\wechat-login-qr.png 扫码后也不能马上放心。手机上显示“你现在可以在新设备上使用微信了”，只能说明手机授权了，不代表 bot 真的初始化成功。\n今天就遇到过这种日志：\nINFO onScan: 3(undefined) Scanned wechat4u webwxinit BaseResponse: {\u0026#34;Ret\u0026#34;:1,\u0026#34;ErrMsg\u0026#34;:\u0026#34;\u0026#34;} AssertionError [ERR_ASSERTION]: 1 == 0 这就是手机扫了，但 Web WeChat 初始化失败。真正要看的，是有没有这一行：\nContact\u0026lt;徐子昂昂\u0026gt; has logged in 后来有一次把：\nWECHAT_PUPPET_UOS=\u0026#39;true\u0026#39; 改成：\nWECHAT_PUPPET_UOS=\u0026#39;false\u0026#39; 再重新生成二维码，终于出现了 Contact\u0026lt;徐子昂昂\u0026gt; has logged in。这不一定适用于所有号，但以后遇到 webwxinit Ret=1，至少知道可以试这个方向。\n不过登录成功以后还要继续看。后面还会看到 1205 == 0、-1 == 0、AggregateError 这些 wechat4u 的同步警告。它们不一定马上让 bot 死掉，但说明这条 Web WeChat 链路并不稳。最后还是要在群里真的 @ 一句，看它能不能收到并回复。\n九、最后留下的一组检查命令 今天最后留下来的，是一组我以后会先跑的检查。\nQQ / OpenClaw：\nopenclaw gateway status openclaw channels status --deep timeout 75 openclaw infer model run --gateway \\ --model deepseek-openai/deepseek-v4-flash \\ --prompt \u0026#39;只回复OK\u0026#39; \\ --json 微信进程和登录：\ntmux ls 2\u0026gt;/dev/null || true ps -eo pid,ppid,etime,cmd | grep -Ei \u0026#39;wechat-bot|node ./cli.js|npm run start\u0026#39; | grep -v grep grep -E \u0026#39;Contact\u0026lt;.*has logged in|onScan:|has logged out\u0026#39; /opt/wechat-bot/wechat-bot.log | tail -80 微信模型：\ncd /opt/wechat-bot node --input-type=module \u0026lt;\u0026lt;\u0026#39;NODE\u0026#39; import { getGptReply } from \u0026#39;./src/openai/index.js\u0026#39; console.log(await getGptReply(\u0026#39;只回复OK\u0026#39;)) NODE 微信生图：\ncd /opt/wechat-bot node --input-type=module \u0026lt;\u0026lt;\u0026#39;NODE\u0026#39; import fs from \u0026#39;node:fs\u0026#39; import { generateImage } from \u0026#39;./src/image/index.js\u0026#39; const img = await generateImage(\u0026#39;一只白色小猫，简单线稿\u0026#39;) console.log({ ok: img.ok, filePath: img.filePath, exists: img.filePath ? fs.existsSync(img.filePath) : false, }) NODE 这些命令看着有点啰嗦，但比凭感觉判断可靠。尤其是这种聊天机器人，坏的时候经常只是某一段断了。\n十、收尾 今天最有用的经验就一句话：别急着说好了。\n先看是哪一层好了。\n进程好了，还是登录好了？\n扫码好了，还是 Web WeChat 初始化好了？\n模型好了，还是群里真的能回？\n图片生成好了，还是图片真的发出去了？\n机器人看起来像一个小玩具，真跑起来更像一串管道。每段都可能漏水。以后再修它，第一件事先问：现在坏的是哪一层。\n","permalink":"https://june6699.github.io/posts/%E6%8A%8A%E5%BE%AE%E4%BF%A1%E7%BE%A4%E9%87%8C%E7%9A%84%E5%BE%90%E5%AD%90%E6%98%82%E6%98%82%E8%B7%91%E8%B5%B7%E6%9D%A5/","summary":"\u003ch2 id=\"一起因\"\u003e一、起因\u003c/h2\u003e\n\u003cp\u003e今天本来只是想把两个机器人跑起来。\u003c/p\u003e\n\u003cp\u003e一个放在 QQ 里，走 OpenClaw；一个放在微信里，用 \u003ccode\u003ewangrongding/wechat-bot\u003c/code\u003e。名字也很随意，叫“徐子昂昂”。我的预期并不复杂：群里 @ 它，它能回；前面刚聊过的东西，它别下一句就忘；微信这边再加一个 \u003ccode\u003e/生图\u003c/code\u003e，后面接图片 API。\u003c/p\u003e","tags":["技术","技术/AI","技术/运维"],"title":"把微信群里的徐子昂昂跑起来"},{"content":"千人同茶不同味，万人同道不同心。\n不必逢人倾道理，自知心境各西东。\n自是人间多情客，何来情爱论输赢。\n是非本是立场异，得失皆如逝水流。\n世间哪有真对错，只是人心各有偏。\n浮生聚散皆天意，何必痴心问是非。\n而今悟得浮生意，独守清欢度岁华。\n这几句读下来，其实说的就是一句很简单的话：同样一杯茶，有人喝出清香，有人觉得寡淡；同一条路，有人同行一程，却未必真能同心。很多事，不必急着解释，也不必非要争个高低。每个人的经历不同，站的位置不同，看见的自然也不同。\n以前总觉得，误会要解释清楚，道理要讲明白，是非要分出对错。后来才慢慢明白，很多时候不是你说得不够清楚，而是对方并不站在你的处境里听。你讲你的委屈，他听见的是矫情；你说你的难处，他理解成借口。人心隔着人心，本来就不容易相通。\n就像最近网上很多事情，一开始大家都急着站队，几句话、几张截图，就能把一个人推到风口浪尖。等到后面信息慢慢补全，才发现事情未必是最初看到的样子。可那时候，骂也骂过了，伤害也造成了。很多“是非”，其实一半是事实，一半是立场；一半是情绪，一半是偏见。\n生活里也是这样。朋友之间因为一句话疏远，亲人之间因为一点钱生怨，感情里因为谁付出得多争输赢。可争到最后，赢了道理，往往输了关系；说尽委屈，也未必换来理解。人这一生，能遇见是缘分，能同行是福气，走散了也未必是谁错了，只是各有各的路要走。\n所以现在越来越觉得，真正的成熟，不是把所有人都说服，而是学会把心安顿好。能解释的解释，解释不了的就放下；能珍惜的珍惜，留不住的就随缘。人活到最后，求的不是处处被理解，而是自己心里有数，日子过得清净。\n浮生很短，别把太多力气耗在辩是非上。\n有些茶，冷了就别续了；有些人，远了也别追了。\n守住自己的清欢，把日子过成自己喜欢的样子，就很好。\n","permalink":"https://june6699.github.io/posts/%E4%B8%8D%E5%BF%85%E9%80%A2%E4%BA%BA%E8%AE%B2%E9%81%93%E7%90%86/","summary":"\u003cp\u003e千人同茶不同味，万人同道不同心。\u003cbr\u003e\n不必逢人倾道理，自知心境各西东。\u003cbr\u003e\n自是人间多情客，何来情爱论输赢。\u003cbr\u003e\n是非本是立场异，得失皆如逝水流。\u003cbr\u003e\n世间哪有真对错，只是人心各有偏。\u003cbr\u003e\n浮生聚散皆天意，何必痴心问是非。\u003cbr\u003e\n而今悟得浮生意，独守清欢度岁华。\u003c/p\u003e","tags":["诗","诗/杂感"],"title":"不必逢人讲道理"},{"content":"近十年来，中国人写给“所有人”的祝福，像是慢慢换了一种口气。\n早些年，我们常说的是“国泰民安”“阖家幸福”“身体健康”“万事如意”。这些词很大，也很稳，像春联，像年画，像电视里响起来的钟声。它们把一个人放回家庭、家国和岁月秩序里：家要团圆，国要安宁，人要健康，年景要好。\n后来，祝福开始变得更轻，也更贴近一个具体的人。朋友圈、弹幕、短视频和聊天框里，越来越常见的是“平安喜乐”“万事胜意”“顺遂无虞”“所行皆坦途”“所得皆所愿”。再往后，又有人喜欢写得更古雅一点：“岁岁常欢愉，年年皆胜意”“多喜乐，长安宁”“历添新岁月，春满旧山河”。这些句子未必都出自某一首确定的古诗，却带着一种古典汉语的温柔：不把愿望喊得太满，只把好事轻轻放到对方面前。\n一、从“国家好”到“日子好” 如果只看公共表达，近十年的关键词大致离不开：幸福、安康、团圆、奋斗、平安、繁荣。\n“幸福”是最稳定的底色。它不只是抽象口号，也经常落到一个个日常场景里：饭桌边的团圆、孩子的成长、老人的安康、打工人回家的车票、普通人对来年收入和生活的盼头。\n“安康”则像是疫情之后被重新擦亮的词。过去说“身体健康”，有时只是客套；后来再说“平安健康”，分量就重了许多。人们忽然明白，能正常出门、能和家人吃饭、能好好睡一觉，本身就是很大的祝福。\n“团圆”一直没有离开。春节、元宵、中秋这些节点里，中国式祝福的核心仍然是“人要回来，灯要亮着，饭要热着”。哪怕年轻人已经习惯远程工作、异地生活、视频拜年，祝福里仍会留一盏家里的灯。\n二、从“万事如意”到“万事胜意” “万事如意”是老派祝福里的常青树，端正、圆满、没有锋芒。但近几年，“万事胜意”似乎更受年轻人喜欢。\n“如意”是愿事情按照心意发生；“胜意”则更像是：愿结果比你原先想的还要好。它少一点标准答案，多一点惊喜。对于不太敢奢望的人来说，“胜意”二字尤其动人，因为它不是命令生活必须完美，而是悄悄给未来留出一点意外的好。\n与它相近的，还有“所愿皆所得”“所行皆坦途”“一路生花”。这些祝福都不再只强调宏大的成功，而更在意个体路径是否顺、心愿是否被看见、奔波是否值得。\n三、“平安喜乐”为什么动人 “平安喜乐”这四个字，几乎可以概括近十年最常见的私人祝福。\n它不求大富大贵，也不求轰轰烈烈，只求一个人免于大的惊惧，同时还能保有一点发自内心的高兴。平安是底线，喜乐是光。只有平安，没有喜乐，日子太苦；只有喜乐，没有平安，幸福又不稳。把它们放在一起，正好是普通人对好生活最朴素的定义。\n所以我们会看到很多变体：\n愿你平安喜乐，得偿所愿。\n先保有身心安稳，再慢慢抵达心中所想。\n愿你顺遂无虞，皆得欢喜。\n路上少些阻滞，心里多些明亮。\n愿你岁岁常欢愉，年年皆胜意。\n每一年都有能笑出来的时刻，每一年都比预想更好一点。\n四、“多喜乐，长安宁”的好处 “多喜乐，长安宁”这类祝福，最妙处在分寸。\n它没有说“永远快乐”。“永远”太重，也太不像真的人生。它只说“多喜乐”：愿开心的事多一点，愿难过的事少一点，愿你在疲惫生活里还能捡到一些细碎的光。\n它也没有说“从此无忧”。“无忧”近乎神话，而“长安宁”更像人间愿望：不一定没有风雨，但心有归处；不一定事事顺利，但夜里能睡得安稳；不一定日日热闹，但长久地平静、安定、被生活温柔相待。\n所以这句话比“万事如意”更松，也比“天天开心”更深。它承认人生不会全是好事，却仍然认真祝你：好的多一些，安宁久一些。\n五、这些祝福词，可以怎样分 若把近十年来常见的祝福词粗略归类，大概有几条线。\n1. 家国型 国泰民安，山河无恙。\n愿国家太平，人民安居，辽阔山河皆在安稳之中。\n家和人兴，岁稔年丰。\n愿小家和睦，人丁兴旺，也愿年景丰足。\n2. 生活型 阖家幸福，身体安康。\n最传统，也最不该被轻看的祝愿。\n烟火寻常，三餐有味。\n愿日子不必惊天动地，但有饭香，有灯火，有可依靠的日常。\n3. 青年型 前程似锦，未来可期。\n愿年轻人的路还很长，眼前的努力都通向更开阔的地方。\n所行皆坦途，所遇皆良人。\n愿奔赴时少些坎坷，也愿途中遇见善意。\n4. 温柔型 平安喜乐，顺遂无虞。\n愿你身心安稳，路上少忧。\n多喜乐，长安宁。\n愿欢喜多一点，安宁长一点。\n5. 古意型 岁岁常欢愉，年年皆胜意。\n把一年一年的日子，都说成缓慢而可靠的祝愿。\n历添新岁月，春满旧山河。\n新岁覆盖旧岁，春色仍然回到熟悉的山河上。\n六、最后，若只留一句 如果要从这些祝福里选一句写给所有人，我可能不会选最满的那句。\n“万事如意”很好，但人生很难万事都如意；“前程似锦”也很好，但并不是每个人此刻都站在前程的入口。相比之下，“多喜乐，长安宁”更像一盏小灯。它不夸口，不催促，不要求你必须成功、必须热闹、必须证明什么。\n它只是说：愿你在往后的日子里，喜乐多一些，安宁长一些。若有风雪，也有归处；若有奔波，也有饭香；若有不得已，也仍有几件小事，足以让你觉得人间值得。\n祝我们都多喜乐，长安宁。\n","permalink":"https://june6699.github.io/posts/%E8%BF%91%E5%8D%81%E5%B9%B4%E6%9D%A5%E5%86%99%E7%BB%99%E6%89%80%E6%9C%89%E4%BA%BA%E7%9A%84%E7%A5%9D%E7%A6%8F%E8%AF%8D/","summary":"\u003cp\u003e近十年来，中国人写给“所有人”的祝福，像是慢慢换了一种口气。\u003c/p\u003e\n\u003cp\u003e早些年，我们常说的是“国泰民安”“阖家幸福”“身体健康”“万事如意”。这些词很大，也很稳，像春联，像年画，像电视里响起来的钟声。它们把一个人放回家庭、家国和岁月秩序里：家要团圆，国要安宁，人要健康，年景要好。\u003c/p\u003e","tags":["随笔","词语","祝福"],"title":"近十年来，写给所有人的祝福词"},{"content":"一、问题现场 晚上在一台 Rocky Linux 8.10 机器上看进程，随手敲了个：\nhtop 结果直接崩了：\n段错误 (核心已转储) 第一反应一般会怀疑 htop 包坏了，或者 ncurses 这类终端库出了问题。先把基本信息看一遍：\nwhich htop # /usr/bin/htop cat /etc/centos-release # Rocky Linux release 8.10 (Green Obsidian) rpm -qf $(command -v htop) # htop-3.2.1-1.el8.x86_64 htop --version # htop 3.2.1 路径是系统路径，包也是 EPEL 里的正常包。于是先重装：\nsudo yum reinstall -y htop ncurses ncurses-libs 重装完成后再跑：\nhtop # 段错误 (核心已转储) 问题还在。到这里基本可以先把“软件包下载坏了”这个方向放一边。\n二、干净环境下 htop 能跑 下一步是排除配置和环境变量。先用一个尽量干净的环境启动 htop：\nmkdir -p /tmp/htop-clean-home env -i HOME=/tmp/htop-clean-home TERM=xterm-256color LANG=C LC_ALL=C /usr/bin/htop 这条命令能正常打开。\n这就很关键了：如果 htop 本体或者系统的 ncurses 库真的坏了，干净环境下也应该崩。现在干净环境能跑，说明问题更像是当前 shell 里某个环境变量把运行时环境带歪了。\n我又清掉 root 下可能存在的 htop 配置：\nmv /root/.config/htop /root/.config/htop.bak.$(date +%s) 2\u0026gt;/dev/null mv /root/.htoprc /root/.htoprc.bak.$(date +%s) 2\u0026gt;/dev/null 再跑普通的：\nhtop # 段错误 (核心已转储) 配置文件也不是根因。\n三、不是 TERM，也不是中文 locale 当时的终端和语言环境是：\necho \u0026#34;TERM=$TERM\u0026#34; # TERM=xterm locale # LANG=zh_CN.UTF-8 # LC_CTYPE=\u0026#34;zh_CN.UTF-8\u0026#34; # ... 分别改 TERM 和 locale 测试：\nTERM=xterm-256color htop # 段错误 (核心已转储) LANG=C LC_ALL=C htop # 段错误 (核心已转储) TERM=xterm-256color LANG=C LC_ALL=C htop # 段错误 (核心已转储) 这些都不行。但下面这条可以：\nenv -i HOME=/root TERM=xterm-256color LANG=C LC_ALL=C /usr/bin/htop 这说明 HOME=/root 本身没问题，TERM 和 LANG 也不是主犯。真正的问题藏在其它环境变量里。\n四、抓到元凶：LD_LIBRARY_PATH 把可疑环境变量列出来：\nenv | sort | egrep \u0026#39;^(LD_|XDG_|TERMINFO|NCURSES|HTOP|MALLOC_|GLIBC_|TERM=|LANG=|LC_)\u0026#39; 输出里有一行很扎眼：\nLD_LIBRARY_PATH=/root/.conda/envs/dy_p39/lib: 验证一下：\nenv -u LD_LIBRARY_PATH htop 这次 htop 正常打开。\n到这里根因就确定了：不是 htop 坏了，而是当前 shell 里全局设置了 LD_LIBRARY_PATH，让系统程序优先加载了 Conda 环境里的动态库。\n五、LD_LIBRARY_PATH 到底做了什么 Linux 程序运行时，经常需要加载 .so 动态库。比如 htop 这种终端程序，会依赖 ncurses、libtinfo 这类库来处理终端界面。\n正常情况下，系统会从默认库路径里找：\n/lib64 /usr/lib64 但如果设置了 LD_LIBRARY_PATH，动态链接器会优先去这个变量指定的目录里找库。当前机器上的设置是：\nLD_LIBRARY_PATH=/root/.conda/envs/dy_p39/lib: 这意味着运行 /usr/bin/htop 时，系统并不是老老实实先用 Rocky 自己的库，而是会先去这个 Conda 环境里找同名库。\nConda 环境里的库是给那个 Python 环境服务的，版本、编译选项、ABI 都可能和系统包不完全一致。系统程序一旦误加载了这些库，就可能出现很奇怪的问题：轻则报 symbol not found，重则直接段错误。\n这次就是后者。\n还有一个细节：这个变量最后有个冒号：\n/root/.conda/envs/dy_p39/lib: 末尾空路径在不少场景下会被解释成当前目录。放在 root 环境里不是好习惯，也有额外风险。\n六、临时解决 如果只是想马上用 htop，最简单：\nenv -u LD_LIBRARY_PATH htop 这条命令的意思是：运行 htop 时临时取消 LD_LIBRARY_PATH。\n如果当前终端里不需要这个变量，也可以直接：\nunset LD_LIBRARY_PATH htop 这只影响当前 shell。重新登录后，如果配置文件里还写着那行 export，问题还会回来。\n也可以给 htop 加一个 alias：\nalias htop=\u0026#39;env -u LD_LIBRARY_PATH /usr/bin/htop\u0026#39; 想让 alias 长期生效，可以写进 ~/.bashrc：\necho \u0026#34;alias htop=\u0026#39;env -u LD_LIBRARY_PATH /usr/bin/htop\u0026#39;\u0026#34; \u0026gt;\u0026gt; ~/.bashrc source ~/.bashrc 不过这个只是绕过。真正该修的是全局环境变量。\n七、永久解决 先找到是谁设置了 LD_LIBRARY_PATH：\ngrep -R \u0026#34;LD_LIBRARY_PATH\u0026#34; ~/.bashrc ~/.bash_profile ~/.profile /etc/profile /etc/profile.d 2\u0026gt;/dev/null 如果看到类似这样的行：\nexport LD_LIBRARY_PATH=/root/.conda/envs/dy_p39/lib:$LD_LIBRARY_PATH 或者：\nexport LD_LIBRARY_PATH=/root/.conda/envs/dy_p39/lib: 建议删掉，或者至少不要放在 root 的全局 shell 配置里。\nConda 环境应该通过激活来使用：\nconda activate dy_p39 不要把某个 Conda 环境的 lib 目录长期挂到所有系统命令前面。这样影响的不是一个 Python 项目，而是整个 shell 里启动的所有程序。\n如果某个环境确实需要额外设置 LD_LIBRARY_PATH，也应该把它限制在这个 Conda 环境激活之后。比如放到对应环境的 activate.d 脚本里，而不是写进 root 的 .bashrc 或 /etc/profile。\n八、修完后怎么确认 重新登录一个终端，检查：\necho \u0026#34;$LD_LIBRARY_PATH\u0026#34; 确认里面不再有：\n/root/.conda/envs/dy_p39/lib 再跑：\nhtop 如果普通 htop 可以正常打开，问题就解决了。\n也可以做一个对照：\nenv -u LD_LIBRARY_PATH htop 如果取消 LD_LIBRARY_PATH 就正常，带上它就崩，那就说明根因确实是动态库搜索路径污染。\n九、结论 这次 htop 段错误不是系统坏了，也不是 htop 包坏了，而是一个 Conda 环境的库路径被全局写进了 LD_LIBRARY_PATH。\nLD_LIBRARY_PATH 这个变量很有用，但也很危险。它会改变动态库加载顺序，让系统程序优先吃到你指定目录里的 .so。如果这个目录来自 Conda、手动编译软件或者某个项目私有环境，就很容易污染系统命令。\n临时处理用：\nenv -u LD_LIBRARY_PATH htop 永久处理是删掉全局配置里的那行 LD_LIBRARY_PATH，让 Conda 环境只在 conda activate 后影响自己该影响的程序。\n但是你用htop不多也不需要。\n","permalink":"https://june6699.github.io/posts/htop%E6%AE%B5%E9%94%99%E8%AF%AF%E6%8E%92%E6%9F%A5-ld_library_path%E5%92%8Cconda%E5%8A%A8%E6%80%81%E5%BA%93%E6%B1%A1%E6%9F%93/","summary":"\u003ch2 id=\"一问题现场\"\u003e一、问题现场\u003c/h2\u003e\n\u003cp\u003e晚上在一台 Rocky Linux 8.10 机器上看进程，随手敲了个：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehtop\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e结果直接崩了：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e段错误 \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e核心已转储\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e第一反应一般会怀疑 \u003ccode\u003ehtop\u003c/code\u003e 包坏了，或者 ncurses 这类终端库出了问题。先把基本信息看一遍：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewhich htop\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /usr/bin/htop\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecat /etc/centos-release\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Rocky Linux release 8.10 (Green Obsidian)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erpm -qf \u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003ecommand -v htop\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# htop-3.2.1-1.el8.x86_64\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehtop --version\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# htop 3.2.1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e路径是系统路径，包也是 EPEL 里的正常包。于是先重装：\u003c/p\u003e","tags":["技术","技术/Linux","技术/运维"],"title":"一次 htop 段错误排查：LD_LIBRARY_PATH 和 Conda 动态库污染"},{"content":"学习视频链接 11-785 Deep Learning 文档 S25 0、为啥叫重新学习 原本都学了一大半了，课程确实很难，但是又忘了，现在开始重新学习。之前第一次学，经常要停下来思考、问AI、推导公式，很慢很慢才理解，相信这次会学的更快，更省时间。\n","permalink":"https://june6699.github.io/posts/%E9%87%8D%E6%96%B0%E5%BC%80%E5%A7%8B%E5%AD%A6cmu-11-785/","summary":"\u003ch3 id=\"学习视频链接\"\u003e\u003ca href=\"https://www.bilibili.com/video/BV1Y2ySBgEoe?spm_id_from=333.788.player.switch\u0026amp;vd_source=76a6f89f0900bd443ef08648e4c92f12\u0026amp;p=2\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e学习视频链接\u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://deeplearning.cs.cmu.edu/S25/index.html\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e11-785 Deep Learning 文档 S25\u003c/a\u003e\n\u003c/p\u003e\n\u003ch3 id=\"0为啥叫重新学习\"\u003e0、为啥叫重新学习\u003c/h3\u003e\n\u003cp\u003e原本都学了一大半了，课程确实很难，但是又忘了，现在开始重新学习。之前第一次学，经常要停下来思考、问AI、推导公式，很慢很慢才理解，相信这次会学的更快，更省时间。\u003c/p\u003e","tags":["技术","技术/AI","技术/AI/学习"],"title":"重新学习CMU 11-785深度学习导论"},{"content":"一、这条流程在解决什么问题 这次要处理的是三批猪 Hi-C 数据：6month、70day、9year。手头已经有去重后的 validPairs，目标是把它们整理成 FitHiC2 能吃的 10 kb 输入，再跑出显著互作。\n中间最容易踩坑的地方不是 FitHiC2 命令本身，而是输入文件。FitHiC2 至少要看三类东西：\ncontactCounts：每一对 bin 之间观测到多少次接触。 fragments：每个 bin 的坐标、边际接触数、是否可比对。 bias：每个 bin 的归一化偏差权重，用于校正测序深度、可比对性、GC、片段可捕获性等系统误差。 我主要改了两个地方。第一，原始 createFitHiCFragments-fixedsize.py 会把 fragments 第 4 列和第 5 列都写成 1，能跑，但太粗糙：第 4 列应该尽量是真实的 marginalized contact count，第 5 列应该反映 bin 的 mappability。第二，官方 validPairs2FitHiC-fixedSize.sh 里有一处低距离过滤的括号写错了，下面会单独拎出来说。这里给的是修过后的版本。\n二、FitHiC2 原理 2.1 Hi-C 接触矩阵的距离衰减 Hi-C 数据最明显的规律是：同一条染色体上，两个位点之间的基因组距离越近，接触频率通常越高；距离越远，接触频率越低。这不是某一个 loop 的特异信号，而是聚合物折叠和实验捕获共同造成的背景规律。\n因此，判断一对 bin 是否“显著互作”，不能只看 contactCount 高不高。一个 10 kb 相邻 bin 的 count=100 可能很普通，但相隔 2 Mb 的两个 bin 如果也有 count=100，就可能非常异常。FitHiC2 做的事情，就是在给定距离背景下判断某个接触数是否显著高于期望。\n2.2 FitHiC2 的统计建模思路 只看和这次流程有关的部分，FitHiC2 大致是在做这几件事：\n把基因组切成固定大小的 bin，例如 10 kb。 对每个 bin pair 计算观测接触数，同时记录这对 bin 的基因组距离。 用所有中距离接触拟合一条“距离-接触概率”背景曲线，通常通过 equal-occupancy binning 和 spline 完成。 对每个 bin pair 计算观测值偏离背景期望的显著性，得到 p-value，再通过 Benjamini-Hochberg 方法得到 q-value。 FitHiC2 输出的主结果不是“有没有接触”，而是“这个接触在同距离背景下是否比期望更富集”。所以解释结果时应优先看 q-value 和 observed / expected，而不是只看原始 contactCount。\n2.3 fragments 文件为什么重要 FitHiC2 的 fragments 文件每行代表一个可分析的 genomic bin。官方格式是 5 列：\nchr extraField fragmentMid marginalizedContactCount mappable 在固定 bin 流程里，第二列可以写 bin 起点，第三列必须是 bin 中点。第四列是这个 bin 参与的总接触量，第五列通常写成 0/1 表示是否可比对。FitHiC2 会用这些信息决定哪些 bin 可以进入背景模型，也会结合 bias 文件进行显著性估计。\n如果第 4 列全部写成 1，低覆盖 bin 和高覆盖 bin 会被粗暴看成同类。若第 5 列全部写成 1，低 mappability 区域也会进入模型。这两类问题都可能让背景估计变脏，最终影响显著互作的可靠性。\n2.4 bias 文件为什么重要 Hi-C 矩阵的每个 bin 都有自己的捕获偏好。某些区域因为 GC 含量、重复序列、酶切片段、可比对性或局部测序深度，天然比其他区域更容易产生 contact。HiCKRy 使用 Knight-Ruiz 矩阵平衡算法为每个 bin 估计一个 bias 值。\nFitHiC2 的 bias 文件格式是：\nchr midpoint bias 平均值通常接近 1。bias 高的 bin 表示原始接触量整体偏高，bias 低的 bin 表示原始接触量整体偏低。FitHiC2 在计算期望接触数时会纳入这两个端点的 bias，从而减少系统偏差造成的假阳性。\n三、全局配置与路径写法 代码里不要直接写个人目录或服务器用户名。建议所有路径集中放在一个配置文件里，后续脚本只引用变量。下面的 /path/to/pig_hic_project 是占位路径，实际运行时替换成自己的项目根目录即可。\n#!/usr/bin/env bash set -euo pipefail PROJECT_ROOT=\u0026#34;/path/to/pig_hic_project\u0026#34; RAW_DIR=\u0026#34;${PROJECT_ROOT}/01.data\u0026#34; SCRIPT_DIR=\u0026#34;${PROJECT_ROOT}/scripts\u0026#34; OUT_DIR=\u0026#34;${PROJECT_ROOT}/fithic2_10kb\u0026#34; CHROMSIZES=\u0026#34;${PROJECT_ROOT}/chrom_sus11.sizes\u0026#34; MAPPABILITY_TAB=\u0026#34;${OUT_DIR}/mappability_10kb.tab\u0026#34; MAPPABILITY_NOCHR=\u0026#34;${OUT_DIR}/mappability_10kb.nochr.tab\u0026#34; HICKRY=\u0026#34;${SCRIPT_DIR}/HiCKRy.py\u0026#34; RESOLUTION=10000 MIN_CIS_DIST=$((RESOLUTION * 2)) MAP_THRES=0.2 SAMPLES=(6month 9year 70day) mkdir -p \u0026#34;${OUT_DIR}\u0026#34; 后面的 awk 里会用到绝对距离。为了避免再写出 sqrt(($3-$7)^2 \u0026gt; t) 这种括号事故，本文都用一个明确的 awk 函数：\nfunction abs(x) { return x \u0026lt; 0 ? -x : x } 这份配置假设：\nRAW_DIR 下有 ${sample}_shortFormat.sort.txt 或对应的 gzip 文件。 CHROMSIZES 是猪基因组 chromosome size 文件。 SCRIPT_DIR 下放 validPairs2FitHiC-fixedSize.sh、createFitHiCFragments-fixedsize.withmap.py、HiCKRy.py。 OUT_DIR 是所有中间结果和最终结果的输出目录。 四、输入文件解释 4.1 validPairs 文件 validPairs 是 Hi-C 比对、过滤、去重后得到的有效 read pair 文件。不同软件输出列顺序可能不同，本流程假设至少满足下面这几列：\ncol2 chr1 col3 pos1 col6 chr2 col7 pos2 也就是说，脚本里使用 $2/$3 作为第一个端点，使用 $6/$7 作为第二个端点。如果你的 validPairs 格式不是这样，必须先改 awk 里的列号。\n典型输入行可以理解为：\nreadID chr1 pos1 ... ... chr2 pos2 ... 这里的 pos1 和 pos2 是 read 端点在基因组上的坐标。后续会把坐标按 10 kb 分箱，例如 pos=123456 会落入 120000-130000 这个 bin，中点坐标是 125000。\n4.2 chromosome sizes 文件 chrom_sus11.sizes 用来告诉 bedtools makewindows 和 fragments 脚本每条染色体的长度，格式为两列：\nchrom length 1 274330532 2 151935994 ... 染色体命名要和 validPairs 保持一致。若 validPairs 是 1, 2, 3，chrom sizes 也应使用 1, 2, 3；若 validPairs 是 chr1, chr2, chr3，chrom sizes 也应使用 chr1, chr2, chr3。命名不一致会导致交集统计和 FitHiC2 匹配失败。\n4.3 mappability_10kb.tab 文件 mappability_10kb.tab 表示每个 10 kb bin 的平均可比对性。这里的思路是先用 GenMap 计算 75-mer mappability，再转成 bigWig，最后用 multiBigwigSummary 或类似工具按 10 kb bin 求均值。\n本流程要求 mappability 表至少有 4 列：\nchrom start end mean_mappability 1 0 10000 0.98 1 10000 20000 0.12 ... 后续 fragments 生成脚本会读取第 1 列、第 2 列和第 4 列。如果 mean_mappability \u0026gt;= 0.2，该 bin 的 fragments 第 5 列写 1；否则写 0。\n4.4 contactCounts 文件 contactCounts 是 FitHiC2 的互作输入文件，只保留非零 contact 的 bin pair，格式为 5 列：\nchr1 mid1 chr2 mid2 contactCount 示例：\n10 5000 10 11985000 1 10 5000 13 108135000 1 1 5000 1 5000 115 10 10005000 10 10015000 119 字段含义如下：\n列 含义 chr1 第一个 bin 的染色体 mid1 第一个 bin 的中点坐标 chr2 第二个 bin 的染色体 mid2 第二个 bin 的中点坐标 contactCount 两个 bin 之间观测到的 contact 数 需要注意几种常见情况：\n1 5000 1 5000 115 表示同一个 bin 的自接触，通常 count 很高，不应直接解释为远距离 loop。 10 10005000 10 10015000 119 表示相邻 bin 接触，count 高符合 Hi-C 近距离接触更强的规律。 10 5000 13 108135000 1 表示跨染色体接触。FitHiC2 默认多用于 intraOnly，若要分析跨染色体互作，需要显式设置并承担更重的多重检验压力。 4.5 fragments 文件 本流程生成的 fragments 文件格式为：\nchr start mid marginalizedContactCount mappable 示例：\n1 0 5000 342 1 1 10000 15000 0 0 字段含义如下：\n列 含义 chr bin 所在染色体 start bin 起点；对 FitHiC2 来说是 extra field，但保留起点方便检查 mid bin 中点，必须和 contactCounts 中的 midpoint 一致 marginalizedContactCount 该 bin 参与的总接触量，本流程由 validPairs 两端点投影到 bin 后统计 mappable 是否可比对，1 表示通过 mappability 阈值，0 表示不通过 在这个流程中，边际接触数来自通过距离过滤后的 validPairs 端点计数。每个有效 pair 会贡献两个端点；如果两个端点落在同一个 bin，该 bin 会被计两次。这和 Hi-C 矩阵行和的直觉一致：它衡量的是该 bin 总体参与了多少可用 contact。\n五、流程总览 00_config.sh ↓ 01_make_marginal_counts.sh 生成 genome_10kb_bins.bed 和 ${sample}_bins_with_counts.bed ↓ 02_make_contact_counts.sh 生成 10k_res_${sample}_fithic.contactCounts.gz ↓ 03_make_fragments.sh 合并 mappability 与 marginal counts，生成 ${sample}_fragments_fixed_10k.gz ↓ 04_run_hickry_and_fithic.sh 生成 bias 文件和 FitHiC2 显著互作结果 其中 01_make_marginal_counts.sh 和 02_make_contact_counts.sh 互不依赖，可以同时跑。03_make_fragments.sh 必须等 mappability 表和 ${sample}_bins_with_counts.bed 都准备好后再跑。04_run_hickry_and_fithic.sh 必须等 contactCounts 和 fragments 都生成后再跑。\n六、脚本 1：生成每个 bin 的边际接触数 6.1 原理 FitHiC2 的 fragments 第 4 列需要每个 bin 的总接触量。这里不直接从 contactCounts 反推，而是从 validPairs 出发，把每对 reads 拆成两个单端 BED 记录，再用 bedtools intersect -c 统计每个 10 kb bin 中落入多少 read 端点。\n这一步先做三个过滤：\n只保留常规染色体命名长度较短的记录，避免未组装 contig 造成干扰。 去掉线粒体 MT。 去掉同染色体距离不超过 2 × resolution 的极短距离 pairs，减少 self-ligation 和近距离技术噪音。 6.2 代码 #!/usr/bin/env bash set -euo pipefail source ./00_config.sh bedtools makewindows \\ -g \u0026#34;${CHROMSIZES}\u0026#34; \\ -w \u0026#34;${RESOLUTION}\u0026#34; \\ \u0026gt; \u0026#34;${OUT_DIR}/genome_10kb_bins.bed\u0026#34; for sample in \u0026#34;${SAMPLES[@]}\u0026#34; do echo \u0026#34;=== making marginal counts for ${sample} ===\u0026#34; validPairs=\u0026#34;${RAW_DIR}/${sample}_shortFormat.sort.txt\u0026#34; singleBed=\u0026#34;${OUT_DIR}/${sample}_validPairs_singleBED.bed\u0026#34; countsBed=\u0026#34;${OUT_DIR}/${sample}_bins_with_counts.bed\u0026#34; zcat -f \u0026#34;${validPairs}\u0026#34; | awk -v minDist=\u0026#34;${MIN_CIS_DIST}\u0026#34; \u0026#39; BEGIN{OFS=\u0026#34;\\t\u0026#34;} function abs(x) { return x \u0026lt; 0 ? -x : x } length($2) \u0026lt;= 5 \u0026amp;\u0026amp; length($6) \u0026lt;= 5 \u0026amp;\u0026amp; $2 != \u0026#34;MT\u0026#34; \u0026amp;\u0026amp; $6 != \u0026#34;MT\u0026#34; { if ($2 != $6 || abs($3 - $7) \u0026gt; minDist) { print $2, $3 - 1, $3 print $6, $7 - 1, $7 } }\u0026#39; \\ \u0026gt; \u0026#34;${singleBed}\u0026#34; bedtools intersect \\ -a \u0026#34;${OUT_DIR}/genome_10kb_bins.bed\u0026#34; \\ -b \u0026#34;${singleBed}\u0026#34; \\ -c -nonamecheck \\ \u0026gt; \u0026#34;${countsBed}\u0026#34; echo \u0026#34;=== ${sample} marginal counts done ===\u0026#34; done 6.3 输入文件 输入 作用 ${CHROMSIZES} 提供每条染色体长度，用于切 10 kb bin ${RAW_DIR}/${sample}_shortFormat.sort.txt 当前样本的 validPairs 文件 6.4 输出文件 genome_10kb_bins.bed 是全基因组 bin 列表：\nchr start end 1 0 10000 1 10000 20000 ... ${sample}_validPairs_singleBED.bed 是中间文件，每个 valid pair 被拆成两条单端 BED：\nchr start end 1 123455 123456 1 987654 987655 ${sample}_bins_with_counts.bed 是 fragments 第 4 列的来源：\nchr start end count 1 0 10000 342 1 10000 20000 289 七、脚本 2：生成 FitHiC2 contactCounts 7.1 原理 这一步把 validPairs 的两个端点分别换算成 10 kb bin 起点，再转成 bin 中点，最后对相同 bin pair 计数。FitHiC2 要求每个互作只出现一次，所以脚本会把 bin pair 统一成固定顺序：染色体编号较小的端点在前；同染色体时，起点坐标较小的端点在前。\n官方 validPairs2FitHiC-fixedSize.sh 里这一行要改：\nawk -v t=$lowDistThres \u0026#39;{if($2!=$5||($2==$5 \u0026amp;\u0026amp; (sqrt(($3-$6)^2\u0026gt;t)))) {print $0}}\u0026#39; 这里的 $2/$3 和 $5/$6 是官方脚本默认的 validPairs 列号。本文前面那份 shortFormat 文件用的是 $2/$3 和 $6/$7，所以后面的完整脚本会按本地列号写；括号问题和修法是同一个问题。\n问题出在括号位置。awk 会先算 ($3-$6)^2 \u0026gt; t，这个表达式的结果只有 0 或 1，再丢给 sqrt()。也就是说它算的不是两个端点之间的距离，而是在对一个真假值开方：真就是 sqrt(1)=1，假就是 sqrt(0)=0。\n这会把低距离过滤改坏。原本应当保留“同染色体且距离大于阈值”的 pair；错误写法实际只是在判断 ($3-$6)^2 \u0026gt; t 是否为真。因为左边是平方、右边还是原始距离阈值，等价阈值变成了 sqrt(t)。如果 t=20000，最后实际只过滤掉约 141 bp 以内的 pair，而不是过滤掉 20 kb 以内的 pair。\n最直接的修法是先取绝对距离，再和阈值比较：\nawk -v t=$lowDistThres \u0026#39;function abs(x){return x \u0026lt; 0 ? -x : x} {if($2!=$5 || ($2==$5 \u0026amp;\u0026amp; abs($3-$6)\u0026gt;t)) {print $0}}\u0026#39; 如果继续用平方也可以，但要把阈值一起平方：\n($3 - $6)^2 \u0026gt; t^2 我更倾向于 abs()，一眼就能看出来是在做距离过滤，不容易再被括号坑。\n7.2 validPairs2FitHiC-fixedSize.sh #!/usr/bin/env bash set -euo pipefail w=\u0026#34;$1\u0026#34; libName=\u0026#34;$2\u0026#34; validPairsFile=\u0026#34;$3\u0026#34; outdir=\u0026#34;$4\u0026#34; lowDistThres=$((w * 2)) mkdir -p \u0026#34;${outdir}\u0026#34; zcat -f \u0026#34;${validPairsFile}\u0026#34; | awk -v r=\u0026#34;${w}\u0026#34; -v minDist=\u0026#34;${lowDistThres}\u0026#34; \u0026#39; BEGIN{OFS=\u0026#34;\\t\u0026#34;} function abs(x) { return x \u0026lt; 0 ? -x : x } length($2) \u0026lt;= 5 \u0026amp;\u0026amp; length($6) \u0026lt;= 5 \u0026amp;\u0026amp; $2 != \u0026#34;MT\u0026#34; \u0026amp;\u0026amp; $6 != \u0026#34;MT\u0026#34; { if ($2 != $6 || abs($3 - $7) \u0026gt; minDist) { chr1 = $2 start1 = int($3 / r) * r chr2 = $6 start2 = int($7 / r) * r if (chr1 \u0026lt; chr2 || (chr1 == chr2 \u0026amp;\u0026amp; start1 \u0026lt;= start2)) { print chr1, start1, chr2, start2 } else { print chr2, start2, chr1, start1 } } }\u0026#39; | sort -k1,1 -k2,2n -k3,3 -k4,4n | uniq -c | awk -v r=\u0026#34;${w}\u0026#34; \u0026#39;BEGIN{OFS=\u0026#34;\\t\u0026#34;} { count = $1 chr1 = $2 mid1 = $3 + r / 2 chr2 = $4 mid2 = $5 + r / 2 print chr1, mid1, chr2, mid2, count }\u0026#39; | gzip \u0026gt; \u0026#34;${outdir}/${libName}_fithic.contactCounts.gz\u0026#34; 7.3 批量运行 #!/usr/bin/env bash set -euo pipefail source ./00_config.sh for sample in \u0026#34;${SAMPLES[@]}\u0026#34; do echo \u0026#34;=== making contactCounts for ${sample} ===\u0026#34; bash \u0026#34;${SCRIPT_DIR}/validPairs2FitHiC-fixedSize.sh\u0026#34; \\ \u0026#34;${RESOLUTION}\u0026#34; \\ \u0026#34;10k_res_${sample}\u0026#34; \\ \u0026#34;${RAW_DIR}/${sample}_shortFormat.sort.txt\u0026#34; \\ \u0026#34;${OUT_DIR}\u0026#34; echo \u0026#34;=== ${sample} contactCounts done ===\u0026#34; done 7.4 输出文件解释 输出文件为：\n10k_res_${sample}_fithic.contactCounts.gz 检查方式：\nzcat \u0026#34;${OUT_DIR}/10k_res_6month_fithic.contactCounts.gz\u0026#34; | head 若看到 5 列，且中点坐标均为 5000, 15000, 25000... 这种形式，说明分箱逻辑基本正确。\n八、脚本 3：生成 corrected fragments 8.1 原理 这一步把三类信息合并成 FitHiC2 fragments 文件：\nchrom sizes：决定全基因组有哪些 bin。 ${sample}_bins_with_counts.bed：提供每个 bin 的边际接触数。 mappability_10kb.tab：提供每个 bin 的平均 mappability，并转成 0/1。 如果 mappability 文件带有 chr 前缀，而 validPairs 和 chrom sizes 没有 chr 前缀，需要先去掉前缀。反过来也一样，总之所有输入必须使用同一套染色体命名。\n8.2 mappability 文件准备 如果 mappability 文件在另一台服务器上，可以用占位变量表示远程来源：\n#!/usr/bin/env bash set -euo pipefail source ./00_config.sh REMOTE_MAP_SOURCE=\u0026#34;user@remote-host:/path/to/mappability_10kb.tab\u0026#34; scp \u0026#34;${REMOTE_MAP_SOURCE}\u0026#34; \u0026#34;${MAPPABILITY_TAB}\u0026#34; sed \u0026#39;s/^chr//\u0026#39; \u0026#34;${MAPPABILITY_TAB}\u0026#34; \u0026gt; \u0026#34;${MAPPABILITY_NOCHR}\u0026#34; 如果本来就没有 chr 前缀，sed 后的文件和原文件内容会基本一致。\n8.3 createFitHiCFragments-fixedsize.withmap.py #!/usr/bin/env python import argparse import gzip def strip_chr(chrom): return chrom[3:] if chrom.startswith(\u0026#34;chr\u0026#34;) else chrom def read_mappability(path, threshold): values = {} with open(path, \u0026#34;r\u0026#34;, encoding=\u0026#34;utf-8\u0026#34;) as handle: for line in handle: if not line.strip() or line.startswith(\u0026#34;#\u0026#34;): continue parts = line.rstrip().split() if len(parts) \u0026lt; 4: continue chrom = strip_chr(parts[0]) start = int(parts[1]) mean_mappability = float(parts[3]) values[(chrom, start)] = 1 if mean_mappability \u0026gt;= threshold else 0 return values def read_counts(path): counts = {} with open(path, \u0026#34;r\u0026#34;, encoding=\u0026#34;utf-8\u0026#34;) as handle: for line in handle: if not line.strip() or line.startswith(\u0026#34;#\u0026#34;): continue parts = line.rstrip().split() if len(parts) \u0026lt; 4: continue chrom = strip_chr(parts[0]) start = int(parts[1]) count = int(parts[3]) counts[(chrom, start)] = count return counts def parse_args(): parser = argparse.ArgumentParser( description=\u0026#34;Create FitHiC2 fixed-size fragments with real marginal counts and mappability.\u0026#34; ) parser.add_argument(\u0026#34;--chrLens\u0026#34;, required=True) parser.add_argument(\u0026#34;--resolution\u0026#34;, type=int, required=True) parser.add_argument(\u0026#34;--mappability\u0026#34;, required=True) parser.add_argument(\u0026#34;--counts\u0026#34;, required=True) parser.add_argument(\u0026#34;--outFile\u0026#34;, required=True) parser.add_argument(\u0026#34;--mapThres\u0026#34;, type=float, default=0.2) return parser.parse_args() def main(): args = parse_args() mappability = read_mappability(args.mappability, args.mapThres) counts = read_counts(args.counts) with open(args.chrLens, \u0026#34;r\u0026#34;, encoding=\u0026#34;utf-8\u0026#34;) as chrom_handle, gzip.open(args.outFile, \u0026#34;wt\u0026#34;) as out: for line in chrom_handle: if not line.strip() or line.startswith(\u0026#34;#\u0026#34;): continue chrom, size_text = line.rstrip().split()[:2] chrom = strip_chr(chrom) chrom_size = int(size_text) interval_end = ((chrom_size + args.resolution - 1) // args.resolution) * args.resolution for start in range(0, interval_end, args.resolution): mid = start + args.resolution // 2 key = (chrom, start) marginal_count = counts.get(key, 0) is_mappable = mappability.get(key, 0) out.write(f\u0026#34;{chrom}\\t{start}\\t{mid}\\t{marginal_count}\\t{is_mappable}\\n\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: main() 8.4 批量运行 #!/usr/bin/env bash set -euo pipefail source ./00_config.sh for sample in \u0026#34;${SAMPLES[@]}\u0026#34; do echo \u0026#34;=== making fragments for ${sample} ===\u0026#34; python \u0026#34;${SCRIPT_DIR}/createFitHiCFragments-fixedsize.withmap.py\u0026#34; \\ --chrLens \u0026#34;${CHROMSIZES}\u0026#34; \\ --resolution \u0026#34;${RESOLUTION}\u0026#34; \\ --mappability \u0026#34;${MAPPABILITY_NOCHR}\u0026#34; \\ --counts \u0026#34;${OUT_DIR}/${sample}_bins_with_counts.bed\u0026#34; \\ --outFile \u0026#34;${OUT_DIR}/${sample}_fragments_fixed_10k.gz\u0026#34; \\ --mapThres \u0026#34;${MAP_THRES}\u0026#34; echo \u0026#34;=== ${sample} fragments done ===\u0026#34; done 8.5 输出文件解释 输出文件为：\n${sample}_fragments_fixed_10k.gz 检查方式：\nzcat \u0026#34;${OUT_DIR}/6month_fragments_fixed_10k.gz\u0026#34; | head 理想情况下应满足：\n每行 5 列。 第 3 列中点坐标能在 contactCounts 的第 2/4 列中找到。 第 4 列不是全 1，而是随 bin 覆盖度变化。 第 5 列只包含 0 和 1。 九、脚本 4：运行 HiCKRy 和 FitHiC2 9.1 原理 HiCKRy 先根据 contactCounts 和 fragments 估计每个 bin 的归一化 bias。FitHiC2 再利用 contactCounts、fragments 和 bias 文件拟合距离背景曲线，并计算每个互作的显著性。\n建议在 FitHiC2 中显式设置：\n-f：fragments 文件。 -i：contactCounts 文件。 -o：输出目录。 -r：固定 bin 分辨率。 --biases：HiCKRy 生成的 bias 文件。 -l：输出文件名前缀，避免多个样本都叫 fithic。 -x intraOnly：默认只分析同染色体互作，适合大多数 loop 或 domain 相关分析。 9.2 代码 #!/usr/bin/env bash set -euo pipefail source ./00_config.sh for sample in \u0026#34;${SAMPLES[@]}\u0026#34; do echo \u0026#34;=== running HiCKRy and FitHiC2 for ${sample} ===\u0026#34; interactions=\u0026#34;${OUT_DIR}/10k_res_${sample}_fithic.contactCounts.gz\u0026#34; fragments=\u0026#34;${OUT_DIR}/${sample}_fragments_fixed_10k.gz\u0026#34; bias_txt=\u0026#34;${OUT_DIR}/${sample}_bias_10k.txt\u0026#34; bias_gz=\u0026#34;${OUT_DIR}/${sample}_bias_10k.txt.gz\u0026#34; sample_out=\u0026#34;${OUT_DIR}/10k_res_${sample}_output\u0026#34; python \u0026#34;${HICKRY}\u0026#34; \\ -i \u0026#34;${interactions}\u0026#34; \\ -f \u0026#34;${fragments}\u0026#34; \\ -o \u0026#34;${bias_txt}\u0026#34; gzip -c \u0026#34;${bias_txt}\u0026#34; \u0026gt; \u0026#34;${bias_gz}\u0026#34; mkdir -p \u0026#34;${sample_out}\u0026#34; fithic \\ -f \u0026#34;${fragments}\u0026#34; \\ -i \u0026#34;${interactions}\u0026#34; \\ -o \u0026#34;${sample_out}\u0026#34; \\ -r \u0026#34;${RESOLUTION}\u0026#34; \\ --biases \u0026#34;${bias_gz}\u0026#34; \\ -l \u0026#34;10k_res_${sample}\u0026#34; \\ -L \u0026#34;${MIN_CIS_DIST}\u0026#34; \\ -x intraOnly echo \u0026#34;=== ${sample} FitHiC2 done ===\u0026#34; done 如果本地安装的 FitHiC2 对 --biases 的 gzip 支持有差异，可以把 bias_gz 换成 bias_txt 测试；但从格式规范上讲，gzip 版本更稳。\n十、最终输出文件解释 10.1 bias 文件 HiCKRy 输出：\n${sample}_bias_10k.txt ${sample}_bias_10k.txt.gz 格式为：\nchr midpoint bias 1 5000 0.932 1 15000 1.104 解释方式：\nbias ≈ 1：该 bin 的整体接触量接近平均水平。 bias \u0026gt; 1：该 bin 原始接触量偏高，可能更容易被捕获。 bias \u0026lt; 1：该 bin 原始接触量偏低。 极端 bias 值通常需要警惕，可能来自低覆盖、低 mappability 或异常重复区域。 10.2 spline 拟合文件 FitHiC2 输出：\n10k_res_${sample}.fithic_pass1.txt 这个文件记录 equal-occupancy binning 和 spline 拟合背景，常见字段为：\n字段 含义 avgGenomicDist 当前距离分组的平均基因组距离 contactProb 拟合得到的背景接触概率 stdErr 该距离分组接触概率的标准误 numLocusPairs 当前距离分组包含的 bin pair 数 CCtotal 当前距离分组的总 contact count 它不是最终 loop 表，而是用来检查背景模型是否合理。通常可以画 avgGenomicDist 对 contactProb 的曲线，正常情况下应呈现随距离增加而下降的趋势。\n10.3 显著互作文件 FitHiC2 主结果为：\n10k_res_${sample}.spline_pass1.significances.txt.gz 它会在原始 contactCounts 的 5 列后追加显著性字段：\nchr1 mid1 chr2 mid2 contactCount p-value q-value bias1 bias2 ExpCC 字段解释：\n字段 含义 chr1/mid1 第一个互作端点 chr2/mid2 第二个互作端点 contactCount 观测接触数 p-value 在距离背景和 bias 校正后，该接触数的显著性 q-value BH 多重检验校正后的 FDR bias1/bias2 两个端点的归一化 bias ExpCC FitHiC2 根据距离背景和 bias 估计的期望接触数 常用筛选方式：\nzcat \u0026#34;${OUT_DIR}/10k_res_6month_output/10k_res_6month.spline_pass1.significances.txt.gz\u0026#34; | awk \u0026#39;BEGIN{OFS=\u0026#34;\\t\u0026#34;} $7 \u0026lt;= 0.01 {print $0}\u0026#39; \\ \u0026gt; \u0026#34;${OUT_DIR}/10k_res_6month_output/10k_res_6month.q0.01.interactions.txt\u0026#34; 解释结果时建议同时看：\nq-value 是否足够低，例如 \u0026lt;= 0.01 或 \u0026lt;= 0.05。 contactCount 是否不是孤立的极低计数。 ExpCC 是否明显低于观测值。 两个端点是否都位于 mappable 且 coverage 不异常的区域。 是否落在重复序列、组装 gap 或染色体边界附近。 十一、质控检查 11.1 检查 contactCounts 是否为 5 列 zcat \u0026#34;${OUT_DIR}/10k_res_6month_fithic.contactCounts.gz\u0026#34; | awk \u0026#39;NF != 5 {print NR, $0; exit}\u0026#39; 没有输出通常表示列数正常。\n11.2 检查 fragments 是否为 5 列 zcat \u0026#34;${OUT_DIR}/6month_fragments_fixed_10k.gz\u0026#34; | awk \u0026#39;NF != 5 {print NR, $0; exit}\u0026#39; 11.3 检查 midpoint 是否对齐 zcat \u0026#34;${OUT_DIR}/10k_res_6month_fithic.contactCounts.gz\u0026#34; | awk -v r=\u0026#34;${RESOLUTION}\u0026#34; \u0026#39;($2 % r != r / 2) || ($4 % r != r / 2) {print NR, $0; exit}\u0026#39; 如果没有输出，说明 contactCounts 中点坐标符合 10 kb 分辨率。\n11.4 检查 mappability 是否只有 0/1 zcat \u0026#34;${OUT_DIR}/6month_fragments_fixed_10k.gz\u0026#34; | awk \u0026#39;$5 != 0 \u0026amp;\u0026amp; $5 != 1 {print NR, $0; exit}\u0026#39; 11.5 检查低 mappability 比例 zcat \u0026#34;${OUT_DIR}/6month_fragments_fixed_10k.gz\u0026#34; | awk \u0026#39;{total += 1; low += ($5 == 0)} END{print low, total, low / total}\u0026#39; 如果 low / total 极高，通常说明 mappability 文件和 chrom sizes 的染色体命名或坐标没有对齐。\n十二、常见问题 12.1 染色体命名不一致 这是最常见的问题。chr1 和 1 对程序来说是两个不同染色体。validPairs、chrom sizes、mappability、contactCounts、fragments 必须统一。猪基因组中线粒体如果写作 MT，就不要在脚本里写 chrM。\n12.2 fragments 第 4 列不应全是 1 第 4 列代表边际接触量。如果全是 1，FitHiC2 仍可能运行，但模型会丢失覆盖度差异信息。更好的做法是像本文这样从 validPairs 统计每个 bin 的 endpoint count。\n12.3 fragments 第 5 列不应无脑全是 1 第 5 列用于 mappability 过滤。低 mappability 区域容易产生假信号，应根据 mappability 均值转成 0/1。本文默认阈值是 0.2，可根据实际数据调整。\n12.4 contactCounts 和 fragments 的 midpoint 必须一致 如果 contactCounts 使用 5000, 15000, 25000...，fragments 第 3 列也必须使用同样中点。一个常见错误是 contactCounts 用中点，fragments 却用起点，结果 FitHiC2 找不到对应 fragment。\n12.5 跨染色体互作不要默认混入主分析 FitHiC2 可以分析 interchromosomal contacts，但跨染色体互作数量多、噪音高，多重检验负担也更重。除非研究问题明确需要，建议主分析先使用 -x intraOnly。\n十三、参考资料 FitHiC2 官方仓库与输入输出格式说明：https://github.com/ay-lab/fithic Kaul A, Bhattacharyya S, Ay F. Identifying statistically significant chromatin contacts from Hi-C data with FitHiC2. Nature Protocols 15, 991-1012 (2020). https://doi.org/10.1038/s41596-019-0273-0 Ay F, Bailey TL, Noble WS. Statistical confidence estimation for Hi-C data reveals regulatory chromatin contacts. Genome Research 24, 999-1011 (2014). https://doi.org/10.1101/gr.160374.113 ","permalink":"https://june6699.github.io/posts/fithic2-%E7%8C%AAhi-c%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E6%B5%81%E7%A8%8B%E6%96%87%E6%A1%A3/","summary":"\u003ch2 id=\"一这条流程在解决什么问题\"\u003e一、这条流程在解决什么问题\u003c/h2\u003e\n\u003cp\u003e这次要处理的是三批猪 Hi-C 数据：\u003ccode\u003e6month\u003c/code\u003e、\u003ccode\u003e70day\u003c/code\u003e、\u003ccode\u003e9year\u003c/code\u003e。手头已经有去重后的 \u003ccode\u003evalidPairs\u003c/code\u003e，目标是把它们整理成 FitHiC2 能吃的 \u003ccode\u003e10 kb\u003c/code\u003e 输入，再跑出显著互作。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/分析"],"title":"FitHiC2 猪 Hi-C 数据处理记录：validPairs 到显著互作"},{"content":"中转 API 站点内卷和信息茧房的现状 最近看了一圈 AI 中转 API 站点，最大的感受不是“这行真赚钱”，而是“这行真魔幻”。\n同样是接 OpenAI、Claude、Gemini、各种国产模型，站点之间的价格可以差到离谱。低的低到像是在清库存，高的又高到让人怀疑是不是有人根本不知道官方价格长什么样。最有意思的是，便宜的站点未必没人用，贵的站点也照样有人买单。\n所以现在这个市场很像两个东西叠在一起：一边是极致内卷，大家把价格打到地板；另一边是信息茧房，很多用户只待在自己熟悉的圈子里，被谁的教程、谁的群、谁的推荐链接带进去，就在那里一直充值。\n1、价格已经卷到很难理解 比如 aibz.cc 的 pricing 页面 ，截图里 gpt-5.4 和 gpt-5.5 的输入价格写到 0.0100 / 1M Tokens 这个级别。按照普通用户的感知，这几乎就是 1M token 一分钱量级了。\n这个价格放在几年前，听起来像玩笑。现在却真的出现在中转站价格表里。\n当然，中转站价格不能只看一行数字。还要看它的倍率、渠道、稳定性、限速、并发、上下文、是否偷换模型、是否共享池、是否存在缓存和补全价格差异。但就算把这些因素都算进去，这种标价仍然说明一件事：低价站已经卷到不靠“模型贵”挣钱了，而是靠流量、充值沉淀、渠道套利、活动补贴，甚至靠用户懒得细算。\n2、图片接口也卷得很狠 再看 浮生云算的 pricing 页面 ，截图里 gpt-image-2 的价格低到 0.0213 / 请求。如果按一张图一次请求来理解，就是两分钱左右一张图。\n图片生成以前给人的感觉是“贵、慢、舍不得多试”。现在一些中转站把它卖成了可以随便点几下的消耗品。对普通用户来说，这当然爽；对站点来说，这就进入了另一个游戏：谁能拿到更便宜的上游，谁能更好地做池化，谁能把失败率、延迟和售后压住，谁就能多活一阵。\n但这也会带来一个问题：价格太低之后，用户反而更难判断质量。因为大家第一眼只看数字，0.02 比 0.2 香太多了，很少有人会继续问：这个图到底是不是同一个模型出的？队列是不是被挤爆？失败重试算不算钱？高峰期会不会直接降级？\n低价不是原罪，低价加黑箱才麻烦。\n3、GPT 也出现了明显价格分层 同一个页面里，截图三的 gpt-5.4 输入 0.2 / 1M、输出 1.2 / 1M，gpt-5.5 输入 0.4 / 1M、输出 2.4 / 1M。这已经属于比较便宜、也比较容易被开发者接受的价格带。\n如果只是个人写脚本、做插件、跑一点 Agent、接一下 Codex 或 Claude Code 这类工具，这种价格会让人很容易形成一种心理：反正不贵，先用着。\n也正是因为“不贵”，很多人不会再去研究官方 API、账单、区域限制、支付方式、模型差异、上游条款。他只要拿到一个 base url 和 key，就可以开工。这个便利性本身就是中转站存在的理由。\n但便利性也会反过来锁住人。一个人如果最早接触 AI API 就是从某个群、某个教程、某个站长开始，他之后很可能把那个站点当成“默认世界”。只要还能用，他就不会到处比价；只要客服还在，他就觉得安全；只要群里有人说“这个稳”，他就懒得再查。\n4、贵的也有人买单 更有意思的是，便宜站卷成这样，贵站也不是活不下去。\n比如 Toy\u0026rsquo;s Tech Notes 上这篇《孙宇晨涉足AI中转服务：B.ai新用户送50万积分，API价格对标官方 》，里面提到 B.ai 给新用户送 50 万积分，API 调用价格与 OpenAI 等官方模型保持一致。大家调侃的“孙割”一出手，打法还是熟悉的味道：送积分、做声量、先把人拉进来。\n我又去翻了一下 B.AI 官方文档的 Pricing and Usage 。它的计价单位是 Credits，文档里写的是 1 USD = 1,000,000 Credits。在这套换算下，GPT-5.4 是输入 2.50 Credits/Token、输出 15.00 Credits/Token，也就是约 $2.5 / 1M 输入、$15 / 1M 输出；GPT-5.5 是输入 5.00 Credits/Token、输出 30.00 Credits/Token，也就是约 $5 / 1M 输入、$30 / 1M 输出。\n这就很有意思了。前面那些中转站已经能把 gpt-5.4 做到输入 0.2 / 1M、输出 1.2 / 1M，甚至还有更夸张的 0.01 / 1M 标价；B.AI 这里按 Credits 折算下来，价格一下子回到另一个世界。\n问题在于，如果一个中转站价格对标官方，甚至经过积分换算、充值门槛、汇率和损耗之后让人感觉比官方还贵，那它为什么还有人用？\n原因其实也不复杂。\n有人不会注册官方账号，有人不想折腾海外支付，有人只相信自己所在社群里反复出现的推荐；有人觉得“贵一点但有人教我用”很值；还有人只是被活动文案吸引，看到“送 50 万积分”就先冲进去试试。\n这就不是单纯的价格问题了，而是分发问题、信任问题、信息差问题。\n信息茧房不是不知道便宜，而是不知道自己该比什么 很多人以为信息茧房是“用户不知道外面有更便宜的站”。但我觉得更准确一点说，是用户不知道自己应该比较什么。\n他可能知道 A 站便宜、B 站贵，但他不知道应该看输入价还是输出价，不知道缓存价是什么意思，不知道图片接口按请求还是按张，不知道同名模型可能有不同渠道，不知道 gpt-5.5 这个名字背后到底是不是自己以为的那个东西。\n所以最后就变成：谁把教程写得更顺，谁在群里回复更快，谁的控制台看起来更像那么回事，谁就更容易成交。\n价格表只是表面。真正影响购买的是路径依赖。\n5、内卷和茧房会同时存在 按理说，一个市场只要足够透明，价格差就会被慢慢抹平。但 AI 中转站偏偏不是这样。\n因为它不是一个完全透明的商品市场。它混合了模型调用、代理服务、支付通道、账号池、额度池、风控、售后、社群运营、教程分发。用户买的也不只是 token，而是“我能不能马上用起来”。\n所以低价站会继续卷，卷到一部分人只赚流水不赚钱；贵价站也会继续活着，靠品牌、圈层、教程、活动和信息差吃饭。\n这就是现在很割裂的地方：同一个模型，有人用 0.01 / 1M 的价格薅到飞起，也有人按接近官方甚至更贵的价格充值，还觉得自己找到了靠谱渠道。\n6、最后 我倒不是说所有中转站都不好。相反，中转站确实解决了很多现实问题：支付、网络、统一接口、模型聚合、额度管理、团队分账，这些对普通用户和小团队都很有价值。\n但这个行业现在的问题也很明显：价格太乱，命名太乱，渠道太黑箱，宣传又太会包装。\n以后看中转 API 站点，我觉得至少要多问几句：\n这个价格是输入价、输出价，还是综合价？ 图片生成是按请求、按张，还是失败也计费？ 同名模型有没有偷换渠道或降级？ 高峰期延迟、限速、失败率怎么样？ 余额、日志、用量明细能不能对得上？ 站点跑路时，剩余额度有没有任何保障？ 便宜可以用，贵也不是一定不能用。真正怕的是自己没有比较能力，只是被某个信息流推着走。\n这年头，AI API 中转站一边在内卷，一边在收割信息差。能不能省钱，很多时候不取决于谁的价格表最低，而取决于你有没有意识到：自己看到的那张价格表，可能只是一个很小的窗口。\n","permalink":"https://june6699.github.io/posts/%E4%B8%AD%E8%BD%ACapi%E7%AB%99%E7%82%B9%E5%86%85%E5%8D%B7%E5%92%8C%E4%BF%A1%E6%81%AF%E8%8C%A7%E6%88%BF%E7%9A%84%E7%8E%B0%E7%8A%B6/","summary":"\u003ch2 id=\"中转-api-站点内卷和信息茧房的现状\"\u003e中转 API 站点内卷和信息茧房的现状\u003c/h2\u003e\n\u003cp\u003e最近看了一圈 AI 中转 API 站点，最大的感受不是“这行真赚钱”，而是“这行真魔幻”。\u003c/p\u003e\n\u003cp\u003e同样是接 OpenAI、Claude、Gemini、各种国产模型，站点之间的价格可以差到离谱。低的低到像是在清库存，高的又高到让人怀疑是不是有人根本不知道官方价格长什么样。最有意思的是，便宜的站点未必没人用，贵的站点也照样有人买单。\u003c/p\u003e","tags":["技术","技术/AI"],"title":"中转 API 站点内卷和信息茧房的现状"},{"content":"EYKTHYR：从空间多组学中寻找驱动基因程序的转录因子 1. 文章信息 原文：EYKTHYR reveals transcriptional regulators of spatial gene programs DOI：10.1101/2025.05.19.654884 PubMed：PMID 40475415 代码：gkrieg/eykthyr 作者：Spencer Krieger, Ellie Haber, Jian Ma 机构：Carnegie Mellon University 类型：bioRxiv 预印本，尚未同行评议 版本日期：2025-05-23 这篇文章提出的 EYKTHYR 是一个面向空间多组学的转录因子调控推断框架。它把空间转录组、空间染色质可及性和细胞空间邻域放到同一个可解释模型里，通过模拟 in silico TF knockout 来判断哪些转录因子可能驱动了特定空间基因程序。\n一句话说，它不是单纯问“哪个 TF 表达高”，而是问：在某个空间区域里，哪个 TF 的可及 motif 信号最可能解释某个空间 gene program 的变化。\n2. 为什么这篇文章值得看 空间组学现在越来越容易同时拿到两类信息：一类是 RNA 表达，另一类是染色质可及性。问题是，有了这两张图以后，我们通常还是停留在比较表达量、比较 peaks、做 pathway enrichment 这些层面。它们能告诉我们“哪里不同”，但不太能直接回答“谁在驱动这些空间状态差异”。\n传统 GRN 推断方法在这里有几个麻烦：\n很多方法没有显式使用空间上下文，会把局部组织微环境里的调控信号平均掉。 如果只依赖 TF 自身的 RNA 表达，遇到 TF 低表达或 dropout 时很容易漏掉真正重要的调控因子。 空间多组学数据往往稀疏，直接在 gene-level 上做调控网络，参数多、噪声大、解释也不稳。 EYKTHYR 的切入点很聪明：先把表达矩阵压缩成少数可解释的空间 metagene，再把 ATAC 数据转成 TF activity，然后在每个局部空间邻域里拟合 TF 到 metagene 的影响。这样既降低噪声，又保留了“某个 TF 影响哪个空间基因程序”的解释性。\n3. 先理解两个概念：metagene 和 dropout 3.1 Metagene 不是一个真实基因，而是一组空间基因程序 Metagene 可以先按“宏基因”来理解，但它不是基因组里真实存在的一段 DNA，而是从表达矩阵中学出来的一个抽象变量。更直白地说，它代表一组在空间上协同表达、共同反映某种组织功能或细胞状态的基因。\n如果单个基因像一个乐手，metagene 更像一个乐队；如果单个基因像一个员工，metagene 更像一个部门。真正有生物学意义的往往不是某一个基因孤零零地升高，而是一组基因一起形成一个空间表达程序，例如神经分化、细胞周期、axon guidance 或特定组织区域的 identity。\n在数学上，可以把每个 metagene 看成一组基因的加权组合。某个基因权重越高，说明它越能代表这个空间程序；某个细胞或 spot 的 metagene score 越高，说明这个空间程序在该位置越活跃。因此，metagene 同时有两层含义：一层是“哪些基因组成这个程序”，另一层是“这个程序在哪里强、在哪里弱”。\n3.2 Dropout 让单个基因层面的判断很不稳 空间转录组和单细胞数据里有大量 0。这里要先区分两种 0：一种是真 0，也就是基因确实没有表达；另一种是假 0，也就是基因本来有 RNA，但因为捕获、反转录、PCR 扩增或测序深度等技术原因没有被检测到，这就是常说的 dropout。\n低表达基因尤其容易遇到这个问题。一个细胞里某个转录本可能本来就只有几个到几十个拷贝，组织处理、RNA 捕获、扩增和测序每一步都会损失一部分信号。空间数据还会受到组织切片质量、局部 RNA 扩散、spot 分辨率和测序深度的影响。所以，如果直接拿单个 gene-level 表达去推断调控关系，很多结果可能只是技术稀疏性造成的假象。\n这也是为什么 EYKTHYR 不急着在每个基因上直接建一个巨大的 GRN。单个基因可能被 dropout 打成 0，但一组功能相关、空间上共表达的基因不太可能同时全部丢失。把它们压缩成 metagene，相当于用群体信号降低单个基因缺失和随机噪声的影响。\n3.3 为什么线性设计重要 EYKTHYR 的核心不是“用复杂模型硬猜缺失值”，而是用两层相对透明的线性关系把问题拆开。\n第一层是 gene 到 metagene。表达矩阵被压缩成少数 metagene 后，模型不再追着几万个稀疏基因跑，而是分析几十个更稳定的空间基因程序。这一步能减少参数量，也能把随机噪声平均掉。\n第二层是 TF activity 到 metagene。EYKTHYR 从 ATAC peak 和 motif 信息推断 TF activity，再在每个局部空间邻域里用 Ridge regression 学习“哪些 TF activity 能解释哪些 metagene 的变化”。这样得到的不是一个全局平均调控网络，而是带空间位置的 TF-metagene 权重。\n线性关系的好处是解释路径很清楚：敲掉某个 TF 后，模型可以先预测哪些 metagene 会变，再根据 metagene 的基因权重把变化投回 gene-level。这里不需要把它理解成严格的矩阵求逆或万能补全；更准确地说，它提供了一条可追踪的解释链：TF activity -\u0026gt; metagene shift -\u0026gt; affected genes/pathways。\n4. 方法主线 Figure 1 基本把全文的方法逻辑画完了。左边输入是 paired spatial multiome：同一位置或同一细胞上的 RNA expression 与 chromatin accessibility。中间有两个关键转换：表达矩阵通过 POPARI 变成 metagenes；ATAC peaks 通过 motif annotation 变成 TF activity。右边的核心动作是对某个 TF 做虚拟敲除，也就是把该 TF activity 设为 0，再观察 metagene、cell identity 和下游基因会怎样变化。\n可以把它拆成六步：\n用 POPARI 将表达矩阵嵌入到低维 metagene 空间。每个 metagene 对应一组空间共表达基因，因此 metagene 的变化还能映射回 gene-level。 用 ArchR、MACS2 等流程处理 ATAC 数据，得到 cell-by-peak 矩阵。 用 motif annotation 得到 peak-by-TF motif 矩阵，再通过 A = P T 把 peak accessibility 转成 TF activity。 对每个 cell 或 spot 取空间近邻。作者经验上使用 100 个邻居较稳定，其中一半来自同 cell type，一半不限制 cell type。 在每个局部邻域里训练 Ridge regression，把 TF activity 映射到 metagene expression，得到局部 TF-metagene influence weights。 对某个 TF 做 in silico knockout，把该 TF 的 activity 设为 0，再通过线性权重传播到 metagene 和 gene-level，观察细胞状态、空间区域和通路层面的变化。 这个设计最重要的地方，是它没有把空间多组学整合做成一个黑箱分数。TF activity 到 metagene、metagene 到 gene expression 都保持线性映射，所以结果可以一路解释到“哪个 TF、哪个 metagene、哪些基因、哪个空间 compartment”。\n5. 核心结果 5.1 小鼠脑发育：找到 pallium differentiation 的空间调控因子 作者首先在 MISAR-seq 小鼠胚胎脑发育数据上测试 EYKTHYR，关注 progenitors 向 dorsal pallium ventricular region、dorsal pallium mantle region 和 subpallium 的分化。\n他们整理了文献中已知的 pallium differentiation 相关 TF，包括 Arx、Emx1、Emx2、Gli3、Lef1、Lhx2、Nr2e1、Pax6、Sp8 等。EYKTHYR 的评价方式不是只看 TF 排名，而是模拟 TF knockout 后，看细胞簇分离度、混合程度和扰动方向是否发生合理变化。\n结果显示，top 20 TF 中有 14 个与 pallium、forebrain 或 visual cortex development 有关。已知 regulator 在多个指标上显著靠前，包括 silhouette、iLISI、PCR 和综合分数。相比之下，CellOracle 和 expression-only EYKTHYR 都没有明显优于随机，说明空间信息和 chromatin accessibility 在这个任务里确实提供了额外信息。\n这部分结果给全文立住了第一个可信点：EYKTHYR 不是把非空间 GRN 方法硬套到空间数据上，而是确实利用了局部空间邻域和 ATAC motif activity。\n5.2 Msx1 案例：低表达 TF 也能被 ATAC 信号救回来 Msx1 是这篇文章最有说服力的案例之一。它在该组织中的 RNA 表达很低，如果只看 TF transcript expression，很容易把它当作“不重要”。但 EYKTHYR 根据染色质可及性推断出 Msx1 在 pallium 和 diencephalon 中有较强 activity，并预测它调控 DPallv 相关 metagene m11。\n更关键的是，作者把 metagene 变化映射回 gene-level 后，发现预测的 downstream genes 显著富集于已有小鼠 GRN 中的 Msx1 downstream genes，P 值达到 4e-7。这说明模型不只是给出了一个漂亮的空间图，而是能和外部调控证据对上。\n文章还提出了一个很有意思的候选机制：Nrg1 isoform II 的 alternative TSS 附近约 650 bp 有 Msx1 motif，并且落在 ENCODE proximal cCRE 区域内。该 isoform 主要在 DPallv 表达，还和神经发育、精神分裂症相关线索有关。作者据此提出，Msx1 可能调控 Nrg1 isoform II 的区域特异表达。\n这张图最值得看的地方，是它展示了为什么不能只盯着 TF 的 RNA 表达。Msx1 的 transcript 很稀疏，但 chromatin accessibility 推出来的 activity 更连续，也更有空间结构。对空间多组学来说，这种“RNA 不显眼、ATAC 很显眼”的 TF 可能正是最容易被传统分析漏掉的一类。\n5.3 小鼠 hindbrain：沿 radial glia 分化轨迹识别 Hes1 第二个应用换成了小鼠胚胎 hindbrain 的 spatial ATAC/RNA-seq 数据，研究 radial glia 向 postmitotic premature neurons 分化。这里的问题不再是离散细胞簇是否分开，而是连续发育轨迹会怎样被 TF perturbation 改变。\n作者用 ventricle spots 的空间距离定义 pseudotime，然后比较自然分化方向向量和 TF knockout 引起的 metagene shift 向量。简单说，如果敲掉某个 TF 后，细胞状态明显沿着或逆着发育方向移动，那这个 TF 就可能参与了这个分化过程。\nEYKTHYR 在这里突出了 Hes1。模型显示 Hes1 强烈影响 ventricle-proximal cells 中的 metagene m13；降低 Hes1 activity 后，ventricle cells 变得更像 hindbrain cells。这和 Hes1 缺失会导致 premature neuron production 和 progenitor depletion 的已知表型相符。\n更强的证据来自 gene-level downstream genes：Hes1 perturbation 预测的下游基因与外部小鼠 GRN 高度富集，P 值为 8.1e-37，并富集 glial differentiation、axon guidance、nervous system development、L1CAM interactions 等通路。\n这部分还有一个细节很重要：同一个 TF 的作用不是全组织一致的。文章显示 Hes1 在 ventricle-proximal 区域和 CNS 区域影响的 metagene 不同，说明 TF regulation 需要放回具体空间 compartment 里理解。\n5.4 人黑色素瘤：T cell 状态受肿瘤微环境约束 第三个应用是 human metastatic melanoma 的 Slide-tags single-cell multiome 数据。原研究按 tumor transcriptomic signature 定义了两个 tumor compartments，并分析 T cell infiltration；EYKTHYR 的 metagene 分析进一步区分出 proliferating T cells。\n在 proliferating T cells 中，EYKTHYR 识别出 KLF4 和 YY1 具有 compartment-specific effects。KLF4 在两个 tumor compartments 中作用方向不同，符合它在不同上下文中既可能限制 T cell proliferation，也可能影响 exhaustion 的复杂角色。\nYY1 的案例更能体现“空间上下文”的价值。作者模拟 YY1 knockout 后，发现 metagene m3 和 m4 在不同 tumor compartment 中的变化方向和幅度不同；这些变化还与 YY1 binding sites 的 promoter accessibility 差异有关。进一步筛选含 YY1 promoter motif 且 compartment 间 accessibility 不同的基因后，bottom tumor compartment 中 cell-cycle pathways 富集，而 top compartment 中没有类似富集。\n也就是说，同一个 TF 并不是在整张组织切片上执行同一套程序。局部肿瘤微环境会改变它影响 T cell 状态的方式。\n6. 这篇文章的创新点 明确面向 spatial multiome 的 TF regulator inference，而不是把非空间 scRNA/scATAC GRN 方法直接套上去。 用 metagene 作为中间层，降低稀疏数据中的噪声和参数量，同时保留 gene-level 可解释性。 从 chromatin accessibility 推断 TF activity，因此能识别 RNA 表达很低但 motif-accessibility 信号强的 TF，例如 Msx1。 每个细胞或 spot 都有局部 TF-metagene weights，因此可以分析 region-specific regulatory effects。 in silico knockout 不只输出 TF 排名，还能预测 cell identity shift、空间向量场、受影响 metagene 和下游通路。 我觉得最值得借鉴的是第二点和第四点。很多空间组学文章会把空间结构当成可视化结果，但 EYKTHYR 是把空间邻域放进了调控模型本身。它的输出天然带着“在哪里起作用”的信息，而不是事后再把结果投回空间图上。\n7. 需要谨慎看待的地方 这篇文章的方法思路很清晰，但也有几个地方不能看得太满。\n第一，它仍然是 bioRxiv 预印本，尚未同行评议。结论可以作为很好的候选假设来源，但不要直接当成已经被实验完全验证的调控网络。\n第二，EYKTHYR 依赖 paired spatial transcriptome 和 spatial chromatin accessibility 数据。这类数据目前还不算特别普及，如果只有普通空间转录组，方法的核心优势就发挥不出来。\n第三，模型假设 TF activity 到 metagene expression 的关系近似线性。这个假设带来了可解释性，但也可能错过 TF cooperation、threshold effect、context-dependent enhancer logic 等非线性调控关系。\n第四，TF activity 是由 motif-bearing accessible peaks 近似得到的。motif 出现在开放区域，并不等于该 TF 一定真实占据了这个位点，也不能直接处理 cofactor、protein abundance 和 post-translational modification。\n第五，in silico knockout 更适合用来做方向判断和候选排序，不应理解成真实扰动实验的定量替代。真正要坐实某个 TF 的空间调控作用，还是需要 Perturb-FISH、spatial CRISPR 或类似实验验证。\n8. 对后续工作的启发 如果我们的研究问题涉及空间组织结构中的 cell state transition、发育轨迹或 tumor microenvironment，EYKTHYR 值得重点关注。它给我的启发不是“又多了一个 GRN 软件”，而是提供了一种问题重构方式：\n先把空间表达模式抽象成 metagene 或 gene program。 再把 chromatin accessibility 转成 TF activity。 最后问某个 TF 的局部 activity 变化，会让哪个空间 gene program、哪个细胞状态、哪个组织区域发生改变。 这比单纯比较 DEG 或 peak accessibility 更接近“谁在驱动空间状态变化”的问题。尤其是在我们有 RNA + ATAC 或其他空间多组学数据时，可以先用类似思路筛出候选 TF，再把最可信的几个交给后续实验或更细的机制分析。\n另一个值得注意的点是 metagene。空间数据通常很吵，直接在 gene-level 上做模型容易不稳定。把空间共表达模式先压缩为 metagene，既能减少参数量，也更符合“组织区域通常由一组 gene program 定义”的直觉。这个思想不一定只能用于 EYKTHYR，也可以迁移到其他空间多组学整合任务里。\n9. 阅读顺序建议 如果只是快速读这篇文章，我建议按这个顺序：\n先看 Figure 1 和 Methods 的模型部分，确认 metagene -\u0026gt; TF activity -\u0026gt; local ridge regression -\u0026gt; in silico knockout 这条链路。 再看 Figure 3 的 Msx1 案例，因为它最能说明为什么要用 chromatin accessibility，而不是只看 TF expression。 接着看 Figure 5 的 Hes1 案例，理解连续发育轨迹下如何评价 TF perturbation。 最后看 Figure 6 的 melanoma 案例，用来理解同一个 TF 为什么会有 tumor compartment-specific effect。 整篇文章最核心的句子可以概括成：空间多组学里的调控因子，不应该只按全局表达量排序，而应该放在局部空间邻域、染色质可及性和 gene program 变化之间一起判断。\n","permalink":"https://june6699.github.io/posts/eykthyr-spatial-gene-programs/","summary":"\u003ch1 id=\"eykthyr从空间多组学中寻找驱动基因程序的转录因子\"\u003eEYKTHYR：从空间多组学中寻找驱动基因程序的转录因子\u003c/h1\u003e\n\u003ch2 id=\"1-文章信息\"\u003e1. 文章信息\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e原文：\u003ca href=\"https://www.biorxiv.org/content/10.1101/2025.05.19.654884v1\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\u003ccode\u003eEYKTHYR reveals transcriptional regulators of spatial gene programs\u003c/code\u003e\u003c/a\u003e\n\u003c/li\u003e\n\u003cli\u003eDOI：\u003ca href=\"https://doi.org/10.1101/2025.05.19.654884\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\u003ccode\u003e10.1101/2025.05.19.654884\u003c/code\u003e\u003c/a\u003e\n\u003c/li\u003e\n\u003cli\u003ePubMed：\u003ca href=\"https://pubmed.ncbi.nlm.nih.gov/40475415/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\u003ccode\u003ePMID 40475415\u003c/code\u003e\u003c/a\u003e\n\u003c/li\u003e\n\u003cli\u003e代码：\u003ca href=\"https://github.com/gkrieg/eykthyr\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\u003ccode\u003egkrieg/eykthyr\u003c/code\u003e\u003c/a\u003e\n\u003c/li\u003e\n\u003cli\u003e作者：Spencer Krieger, Ellie Haber, Jian Ma\u003c/li\u003e\n\u003cli\u003e机构：Carnegie Mellon University\u003c/li\u003e\n\u003cli\u003e类型：\u003ccode\u003ebioRxiv\u003c/code\u003e 预印本，尚未同行评议\u003c/li\u003e\n\u003cli\u003e版本日期：2025-05-23\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e这篇文章提出的 \u003ccode\u003eEYKTHYR\u003c/code\u003e 是一个面向空间多组学的转录因子调控推断框架。它把空间转录组、空间染色质可及性和细胞空间邻域放到同一个可解释模型里，通过模拟 \u003ccode\u003ein silico TF knockout\u003c/code\u003e 来判断哪些转录因子可能驱动了特定空间基因程序。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/论文"],"title":"EYKTHYR：从空间多组学中寻找驱动基因程序的转录因子"},{"content":"项目列表 June6699 VibeCoding 今年的VibeCoding单中转站使用token达到10亿纪念。\n","permalink":"https://june6699.github.io/posts/2026-%E5%B9%B4%E6%80%BB/","summary":"\u003ch3 id=\"项目列表\"\u003e项目列表\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/June6699\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eJune6699\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/images/2026%20%e5%b9%b4%e6%80%bb/image-20260504041708463.png\" alt=\"image-20260504041708463\" width=\"2531\" height=\"465\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch3 id=\"vibecoding\"\u003eVibeCoding\u003c/h3\u003e\n\u003cp\u003e今年的\u003ccode\u003eVibeCoding\u003c/code\u003e单中转站使用\u003ccode\u003etoken\u003c/code\u003e达到10亿纪念。\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/images/2026%20%e5%b9%b4%e6%80%bb/image-20260504040929924.png\" alt=\"image-20260504040929924\" width=\"2552\" height=\"1405\" loading=\"lazy\" /\u003e\n\u003c/p\u003e","tags":["生活","生活/记录"],"title":"2026 年终总结"},{"content":"那年夜色里，父亲教我的担当 岁月如白驹过隙，那些藏在童年褶皱里的细碎往事，大多已在时光的冲刷下变得模糊斑驳，唯有那个漆黑的夜晚，那声清脆的陶瓷碎裂声，以及父亲那句沉甸甸的教诲，如同镌刻在时光里的印记，历经岁月沉淀，愈发清晰可辨。那是我初二的年纪，正是懵懂无知、遇事只会逃避的年纪，而那场意外，恰似一盏微光，照亮了我成长的前路，也让我读懂了担当的重量。\n初二的日子，像被上了发条的时钟，紧凑得让人喘不过气。每日清晨六点半，天还未亮透，窗外仍是疏星淡月，我便要揉着惺忪的睡眼，告别温暖的被窝，踏上上学的路；直到深夜十一点二十分，晚自习的铃声才会划破校园的寂静，我拖着疲惫的身躯，在夜色中匆匆往家赶。我家在一条老街上，青石板路被岁月磨得光滑发亮，中间的主干道狭窄得只能容两辆车勉强交汇，可偏偏总有车辆随意停放，挤占了大半通行空间。无奈之下，我只能沿着每家门口那一米左右的空地行走，脚下是冰凉的石阶，身旁是斑驳的墙壁，墙壁上爬满了翠绿的爬山虎，在夜色里像一团团模糊的影子，无声地陪伴着我每一个晚归的夜晚。\n那夜，和往常一样，我走出校门时，夜色已浓得化不开，像一块浸了墨的绒布，将整条老街裹得严严实实。没有路灯的映照，没有商铺灯牌的点缀，连天边微弱的月光，也被邻居家探出的二楼屋檐切割得支离破碎，只剩零星的微光，勉强勾勒出道路的轮廓。能见度低得可怕，伸手几乎不见五指，我只能凭着记忆，小心翼翼地沿着墙根前行，耳边只有自己的脚步声，在寂静的老街上格外清晰，偶尔传来几声远处的犬吠，更添了几分夜的静谧与清冷。古人云“月黑风高夜”，彼时虽无狂风，可那份伸手不见五指的漆黑，却比狂风更让人心里发慌。\n晚自习的疲惫像潮水般涌来，眼皮沉重得几乎要粘在一起，可脑海里，却还盘旋着那道未解的数学题。那道几何题的辅助线，像一团乱麻，缠绕在我的思绪里，剪不断，理还乱，我皱着眉，反复在心里推演，却始终找不到突破口，烦躁与困意交织在一起，让我只想快点回到家，钻进温暖的被窝，将所有的疲惫与烦恼都抛诸脑后。快走到家门口时，急切的心情压过了所有的谨慎，我情不自禁地小跑起来，脚步轻快，却没注意到，邻居家门口的石阶旁，静静摆放着两个硕大的陶瓷花盆。\n“砰——咔嚓——”\n突如其来的撞击让我浑身一震，脚下一个趔趄，险些摔倒。紧接着，一声刺耳又清脆的陶瓷碎裂声划破了老街的寂静，那声音像一把小锤子，狠狠砸在我的心上，瞬间驱散了所有的困意与烦躁。我浑身僵硬，下意识地回头，夜色太暗，只能看到地上散落的碎片，模糊的影子里，仿佛藏着无数双审视的眼睛。恐惧瞬间攫住了我，心跳快得像要冲出胸膛，手心冒出了冷汗，脑海里一片空白，只有一个念头在疯狂叫嚣：我闯祸了，我撞碎了邻居的花盆，他们会不会骂我？会不会让我赔偿？\n怯懦像藤蔓一样缠绕住我的心脏，我不敢多想，也不敢停留，连道歉的勇气都没有，转身就朝着家的方向狂奔。脚下的石子硌得脚掌生疼，却不及我心里的万分之一慌乱，身后的陶瓷碎片仿佛在无声地控诉，而我，只能用逃跑来掩饰自己的恐惧与愧疚。就像犯错的孩子，总以为只要躲起来，就没有人会发现自己的过错，却不知，那份未说出口的愧疚，早已在心底生根发芽，沉甸甸地压得人喘不过气。\n冲进家门，母亲早已等候在客厅，灯光温柔，驱散了我身上的寒意。“回来了？今天累不累？”母亲的声音温柔得像春日的细雨，可我却不敢抬头看她的眼睛，生怕自己眼底的慌乱暴露了心底的秘密。我强装镇定，摇了摇头，声音细若蚊蚋：“不累。”说完，便匆匆拿起衣物，冲进浴室，冰冷的水流冲刷着我的身体，却洗不掉心底的愧疚与不安。我不敢告诉母亲，那个漆黑的夜晚，我撞碎了邻居的花盆，更不敢告诉她，我是如何狼狈地逃跑，如何不敢面对自己的过错。那晚，我躺在床上，翻来覆去难以入眠，脑海里反复回响着那声陶瓷碎裂的声音，眼前不断浮现出散落的碎片，心里的愧疚像潮水般反复冲刷着我的良知，一夜无眠，唯有满心的忐忑与不安。\n第二天中午，我拖着疲惫的身躯回到家，刚走进家门，就看到了隔壁的叔叔，他正坐在客厅的沙发上，和父亲低声交谈着什么。那一刻，我的心瞬间提到了嗓子眼，浑身的血液仿佛都凝固了，脚步像灌了铅一样沉重，再也挪不动一步。我低着头，目光死死地盯着自己的脚尖，脸颊发烫，耳朵也烧得厉害，连呼吸都变得小心翼翼，生怕叔叔认出我，生怕父亲责备我。我能感觉到，父亲的目光落在了我的身上，那目光里没有愤怒，却带着一种不容回避的严肃，让我更加羞愧难当。\n果然，父亲朝我招了招手，语气平静却带着不容置疑的力量：“过来。”我慢吞吞地走过去，头埋得更低了，做好了迎接责备的准备。“昨天晚上，是不是你撞碎了叔叔家的花盆？”父亲的声音不高，却像一记重锤，敲在我的心上。我咬着嘴唇，点了点头，眼泪在眼眶里打转，却不敢掉下来。叔叔笑着打破了尴尬，指了指墙角的监控，语气里没有丝毫责备：“你这孩子，跑那么快，还好监控拍得清楚，不然我还不知道是谁呢。”我低着头，脸颊发烫，心里既羞愧又庆幸，没想到这不起眼的监控，竟把一切都记录了下来，此刻再想起，倒也多了几分自嘲的笑意。\n父亲拍了拍我的肩膀，语气严肃起来：“犯错不可怕，可怕的是犯错后不敢面对，不敢承担。”说着，他转向叔叔，诚恳地说道：“大哥，实在对不住，孩子年纪小，不懂事，撞碎了你的花盆，我给你赔200块钱，算是弥补你的损失，也让孩子记住这个教训。”叔叔连忙摆了摆手，笑着说道：“没事没事，大晚上的，天色那么暗，也看不清，而且我这花盆也确实挡路了，不能全怪孩子。”说着，他就想推辞那200块钱，可父亲却坚持让他收下，语气坚定：“该赔的，我们一分都不能少，这不仅是赔偿，更是让孩子学会承担责任。”\n父亲转过身，看着我，眼神里满是期许：“低头，给叔叔道歉。”那一刻，我心里的恐惧与羞愧交织在一起，仿佛有无数根针在扎着我的心，我感觉自己的脸颊烧得滚烫，喉咙像被什么堵住了一样，半天说不出一句话。我咬着嘴唇，用尽全身的力气，低着头，声音发颤地说道：“叔叔，对不起，我昨天晚上撞碎了你的花盆，我错了。”说完，眼泪终于忍不住掉了下来，那是愧疚的泪，是恐惧的泪，也是羞愧的泪。\n可让我没想到的是，叔叔却轻轻拍了拍我的头，语气温柔而宽厚：“没事孩子，知道错了就好，以后走路小心点就可以了。你现在正是好好学习的年纪，别因为这点小事影响了心情，好好努力，将来考个好成绩。”叔叔的话，像一股暖流，瞬间驱散了我心底的恐惧与羞愧，让我忍不住抬起头，看着他温和的笑容，心里满是感激。\n走出叔叔家，父亲没有责备我，只是牵着我的手，慢慢走在老街上。阳光透过树叶的缝隙，洒在青石板路上，斑驳陆离，温暖而明亮。父亲语重心长地对我说：“孩子，人生路上，难免会犯错，就像走路会不小心摔倒一样。但摔倒了，不能一直趴在地上，要学会站起来，拍拍身上的灰尘，勇敢地面对自己的错误，承担自己的责任。逃避从来都不是解决问题的办法，只会让你心里的愧疚越来越深，唯有直面错误，才能卸下心里的重担，获得真正的释然。”\n那一刻，我忽然读懂了父亲的话语，也读懂了那份藏在话语里的爱与期许。古人云：“人非圣贤，孰能无过；过而能改，善莫大焉。”那个夜晚，我以为自己闯下了天大的祸，以为天就要塌下来了；道歉的时候，我羞愧得无地自容，仿佛脚下的土地都要陷下去了；可当我说出那句“对不起”，当叔叔原谅我的那一刻，我忽然觉得，所有的恐惧与愧疚都烟消云散了，天地皆通，心里豁然开朗。\n如今，多年过去，我早已不再是那个遇事只会逃避的懵懂少年，那场意外，那段经历，以及父亲的教诲，都已成为我成长路上最珍贵的财富。我渐渐明白，人生本就没有一帆风顺的坦途，总会遇到各种各样的风浪与挫折，总会犯下这样那样的错误。正如汪国真所说：“人生没有笔直的路，所谓的捷径，不过是迂回的风景。”那些曾经让我们恐惧、让我们羞愧的过错，那些曾经让我们觉得天塌地陷的困境，回过头来看，不过是成长路上的一场小风雨，不过是岁月里的一点风霜而已。\n感谢父亲，用他的以身作则，教会我何为责任，何为担当；感谢那个漆黑的夜晚，感谢那场意外，让我在懵懂中成长，在愧疚中醒悟。往后余生，无论遇到多大的困难，无论犯下多大的错误，我都会记得父亲的教诲，勇敢地直面问题，勇敢地承担责任，不逃避，不退缩。因为我知道，唯有直面，方能心安；唯有担当，方能成长。那些走过的弯路，那些犯下的过错，最终都会化作成长的养分，滋养我们成为更好的自己，照亮我们前行的每一步。\n","permalink":"https://june6699.github.io/posts/%E5%A4%9C%E6%B7%B1%E5%BF%BD%E6%A2%A6%E5%B0%91%E5%B9%B4%E4%BA%8B2/","summary":"\u003ch2 id=\"那年夜色里父亲教我的担当\"\u003e那年夜色里，父亲教我的担当\u003c/h2\u003e\n\u003cp\u003e岁月如白驹过隙，那些藏在童年褶皱里的细碎往事，大多已在时光的冲刷下变得模糊斑驳，唯有那个漆黑的夜晚，那声清脆的陶瓷碎裂声，以及父亲那句沉甸甸的教诲，如同镌刻在时光里的印记，历经岁月沉淀，愈发清晰可辨。那是我初二的年纪，正是懵懂无知、遇事只会逃避的年纪，而那场意外，恰似一盏微光，照亮了我成长的前路，也让我读懂了担当的重量。\u003c/p\u003e","tags":["生活","生活/文章"],"title":"夜深忽梦少年事2"},{"content":" 重要 本文为梦中所梦，并非真实发生的故事，我父母对我很好。\n冬雪落满作业本 凌晨醒来时，枕巾已经洇湿了一大片。窗外的天还蒙着一层灰蓝，我摸着自己的脸颊，指尖竟还能触到一丝恍惚的灼痛感——原来昨夜的梦，把封存在童年里的那个冬天，原封不动地拽回了眼前。\n我是被奶奶一手带大的。不是爷爷奶奶，爷爷在我还记不住人脸的年纪就走了，偌大的老屋里，只有我和奶奶两个留守的人，守着日升月落，守着一年四季，也守着村口那条通往外面的马路。那时候的日子过得很慢，慢到我能把日历上标着春节的那个红圈，用铅笔描了一遍又一遍，描到纸页都起了毛。我总在盼，盼着过年，盼着爸爸妈妈回来。\n我总跟奶奶坐在门口的晒谷场——就是家门口那块水泥打的小场子，是我整个童年里最常待的地方。晒谷场的矮桌旁，摆着我们家最好的那把高椅，哪怕它的右边扶手裂了一道长长的缝——那是我去年爬树摔下来磕的，奶奶心疼了好久，找了细铁丝一圈圈缠牢，依旧稳稳当当的。村里别家的孩子都坐矮板凳趴石墩写字，只有我，奶奶说读书写字要坐端正，专门把这把椅子留给我，平日里我都舍不得乱碰，只有写作业、坐在晒谷场等爸妈回家的时候，才会小心翼翼地坐上去。我扒着矮桌翻课本，耳朵却始终竖起来，捕捉着村口的每一声车鸣，每一阵脚步声。我攒了满满一抽屉的奖状，把考了满分的试卷压在枕头底下，连奶奶给我缝的新棉袄，都要留到爸妈回来那天再穿。我总觉得，只要他们回来了，我就不是那个被同学笑“没爸妈管”的孩子了，我就有靠山了，就有藏了一年的话，能说给人听了。\n那年的寒假，天格外晴。阳光晒得晒谷场暖融融的，连风都裹着屋檐下晒萝卜干的甜香。忽然就听见村口有熟悉的声音喊我的小名，我猛地从高椅上站起来，手里的课本“啪嗒”一声掉在矮桌上，抬头就看见马路那头，爸爸妈妈正拎着大包小包，一步一步朝我走来。阳光落在他们身上，给他们的衣角镶了一圈金边，妈妈的头发长了，爸爸的脸黑了些，可他们脸上的笑，是我在电话里、在照片里，盼了一整年的模样。\n我什么都顾不上了，光着脚就冲了过去。风在耳边呼呼地响，心里的雀跃快要从嗓子眼里跳出来。爸爸快步迎上来，一把把我举过头顶，他的身上有柴油和烟草混在一起的味道，是我陌生又贪恋的、属于爸爸的味道。妈妈摸着我的头，指尖带着凉意，笑着说我又长高了，手里还拎着给我买的新球鞋。奶奶站在屋门口，擦着沾了面粉的手，眼角的皱纹都笑成了一朵花。那时候我以为，这一整个冬天的暖，都在这一刻，齐齐地涌进了我的怀里。\n变故是在两天后。年关将近，屋里飘着炒花生和炸丸子的香气，煤炉上的水壶滋滋地响着，客厅里传来爸爸和朋友的说笑声，烟味混着茶香飘过来。妈妈在厨房的水池边洗菜，哗哗的水声盖过了屋外的风声。我蹲在灶门口看火，灶膛里的柴火烧得噼啪响，橘红色的火苗舔着锅底，把我的手和脸都烤得暖烘烘的，这是整个寒冬里，我最熟悉的暖意。奶奶在案板边切着腊肉，刀起刀落，发出沉稳的声响。\n就是这时候，那个小女孩走了进来。她是爸爸朋友的女儿，比我小几岁，扎着两个翘翘的羊角辫，穿一身簇新的红棉袄，进门的时候还冲我笑了笑，眼睛弯成了月牙。我有些不好意思，往灶膛里添了一根柴，把脸往火光里埋了埋。可她没在我身边停留多久，转身就蹲到了墙角的水桶边。那是妈妈一早刚从井里挑回来的清水，清凌凌的，是留着洗菜、做饭、烧开水用的。\n她先是伸出一根手指，在水面上点了点，见没人说她，就把整只手都伸了进去，哗啦哗啦地搅了起来。冰凉的井水溅出来，打湿了她的棉袄袖口，也溅得满地都是水迹，干净的水面上飘起了她袖口沾的灰尘。我皱了皱眉，起身走过去，放轻了声音跟她说：“妹妹，这个水是做饭用的，不能玩，会弄脏的。”\n我话音刚落，她猛地回过头，手还泡在水里，另一只手扬起来，结结实实一个巴掌甩在了我的脸上。\n“啪”的一声脆响，在满是水声和柴火声的厨房里，格外清晰。我的半边脸瞬间烧了起来，火辣辣的疼顺着脸颊窜到耳朵根，整个人都懵了，灶膛里的火光在我眼前晃了又晃，耳朵里嗡嗡作响。她瞪着圆溜溜的眼睛，冲我恶狠狠地喊：“你管我！”\n血一下子冲上了头顶。我长这么大，奶奶从没碰过我一根手指头，连重话都没说过几句。我气的浑身都在抖，想也没想，抬手回了一下，可落下去的时候，力气卸了大半，只轻轻碰了碰她的头顶，咬着牙说：“你怎么能随便打人？”\n就这一下，她像是被踩了尾巴的猫，哇的一声哭了出来，哭声惊天动地，瞬间盖过了厨房里所有的声响。\n客厅里的说话声戛然而止。爸爸和他的朋友第一个冲了进来，妈妈也甩着手上的水跟了过来。那个男人三步并作两步冲过去，一把把小女孩抱进怀里，连声问怎么了。她窝在爸爸怀里，哭的上气不接下气，眼泪鼻涕糊了一脸，伸出手指着我，呜咽着喊：“呜呜……哥、哥哥打我……好疼……”\n我瞬间回过神来，忙开口辩解：“不是的，是她先……”\n话音还没落，一个力道重得多的巴掌，狠狠甩在了我的另一边脸上。\n是爸爸。\n这一巴掌，比小女孩的重了十倍不止。我整个人被打的踉跄了一下，撞在灶台上，嘴里瞬间漫开一股铁锈味，半边脸麻得失去了知觉，疼得我眼前发黑。可比脸上更疼的，是心口，像是被一只冰冷的手狠狠攥住，瞬间缩成了一团。\n我强忍着涌到眼眶里的眼泪，声音都在抖，一遍遍地说：“是她先动手的！她玩做饭的水，我不让她玩，她先扇我巴掌！我就碰了她一下，根本没用力！”\n“人家比你小那么多，怎么可能先打你？”爸爸的脸涨得通红，眼睛里全是怒火，冲我吼道，“肯定是你手欠，先欺负人家小姑娘！我不在家，你就被惯成这个样子？”\n“宝贝不哭不哭，阿姨给你糖吃，是哥哥不好，阿姨这就教训他。”妈妈也走了过去，摸着小女孩的头柔声哄着，转头看向我的时候，眼里全是冰冷的责备，狠狠瞪了我一眼，“作业写完了吗？一天到晚就知道惹是生非！”\n那个抱着女儿的男人，也冷着脸看向我，转头对我爸说：“老徐，你这孩子，可得好好教育教育。”\n全世界的人，都站在了我的对立面。他们都信那个哭的撕心裂肺的小女孩，没人信我，没人愿意听我说一句完整的话。\n只有奶奶。她一把把我拉到身后，用她瘦弱的身子，挡在了我和三个怒气冲冲的大人中间。她把切菜的刀往案板上一放，声音都急得发颤，却依旧挺直了腰板：“我亲眼在这看着的！是这女娃先动手打我孙子！你们不分青红皂白，上来就打孩子骂孩子，有你们这么当父母的吗？”\n“妈，您别在这护着他！”爸爸推开奶奶的手，语气更凶了，“我自己的孩子，我还不知道他什么德行？肯定是他先惹的事！您别拦着我，今天我非得好好教育教育他！”\n我站在奶奶身后，看着爸爸狰狞的脸，心里忽然泛起一阵冰冷的笑。他了解我吗？我一岁那年，他因为绑架欠薪的老板，入狱一年；我十岁的生日宴刚过，他因为赌博，又进去三年；就连我上初中的时候，他还是因为赌博，再一次离开了家。他陪在我身边的日子，加起来有没有一整年？他凭什么说，他了解我？\n就在大人们吵作一团的时候，我越过奶奶的肩膀，看见了那个窝在爸爸怀里的小女孩。她露出半张脸，眼泪还挂在脸上，嘴角却勾起了一丝不易察觉的、狡黠的冷笑，她看着我，用口型一字一顿地说：“你配做我哥哥吗？” 那一瞬间，灶膛里的火再旺，也暖不透我浑身的寒意了。\n我拉了拉奶奶的衣角，她回头看我，眼里全是心疼。我吸了吸鼻子，把快要掉下来的眼泪憋回去，轻声说：“奶奶，别说了，是我的错。我去写作业了。”\n我知道，没用的。跟这两个我并不亲近、甚至陌生的爸爸妈妈辩解，就像一个黑人，试图跟一个极端的种族歧视者讲道理一样难。他们心里早就给我定了罪，我说再多，都是错的。我更不想让奶奶为了我，跟他们争得面红耳赤，受这份委屈。\n可爸爸依旧不肯罢休。他转身就冲向晒谷场，一脚狠狠踹在那把我视若珍宝的高椅上。那是我们家最好的椅子啊，他却踹得毫不留情，椅子在冰冷的水泥地上滑出刺耳的尖响，裂了缝的扶手狠狠撞在矮桌腿上，晃了两晃，最终重重倒在了漫天风雪里。\n“出去写！”他冲我吼，唾沫星子混着烟味溅过来，“屋里容不下你这尊大佛！成绩不怎么样，欺负人的本事倒是学了不少！谁教你的？”\n我抱着作业本，站在原地，指尖掐进了纸页里。谁教我的？反正不会是你。我期末考了全班第三，三十个学生里，我稳稳排在前三。可他回来的第一件事，就是揪着我的成绩单，得知我比他发小的儿子低了十分，连我贴在墙上的奖状都没扫一眼，就把我关在房间里面壁思过。他从来没问过我，这一年在学校有没有受欺负，冬天的棉袄够不够暖，奶奶的腰疾有没有犯。他只在乎，我有没有给他挣回那点可怜的面子。\n数九寒天，外面是零下的气温。风卷着细碎的雪沫子，刮在脸上像刀子割一样。我抱着作业本走出去，先蹲下身，扶起了那把倒在雪地里的高椅。我用袖口一点点擦干净椅面和扶手上的雪，连铁丝缝里的雪沫都擦得干干净净，才把作业本铺在矮桌上，小心翼翼地坐了下去。裂了缝的扶手硌着我的胳膊，和脸上火辣辣的疼叠在一起，钝钝的，往心里钻。\n雪越下越大了，细细的雪花，从灰蒙蒙的天上落下来，落在我的头发上，落在棉袄的肩头，也落在摊开的作业本上。我握着铅笔的手冻得通红，指尖僵得几乎握不住笔杆。雪花落在田字格里，小小的雪粒慢慢化开，晕开淡淡的水痕，我用指尖轻轻一抹，就擦得干干净净。可那些大一点的雪片，落下来就融成一滩水，把铅笔写的字泡得发涨，模糊成一团。\n我握着笔，却一个字也写不下去了。\n雪还在落，一片一片飘进摊开的作业本里，融成大大小小的水洼。我伸出指尖，轻轻碰了碰那汪水，水面晃了晃，映出我通红的眼尾，映着漫天落雪的天。\n原来，这就是后来在书里读到的那句——“水中有明月，碎碎圆圆”。\n眼泪就这么毫无征兆地落了下来。\n一滴砸进水洼里，水面骤然晃荡，那轮小小的“月亮”瞬间碎了，待涟漪散去，又慢慢圆了回来。再一滴，又碎，再圆。碎碎圆圆，圆圆碎碎。\n我把脸埋在臂弯里，肩膀无声地抖着，不敢哭出声，怕屋里的大人听见，又要招来一顿责骂。只有眼泪止不住地往下淌，混着雪水，浸透了整本作业本，那些工工整整写好的字，那些算完的算术题，那些我攒了一整年、想等爸妈回来夸一句的认真，全都糊成了一团，像碎了的月亮，再也拼不回来了。\n梦到这里，就醒了。\n窗外的天已经亮了，城市的车流声隐隐传进来。我躺在被窝里，睁着眼睛看着天花板，脸上还挂着未干的泪。原来这么多年过去了，那个冬天落在脸上的巴掌，那个零下风雪里的晒谷场，那本被眼泪和雪水浸得透湿的作业本，还有那把裂了缝、却被我视若珍宝的高椅，全都安安静静地藏在我的潜意识里，在某个深夜，化作一场梦，把我拽回那个再也回不去的童年。\n小时候，我总在盼，盼着过年，盼着爸爸妈妈回来。我总以为，他们是我的光，是我的靠山，是我一整年的期盼。\n可原来，从那个雪花落满作业本的冬天开始，我就再也不想念爸爸妈妈过年回来了。\n","permalink":"https://june6699.github.io/posts/%E5%A4%9C%E6%B7%B1%E5%BF%BD%E6%A2%A6%E5%B0%91%E5%B9%B4%E4%BA%8B/","summary":"\u003cdiv class=\"callout callout-important\" data-callout=\"important\" role=\"note\" aria-label=\"重要\"\u003e\n  \u003cdiv class=\"callout-head\"\u003e\n    \u003cspan class=\"callout-icon\"\u003e\u003csvg viewBox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M8 10h8\"/\u003e\u003cpath d=\"M8 14h5\"/\u003e\u003cpath d=\"M6 19h8a4 4 0 0 0 4-4V9a4 4 0 0 0-4-4H10a4 4 0 0 0-4 4z\"/\u003e\u003cpath d=\"m6 19-2 2v-5\"/\u003e\u003c/svg\u003e\u003c/span\u003e\n    \u003cspan class=\"callout-title\"\u003e重要\u003c/span\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"callout-body\"\u003e\u003cp\u003e本文为梦中所梦，并非真实发生的故事，我父母对我很好。\u003c/p\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 id=\"冬雪落满作业本\"\u003e冬雪落满作业本\u003c/h2\u003e\n\u003cp\u003e凌晨醒来时，枕巾已经洇湿了一大片。窗外的天还蒙着一层灰蓝，我摸着自己的脸颊，指尖竟还能触到一丝恍惚的灼痛感——原来昨夜的梦，把封存在童年里的那个冬天，原封不动地拽回了眼前。\u003c/p\u003e","tags":["生活","生活/文章"],"title":"夜深忽梦少年事"},{"content":"防盗门锁芯被钥匙拧转时，林慧正在厨房里颠勺。葱花爆香的气息刚漫出来，就被一阵风风火火的脚步声撞得七零八落。\n“妈妈，妈妈！”女儿小雅的声音像颗甜脆的山楂，猝然滚进油烟缭绕的厨房，“你看这个！”林慧顿了顿，伸手去关火，锅里的热气熏得她鼻尖白亮。她扭过身，瞥见小雅举着张试卷在眼前直晃，羊角辫随着蹦跳的节律扫过她的胳膊，透出刚从外面跑回来的寒气。“慢点，当心烫着。”林慧将手在围裙上胡乱擦了擦，接过了试卷。指腹触到试卷边缘的褶皱时，她暗忖，那是被孩子攥了一路的痕迹。鲜红的97分突兀在卷首，格外醒目，像朵饱满的石榴花。\n“嗯，不错。”她的指尖划过分数，声音里漫出笑意，可目光扫到最后一道题时，笑意骤然消隐，“这道应用题，怎么会错？”\n“哎呀，”小雅满不在乎地摆摆手，马尾辫甩到身后，“就是粗心呗，算错了个数字。”\n“粗心可不是小事。”林慧把试卷平铺在不锈钢灶台边，指头点着那道红叉，“你看这些步骤都对，就最后一步掉了个零，多可惜。做题就像绣花，一针一线都懈怠不得。”\n“可我依然是全班第一呀！”小雅踮脚够着锅铲，眼睛瞟着锅里的番茄炒蛋，“王明明才考89分呢。”\n“不许跟别人比，要跟自己比。”林慧的声音低沉而严厉，“妈妈不是常跟你说，做事要力求最好吗？”\n小雅没有接话，径自去碗柜里拿碗筷，瓷碗碰撞的脆响里带着点不服气：“妈妈，我饿了，先盛饭。”\n“放下！”林慧的声音陡然拔高，惊得小雅手一抖，碗筷差点掉在地上。她看着女儿错愕的脸，胸口像塞了团浸了水的棉絮，又沉又堵，“学习态度不端正，先反省好了再吃饭。”\n“我没错！”小雅的眼圈红了，小手攥着衣角，声音带着哭腔，“我考了全班第一，你还不满意？”\n“错了就是错了，别强词夺理！”林慧的声音发颤，不知是气的还是咋的，“你咋越大越不懂事了呢？”\n妈妈迟缓地撩起衣襟擦脸，指缝间漏出的呜咽像被掐住的弦，“你三岁那年，你爸走的时候，家里欠着多少钱你知道吗？我白天在超市理货，晚上去工地扎钢筋，手上磨出的泡破了又结，结了又破，不就是盼着你能有出息吗？你奶奶瘫痪在床，每次给她翻身，她都拉着我的手问你考了多少分……”\n“妈妈！”小雅扑进林慧怀里，小手在她脸上胡乱抹着，眼泪啪嗒啪嗒掉在她手背上，“对不起，我错了，你别哭了。”\n林慧抓住女儿的手，那双手纤巧白嫩，右手中指上却结着长期握笔磨出的薄茧。她深吸一口气，声音哑得像被砂纸磨过：“你说，你错在哪儿了？”\n小雅的嘴唇抿了又抿，睫毛上挂着泪珠，声音细得像蚊子哼：“我不该……不该故意把那道题做错。”\n“你说啥，故意？”林慧猛地松开手，指尖冰凉。她看着女儿低垂的眉眼，蓦地想起上周六带小雅去逛商场，橱窗里那个穿着粉色纱裙的布娃娃，标价是她两天的工资。当时小雅趴在玻璃橱窗上艳羡了好久，而后轻声说：“妈妈，这个娃娃笑起来像你”。\n“你以前说，”小雅的眼泪掉得更凶了，肩膀一抽一抽的，“说我考了满分，就给我买那个布娃娃。可是……可是它要两百六十八，够奶奶半个月的药钱了。”\n林慧的喉咙倏然像被什么东西堵住了，发不出一点声音。她蹲下身，一把将女儿搂进怀里。\n“傻孩子，”她的眼泪砸在女儿的头发上，热得烫人，“妈妈有钱，妈妈这就带你去买。”\n“不要，”小雅在她怀里摇摇头，小手紧紧搂着她的脖子，“我不要娃娃了，妈妈，我以后再也不粗心了，我要考好多好多满分，给你买大房子，给奶奶请最好的医生。”\n厨房里的番茄炒蛋还冒着热气，混着母女俩的抽泣声，竟生出些许微甜的暖意。林慧摸着女儿后背，那里的骨头硌得她手疼，可她确信，这副稚嫩的肩膀，将来定能扛起比布娃娃更重的东西。\n窗外的路灯亮了，透过窗户照射进来，在地上投下两道依偎的影子，像株刚抽出新芽的藤，紧紧缠绕着，一个劲往高处生长。\n原文发表于《西安日报》2025年11月20日第08版西岳。\n原文链接：西安日报电子版 ","permalink":"https://june6699.github.io/posts/%E4%B8%8D%E8%80%83%E6%BB%A1%E5%88%86/","summary":"\u003cp\u003e防盗门锁芯被钥匙拧转时，林慧正在厨房里颠勺。葱花爆香的气息刚漫出来，就被一阵风风火火的脚步声撞得七零八落。\u003c/p\u003e\n\u003cp\u003e“妈妈，妈妈！”女儿小雅的声音像颗甜脆的山楂，猝然滚进油烟缭绕的厨房，“你看这个！”林慧顿了顿，伸手去关火，锅里的热气熏得她鼻尖白亮。她扭过身，瞥见小雅举着张试卷在眼前直晃，羊角辫随着蹦跳的节律扫过她的胳膊，透出刚从外面跑回来的寒气。“慢点，当心烫着。”林慧将手在围裙上胡乱擦了擦，接过了试卷。指腹触到试卷边缘的褶皱时，她暗忖，那是被孩子攥了一路的痕迹。鲜红的97分突兀在卷首，格外醒目，像朵饱满的石榴花。\u003c/p\u003e","tags":["生活","生活/文章"],"title":"不考满分"},{"content":"陆游与唐婉的故事，后世已经讲得太熟。熟到什么地步？熟到一说起沈园，很多人脑子里立刻就是一对被礼法拆开的才子佳人，一堵题词的粉墙，一场春日重逢，一辈子散不掉的相思。\n这样的讲法当然好听，也确实动人，但它真正抓人的地方，其实并不只在那一次相遇，而在于相遇之后的几十年。陆游不是写完一首《钗头凤》就算了，他是在中年、晚年、梦里、暮年重游时，一次次回到那个地方。于是沈园就不再只是一个故事发生的地点，而成了他此后四十多年里反复疼起来的一块旧伤。\n这一篇不打算只把陆游与唐婉写成“千古爱情模板”，也不想把他们写成纯粹的礼教标签。更想做的，是把那条线慢慢展开：从婚姻被迫拆散，到沈园偶遇，再到《钗头凤》之后的回声、菊枕旧梦、重游沈园与梦游沈园，看看这段旧事是怎样在陆游的一生里，越到晚年越压得深。\n一、故事的开头：不是只有“沈园重逢”，前面先有一场被拆开的婚姻 后世多据《齐东野语》与诸家笔记，来勾勒陆游与唐氏的故事轮廓：陆游初娶唐氏，夫妻情意甚笃，却终究不获于姑，后来被迫分开；唐氏再嫁赵士程，陆游则另娶王氏。再往后，才有绍兴乙亥年那场著名的沈园相遇。\n这段故事之所以越传越广，其实并不难理解。它几乎把中国旧式爱情叙事最抓人的东西全占了：年轻时相爱，被家庭与礼法拆开，女方再嫁，男方另婚，许多年后又在旧园中相逢。这样的骨架，本来就很适合长成传奇。\n可真正让它和一般传奇不同的，是后来那些诗。若没有《钗头凤》，这件事未必会如此深入人心；若没有《沈园》诸诗，它又未必能活四十年。换句话说，故事之所以留下来，不只是因为“发生过”，而是因为陆游一直在写。\n二、绍兴乙亥（1155）｜沈园相逢：《钗头凤》把一场重逢压成六十字 按周密《齐东野语》的说法，绍兴乙亥春日，陆游到禹迹寺南沈园游赏，恰与唐氏、赵士程相遇。赵士程命人送酒肴致意，陆游感怅之下，题《钗头凤》于壁。\n于是便有了最有名的这一阕：\n红酥手，黄縢酒，满城春色宫墙柳。\n东风恶，欢情薄，一怀愁绪，几年离索。\n错，错，错！\n春如旧，人空瘦，泪痕红浥鲛绡透。\n桃花落，闲池阁，山盟虽在，锦书难托。\n莫，莫，莫！\n宋·陆游《钗头凤》\n曾经那双柔软的手，还斟过黄縢酒；满城春色里，她却像宫墙边的柳，已隔在别处。东风无情，旧日欢情日渐单薄，只剩下几年离散后的满怀愁绪。春光依旧，人却消瘦，泪痕湿透了手帕。山盟虽然还在，却连一封书信也无法寄托，只能一声声说“错”与“莫”。\n《钗头凤》最妙的地方，是它明明有最好的“写艳”起手，“红酥手，黄縢酒，满城春色宫墙柳”，但最后压住人的，并不是春色，而是“山盟虽在，锦书难托”。山盟还在，却已经没有路了；记忆还在，却已经没有办法。真正让人喘不过气的，从来不是还爱，而是知道这份旧情此后再也没有落点。\n三个“错”，三个“莫”，更是这阕词最重的声音。它不是判案，不是分谁对谁错，而像是人站在旧日与如今中间，已经说不清该怪谁、该怨谁，只能把那种来不及追回的痛，一层一层压成字。\n三、唐婉的回声：后世最不肯放过的，是她那首《钗头凤》 这段故事之所以后来越讲越足，还有一个极重要的原因，就是传世本里那首归于唐婉的和词《钗头凤》。\n后人熟得不能再熟的，正是这一首：\n世情薄，人情恶，雨送黄昏花易落。\n晓风干，泪痕残，欲笺心事，独语斜阑。\n难，难，难！\n人成各，今非昨，病魂常似秋千索。\n角声寒，夜阑珊，怕人寻问，咽泪装欢。\n瞒，瞒，瞒！\n宋·唐婉（传世本）《钗头凤》\n世情薄凉，人心也多狠，黄昏细雨里，花更容易落。晨风吹干了泪痕，想写下心事，却只能独自倚栏低语。如今人已各自分开，一切都不是昨日了，病中的心魂仿佛秋千绳索一般摇摇欲坠。角声凄寒，夜色将尽，还怕别人追问，只能含泪强作欢颜，一切都只好瞒着。\n正因为有了这首和词，沈园故事才彻底从陆游一个人的旧事，变成两个人的相互映照。陆游是“错，错，错”“莫，莫，莫”，唐婉则成了“难，难，难”“瞒，瞒，瞒”。一个偏向追悔，一个偏向难言；一个是旧约无从寄托，一个是心事只能斜阑独语。\n也正因为这首词太会写，后世才越来越不甘心只把他们写成一场被拆散的婚姻，而更愿意把他们写成一对被时代、家族和礼法共同拖住的人。很多人后来记沈园，记住的甚至不只是陆游，而是这两阕词如何隔着一堵墙、一座园子、一段人生互相呼应。\n四、菊枕旧梦：真正漫长的，不是那一次重逢，而是重逢以后还不断想起 如果说《钗头凤》写的是骤然撞上的旧痛，那么多年后的《菊枕》诗，则更像一种慢慢返上来的旧梦。\n陆游晚年在题注里自己写得明白：二十岁时曾作菊枕诗，后来偶然又采菊缝枕囊，忽然想起旧事，于是有感。传世的《菊枕》二首里，最伤人的恰恰是“无人说断肠”与“只有清香似旧时”：\n采得黄花作枕囊，曲屏深幌闷幽香。\n唤回四十三年梦，灯暗无人说断肠。\n宋·陆游《菊枕》其一\n采来黄菊做成枕囊，曲屏深帐里满是幽香。这香气一下唤回了四十三年前的旧梦，可灯火昏暗，身边却已经没有一个可以说断肠的人。\n少日曾题菊枕诗，囊编残稿锁蛛丝。\n人间万事消磨尽，只有清香似旧时。\n宋·陆游《菊枕》其二\n年轻时曾给菊枕题过诗，如今枕囊和残稿都已经积尘结网。人间万事几乎都被岁月消磨尽了，偏偏这点菊花清香，还像当年一样把旧事整个带回来。\n这里最压人的，不是“梦”，而是“唤回”。也就是说，那段旧情本来并没有时时挂在嘴边，可一点气味、一件旧物，就足以把几十年前的人和事整块唤回来。到了这一步，唐婉对陆游而言，已经不只是一个具体的人，而像是岁月里某个再也回不去、却又总能被某种细节勾起的时刻。\n五、四十年后再到沈园：园子还在，人却早已被时间改得认不出来 真正让这段故事从“相思旧事”变成“晚年伤心史”的，是陆游后来一次次再到沈园。\n绍熙壬子，他重到沈园，自题里说“四十年前尝题小阕壁间，偶复一到，而园已易主”，于是写《禹迹寺南有沈氏小园》：\n枫叶初丹槲叶黄，河阳愁鬓怯新霜。\n林亭感旧空回首，泉路凭谁说断肠。\n坏壁旧题尘漠漠，断云幽梦事茫茫。\n年来妄念消除尽，回向禅龛一炷香。\n宋·陆游《禹迹寺南有沈氏小园》\n枫叶初红，槲叶已黄，我也像潘岳那样鬓发愁白，畏惧新霜。到了旧园，只能空自回首；人已在泉下，又能对谁诉说断肠？坏墙上的旧题早已蒙尘，幽梦像断云一样茫茫难寻。到了这些年，妄念似乎都已消尽，所能做的，不过是在佛龛前点上一炷香。\n这首诗里“坏壁旧题尘漠漠”一句，几乎已经把沈园的意义说完。题词还在，墙也还在，可一切都被时间磨旧了。人来重看，不是为了找回当年，而是为了确认：当年确实存在过，如今却真的再也回不去了。\n到了庆元己未，《沈园》二首更是把这种感觉压成几乎人人都会背的两联：\n城上斜阳画角哀，沈园非复旧池台。\n伤心桥下春波绿，曾是惊鸿照影来。\n宋·陆游《沈园》其一\n城头斜阳里，画角声凄哀，沈园早已不是旧时池台模样。只有伤心桥下春水仍绿，仿佛还记得当年曾映照过她如惊鸿般的身影。\n梦断香消四十年，沈园柳老不吹绵。\n此身行作稽山土，犹吊遗踪一泫然。\n宋·陆游《沈园》其二\n旧梦断绝、香魂消散，已经过去四十年，连沈园的柳树都老到不再飞绵。我自己也快要化作稽山之土了，可来到这里凭吊旧踪，仍然不免落泪。\n“伤心桥下春波绿，曾是惊鸿照影来”当然最有名，但我总觉得“沈园非复旧池台”“沈园柳老不吹绵”更狠。因为它们写的不是“人依旧”，而恰恰是“连园子都老了”。一个人若只是偶尔回忆旧情，那还是感伤；可如果连景物都在提醒你时间已经过去太久，那就不只是感伤，而是晚年真正的无可奈何。\n六、梦里再去，八十之后还不肯散：沈园最后成了陆游晚年的梦境 到了开禧乙丑，陆游八十有一，还在写《十二月二日夜梦游沈氏园亭》：\n路近城南已怕行，沈家园里更伤情。\n香穿客袖梅花在，绿蘸寺桥春水生。\n宋·陆游《十二月二日夜梦游沈氏园亭》其一\n离城南越近，我越怕走那条路；一到沈家园里，伤情就更深。梅花的香气仍会穿过衣袖，寺桥边春水依旧碧绿，好像旧景从未真正离去。\n城南小陌又逢春，只见梅花不见人。\n玉骨久成泉下土，墨痕犹锁壁间尘。\n宋·陆游《十二月二日夜梦游沈氏园亭》其二\n城南的小路又逢春天，可如今只见梅花，不见故人。她早已化作泉下之土，只剩下墙上的旧日墨痕，还被尘土锁在那儿。\n“路近城南已怕行”五个字，真是老年人的重话。年轻时还能相逢，中年时还能重游，到老了，连走近那条路都先怕起来。怕的不是记不清，而恰恰是太清楚。\n再往后还有《春游》：\n沈家园里花如锦，半是当年识放翁。\n也信美人终作土，不堪幽梦太匆匆。\n宋·陆游《春游》\n沈家园里繁花似锦，好像有一半都还是当年见过我的旧相识。我也知道美人终究会化作尘土，可还是受不了那场幽梦竟散得这样匆匆。\n这就已经不是单纯的凭吊，而几乎是一个老人在人生最后还在承认：我知道她早已不在，也知道万物终归成土，可我还是放不下。\n七、陆游当然不只剩唐婉，可也正因为如此，沈园才更重 写到这里，也得替陆游留一点完整。因为如果只把他写成一个终生困在沈园里的痴情人，也是在把他写窄。\n写《钗头凤》《沈园》的陆游，也是写《书愤》《示儿》的陆游；他有恢复中原的抱负，有长期的仕途进退，有对家国和时局的大痛。也正因为如此，沈园诗才更显得重。不是一个人一辈子别无所事，只会抱着一段旧情不放，而是一个本来有那么多别的事要写、要愁、要恨、要记的人，到老了，仍会被这一处地方牵住。\n所以沈园真正厉害的，也许并不只是“爱情”。它更像一块记忆的硬结。人活得越久，越知道世界上总有一些地方，明明早就回不去了，却偏偏绕不开。\n唐婉也因此并不只是“陆游的一段旧情”。在这些诗里，她更像陆游一生里那块一直没有真正愈合的部分。少年时是欢情，中年时是旧恨，老年时则成了桥下春波、柳不吹绵、梅花还在而故人不在的梦。\n参考 周密《齐东野语》卷一 陆游《钗头凤》 唐婉《钗头凤》 陆游《菊枕》相关题记与诗 陆游《禹迹寺南有沈氏小园》所在页 陆游《沈园》所在页 陆游《十二月二日夜梦游沈氏园亭》所在页 陆游《春游》所在页 ","permalink":"https://june6699.github.io/posts/%E6%B2%88%E5%9B%AD%E9%81%97%E6%A2%A6%E9%99%86%E6%B8%B8%E4%B8%8E%E5%94%90%E5%A9%89%E7%9A%84%E4%B8%80%E7%94%9F%E7%9B%B8%E6%80%9D/","summary":"\u003cp\u003e陆游与唐婉的故事，后世已经讲得太熟。熟到什么地步？熟到一说起沈园，很多人脑子里立刻就是一对被礼法拆开的才子佳人，一堵题词的粉墙，一场春日重逢，一辈子散不掉的相思。\u003c/p\u003e","tags":["诗","诗/人物"],"title":"沈园遗梦・陆游与唐婉的一生相思"},{"content":"把《江雪》只读成“史上最孤独的一首诗”，当然不算错；但如果只盯着那只孤舟，就会漏掉岸上的另一个人：刘禹锡。\n柳宗元的“孤”，不是凭空落下来的。它前面有同年登第、同入革新与十年南谪，里面夹着父丧、亡妻、母逝、女夭、骨肉分散；它后面还有衡阳分路、柳州北望，以及病中留书托付遗孤。刘禹锡后来在《祭柳员外文》里写：“初托遗嗣，知其不孤。”这八个字，几乎把“刘柳”二人的后半生全说完了。\n所以这篇不再只写柳宗元个人的离散，而想把刘禹锡这条线一并拉进来：用柳宗元的诗做骨架，用正史、墓志、祭文与书信做血肉，看那只“独钓寒江雪”的孤舟，究竟是怎样一步步漂到柳州去的。\n下面仍按编年写；凡诗作不能确系某年者，只系其大致时期，不强作断语。\n一、先从结尾看：所谓“托孤”，到底托的是什么 元和十四年（819）秋冬之际，柳宗元卒于柳州。刘禹锡后来祭他说，自己在“途次衡阳”接到柳使，本以为只是再通消息，不料“忽承讣书”，又“伸纸穷竟，得君遗书”。遗书里最重的，并不是一句空泛哀叹，而是实实在在的托付：遗嗣、归葬、后事。\n刘禹锡紧接着写“初托遗嗣，知其不孤”“誓使周六，同于己子”。这已经不是悼亡文字里的寻常客套，而是明确接下照看朋友遗孤的责任。刘禹锡《柳河东集序》又说，柳宗元病重时“留书抵其友中山刘禹锡曰：‘我不幸卒以谪死，以遗草累故人。’禹锡执书以泣，遂编次为四十五通行于世。”也就是说，柳宗元临终托给刘禹锡的，不只是孩子，还有自己的文稿与身后声名。\n把这一层放到最前面，再回头读《江雪》，那种“孤”就复杂了：他当然孤，但不是无人知他；他当然被放逐，但并非被所有人遗弃。刘禹锡正是那条寒江另一岸还在回应的人。\n二、以诗为轴的刘柳编年（793—819） 1. 贞元九年（793）｜同年登第：刘柳不是贬后才相知 刘禹锡本传明记，他在贞元九年“擢进士第”；而刘禹锡后来为柳宗元作《柳河东集序》时，也追述柳宗元“至九年为名进士”。这说明“刘柳并称”并不是后人为了省事硬拢出来的文学标签，两人从青年时代起，就已经站在同一代文士的中心位置上。\n后来衡阳分路时，刘禹锡回赠柳宗元，有“弱冠同怀长者忧，临岐回想尽悠悠”之句。这句回望很重要：他们的友谊不是贬所里的临时抱团，而是从弱冠时代一路走到理想破碎、两鬓将白之后，仍然彼此记得对方最初的样子。\n2. 贞元十五年（799）｜亡妻杨氏：政治挫败之前，家门已经先冷下来 柳宗元写《亡妻弘农杨氏志》，自记妻子“未三岁，孕而不育，厥疾增甚”，终于贞元十五年去世，年仅二十三。很多人写柳宗元，总喜欢从永贞革新失败才开始讲他的“不幸”；但对柳宗元本人来说，生命里“留不住人”的经验，早在南贬之前就开始了。\n这一层很要紧。因为《江雪》的冷，不只来自政治失路，也来自他过早熟悉的私人丧痛。若把这一层全删掉，柳宗元就容易被读成一个纯粹的“清冷诗人”，而忘了他先是一个不断失去家人的人。\n3. 永贞元年（805）｜同入革新：他们一度真相信天下可为 顺宗即位后，刘禹锡与柳宗元都进入王叔文集团。《旧唐书》刘禹锡传说“引禹锡及柳宗元入禁中，与之图议，言无不从”；柳宗元传则说“与监察吕温密引禁中，与之图事”。两条传记合起来看，正能见出刘柳在革新中的并进关系。\n后来人常把他们只写成“失败者”，可在805年那一小段时间里，他们并不只是失败者，而是真心想过如何改造时政的人。也正因此，革新一败，打击才会那样深。刘禹锡被贬朗州司马，柳宗元则在赴邵州途中再贬永州司马。“二王、刘、柳”从朝堂上的锐气人物，一下变成南方瘴雨里的流人。\n4. 元和元年至五年（806—810）｜永州：《江雪》与《渔翁》之间，既有山水，也有丧亡 柳宗元到永州不久，母亲卢氏卒于零陵佛寺。《先太夫人河东县太君归祔志》直书：“元和元年，岁次丙戌，五月十五日，弃代于永州零陵佛寺。”四年后，幼女和娘又死于永州，《下殇女子墓砖记》记得更简短，也更刺人：“元和五年四月三日，死永州，凡十岁。”所以永州绝不只是“山水成全柳宗元”的文学福地，它首先是流地、病地，也是丧地。\n大致在永州前期，我们今天多把《江雪》系在这一段人生里：\n千山鸟飞绝，万径人踪灭。\n孤舟蓑笠翁，独钓寒江雪。\n唐·柳宗元《江雪》\n群山里再也看不见飞鸟，条条小路上也断绝了人迹。只有江中一叶孤舟，一个披着蓑衣、戴着斗笠的老翁，在漫天寒雪里独自垂钓。\n若只看诗面，《江雪》是天地空净；可一旦放回柳宗元的处境里，它更像被删到只剩最后一个人的世界。鸟绝、人灭、孤舟、独钓，一层层都在做减法：减去同道，减去前途，减去热闹，最后连家门也被现实抽空。\n但柳宗元并不总把自己写成冰点以下的那个人。永州中期的《渔翁》又把世界写亮了一次：\n渔翁夜傍西岩宿，晓汲清湘燃楚竹。\n烟销日出不见人，欸乃一声山水绿。\n回看天际下中流，岩上无心云相逐。\n唐·柳宗元《渔翁》\n渔翁夜里把船泊在西岩旁，清晨汲取湘水、燃起楚竹。等到烟消日出，人影忽然不见，只听橹声一响，满山满水都亮成了绿色。回头再看，他已顺流而下，只剩岩上的白云自来自去。\n《江雪》是把人逼到极静，《渔翁》则像在极静里重新听见一点活气。只是这点亮色并不等于痊愈。烟销日出之后，依旧是“不见人”。柳宗元从山水里得到过喘息，却没有真正脱身。\n5. 永州后段（年未详）｜和刘禹锡隔江论“天”：孤舟上并不只有沉默 如果只说刘禹锡是柳宗元患难中的朋友，还不够；更准确地说，他还是柳宗元在流放岁月里的思想对手与写作同伴。柳宗元《答刘禹锡天论书》一开头就说：“发书得《天论》三篇，大喜。”这种“大喜”不是修辞上的寒暄，而是一个被困南州的人忽然等到了真正能接话的人。\n这很能改变我们对柳宗元“孤绝”的想象。《江雪》里的孤，不是无人世界里的真空之孤，而是现实上被放逐、精神上仍不肯熄火的孤。哪怕隔着永州与朗州的山川瘴雨，刘禹锡仍然是那个能和他争论天人、彼此砥砺的人。\n6. 元和十年至十一年（815—816）｜北归成空：刘禹锡“桃花诗”之后，柳宗元想替他去播州 元和十年前后，刘禹锡和柳宗元一度都等到了“北归”的消息，以为十年南谪终于熬到头。可事情几乎立刻反转。这里顺手要说明一下纪年：刘禹锡本传记“元和十年”自武陵召还，而今传诗题作《元和十一年自朗州召至京，戏赠看花诸君子》，史传与诗题相差一年。无论按哪一条记法，大势都一样：北归未久，刘禹锡就因诗得祸，再度南出。\n那首惹祸的诗，如今最常被记住的是后两句：“玄都观里桃千树，尽是刘郎去后栽。”《旧唐书》说得很直：此诗“语涉讥刺，执政不悦，复出为播州刺史”。\n播州之命一下，柳宗元的反应，在正史和墓志里都被重重记了一笔。《旧唐书》说他对亲友道：“禹锡有母年高……如母子异方，便为永诀。”韩愈《柳子厚墓志铭》记得更动人：“愿以柳易播，虽重得罪，死不恨。”柳州换播州，这不是文学夸饰，而是柳宗元真的想替刘禹锡去更险绝的地方。\n当然，最后让刘禹锡改授连州的不止柳宗元一人，裴度也曾上奏；但正因为《旧唐书》和韩愈墓志两边都记了柳宗元这一举动，才更能看出这不是传闻里的“义气故事”，而是当时人共同认定的一件大事。\n7. 元和十年（815）｜衡阳分路：《重别梦得》不是“友情小诗”，而是一组诀别 从京城再出南方，刘柳同行至衡阳分路。柳宗元不只写了一首《重别梦得》，还写了《衡阳与梦得分路赠别》《三赠刘员外》等；刘禹锡也有《再授连州至衡阳酬柳柳州赠别》《重答柳柳州》。换句话说，衡阳不是“临别一句话”，而是一整组来回唱和。\n先看柳宗元最有名的一首：\n二十年来万事同，今朝岐路忽西东。\n皇恩若许归田去，晚岁当为邻舍翁。\n唐·柳宗元《重别梦得》\n二十年来，我们一同经历了许多事，如今却在岔路口骤然东西分手。若将来还能蒙恩归田，到晚年时，真想与你做相邻而居的老人。\n这四句看似平淡，其实压得很重。“二十年来万事同”把他们从贞元九年一路并到此刻；“今朝岐路忽西东”则把一切理想又打散一次。更难过的是，这不是普通朋友各奔前程，而是一个刚刚想替对方去播州的人，最后仍只能在衡阳看着对方往别处走。\n刘禹锡回赠的《再授连州至衡阳酬柳柳州赠别》首联也写得极直白：“去国十年同赴召，渡湘千里又分岐。”如果说《重别梦得》写的是含忍，那么刘禹锡这两句几乎是在把“同赴召”与“又分歧”的荒凉当面说破。\n8. 元和十年（815）｜柳州城楼：人在南荒，眼睛仍在找刘禹锡 到柳州后不久，柳宗元写下《登柳州城楼寄漳汀封连四州》。题目里的“连州”就是刘禹锡；其馀韩泰、韩晔、陈谏，也都是与他同遭贬逐的旧人。于是这首诗不是泛泛望远，而是写一个人如何在一座更远的城楼上，把分散在漳、汀、封、连诸州的故人都望了一遍。\n城上高楼接大荒，海天愁思正茫茫。\n惊风乱飐芙蓉水，密雨斜侵薜荔墙。\n岭树重遮千里目，江流曲似九回肠。\n共来百越文身地，犹自音书滞一乡。\n唐·柳宗元《登柳州城楼寄漳汀封连四州》\n我登上柳州城楼，只见荒远天地与愁思一样无边。狂风吹乱水上的芙蓉，密雨斜打满墙的薜荔。重重岭树遮断了千里远望，曲折江流像百转愁肠。大家同来南荒之地，却仍各困一州，连书信也常被阻滞。\n“共来百越文身地，犹自音书滞一乡”最能见出这批人的处境：不是只有柳宗元一个人在受苦，而是一群被时代打散的人，各自困在州郡之间，连互通书信都艰难。换句话说，《江雪》里的“独”，到柳州时已经扩大成一代人的共同孤寒。\n9. 元和十一年至十二年（816—817）｜柳州后期：骨肉零落，望乡至极 柳宗元到柳州后，并没有因为做了刺史就从悲苦里走出来。送别宗一时，他写《别舍弟宗一》。今本首句多作“零落残魂倍黯然”，《全唐诗》系统又见“残红”异文，但无论哪一种，都写的是人已被摧折到只剩残余：\n零落残魂倍黯然，双垂别泪越江边。\n一身去国六千里，万死投荒十二年。\n桂岭瘴来云似墨，洞庭春尽水如天。\n欲知此后相思梦，长在荆门郢树烟。\n唐·柳宗元《别舍弟宗一》\n我这早已零落的心魂，因为与你分别更加黯然。我们在越江边一同垂泪。我离开京城已六千里，投荒南土也有十二年了。桂岭瘴云浓黑如墨，你将去的洞庭一带却正是春尽水阔。若问此后相思会落在何处，大概总在荆门郢树的烟水之间。\n这里的“万死投荒十二年”，已经把他从805到816的流放生涯自己算了一遍。它不是单写兄弟离别，而是把十二年的政治打击、家门零落和骨肉分散，一起压进一首诗里。\n再晚一些，他与浩初上人同看山，又写《与浩初上人同看山寄京华亲故》：\n海畔尖山似剑铓，秋来处处割愁肠。\n若为化得身千亿，散上峰头望故乡。\n唐·柳宗元《与浩初上人同看山寄京华亲故》\n海边一座座尖山像锋利剑刃，秋天一到，处处都像在割人的愁肠。若能把自己化作千万个分身，我愿散上每一处峰头，一齐朝着故乡张望。\n到这一步，柳宗元连“回去”都不再敢说，只说把自己化成无数个分身，分散到峰头上朝北张望。能写到这种地步，说明他的望乡已经不是路远，而是近乎无路。\n10. 元和十四年（819）｜临终留书：刘禹锡成了遗稿的编者、遗孤的监护人与故人的执行者 韩愈在《柳子厚墓志铭》里记，柳宗元死时“子男二人：长曰周六，始四岁；季曰周七，子厚卒乃生。女子二人，皆幼。”这就解释了为什么临终托付会那样沉重：他留下的不是已经成人的家属，而是一家几乎全无自立能力的小儿女。\n于是刘禹锡祭文里那句“誓使周六，同于己子”，分量就格外实在。它不是抽象的“我会替你照顾家里”，而是明确把朋友的孩子纳入自己的责任范围。再结合祭文中对归祔先域之事的交代，可以看出柳宗元病中交付刘禹锡的，至少有三件事：孩子、归葬、文稿。\n刘禹锡后来把这些事一一接住。他不只哭，也不只写祭文；他还为柳宗元编集作序，使柳宗元的身后文名不至散失。某种意义上，《江雪》那只孤舟最后没有彻底沉没，正因为岸上一直还有刘禹锡。\n三、把《江雪》放回刘柳故事里 这样回看，《江雪》就不再只是“一个人很孤独”的图解，而是刘柳这一代人共同命运被压缩后的单人镜头。镜头里只剩柳宗元，是因为诗要写极静；但镜头外并不是没人，而是有同年登第的刘禹锡，有替他冒险的柳宗元，有为他编集、替他收孤的刘禹锡，也有那些一起“共来百越文身地”的故人。\n所以柳宗元的“独”，并不是无人之独，而是明知天地冷寂、亲朋零落、归路断绝，还不肯把自己全交给风雪的独。也正因如此，《江雪》后面才应当接着读《重别梦得》、读《登柳州城楼寄漳汀封连四州》，最后读到《祭柳员外文》。不读到“托孤”这一步，我们就还没有真正读完柳宗元，也没有读完刘禹锡。\n四、编年简表 贞元九年（793）：刘禹锡、柳宗元同年登进士第。 贞元十五年（799）：柳宗元妻杨氏去世，柳宗元作《亡妻弘农杨氏志》。 永贞元年（805）：刘禹锡、柳宗元同入王叔文集团；革新失败后，刘禹锡贬朗州司马，柳宗元贬永州司马。 元和元年（806）：柳宗元母卢氏卒于永州。 永州前中期：柳宗元作《江雪》《渔翁》，山水书写与谪居心境同时成形。 元和五年（810）：柳宗元幼女和娘卒于永州，见《下殇女子墓砖记》。 永州后段：柳宗元作《答刘禹锡天论书》，可见刘柳在南谪中仍持续论学、论文。 元和十年至十一年前后（815—816）：刘禹锡北归未久又因《玄都观》诗得祸，改授播州；柳宗元请以柳州易播州，后刘禹锡改授连州。 元和十年（815）：刘柳同行至衡阳分路，柳宗元作《重别梦得》等诗，刘禹锡亦有酬答。 元和十年（815）：柳宗元到柳州后作《登柳州城楼寄漳汀封连四州》，诗中“连州”即刘禹锡。 元和十一年至十二年（816—817）：柳宗元作《别舍弟宗一》《与浩初上人同看山寄京华亲故》，孤寒与望乡之情愈重。 元和十四年（819）：柳宗元卒于柳州，病中留书托付遗嗣、归葬与遗稿于刘禹锡。 元和十五年（820）前后：刘禹锡作《祭柳员外文》《柳河东集序》，承担后事并编柳集行世。 五、参考来源 以下以前四类一手材料为主，辅以具体诗篇页面，便于继续追读：\n《旧唐书》卷160：刘禹锡、柳宗元传 韩愈《柳子厚墓志铭》 刘禹锡《祭柳员外文》 刘禹锡《柳河东集序》 柳宗元《答刘禹锡天论书》 柳宗元《亡妻宏农杨氏志》 柳宗元《先太夫人河东县太君归祔志》 柳宗元《下殇女子墓砖记》 柳宗元《江雪》 柳宗元《渔翁》 柳宗元《重别梦得》 柳宗元《登柳州城楼寄漳汀封连四州》 柳宗元《别舍弟宗一》 柳宗元《与浩初上人同看山寄京华亲故》 刘禹锡《元和十一年自朗州召至京，戏赠看花诸君子》 刘禹锡《再授连州至衡阳酬柳柳州赠别》 《新刊诂训唐柳先生文集》卷42：衡阳赠别与刘禹锡答诗诸篇 ","permalink":"https://june6699.github.io/posts/%E5%AF%92%E6%B1%9F%E5%AD%A4%E9%92%93%E6%9F%B3%E5%AE%97%E5%85%83%E4%B8%8E%E6%B1%9F%E9%9B%AA%E8%83%8C%E5%90%8E%E7%9A%84%E5%8D%81%E5%B9%B4%E7%A6%BB%E6%95%A3/","summary":"\u003cp\u003e把《江雪》只读成“史上最孤独的一首诗”，当然不算错；但如果只盯着那只孤舟，就会漏掉岸上的另一个人：刘禹锡。\u003c/p\u003e\n\u003cp\u003e柳宗元的“孤”，不是凭空落下来的。它前面有同年登第、同入革新与十年南谪，里面夹着父丧、亡妻、母逝、女夭、骨肉分散；它后面还有衡阳分路、柳州北望，以及病中留书托付遗孤。刘禹锡后来在《祭柳员外文》里写：“初托遗嗣，知其不孤。”这八个字，几乎把“刘柳”二人的后半生全说完了。\u003c/p\u003e","tags":["诗","诗/人物"],"title":"寒江孤钓之后：柳宗元、刘禹锡与一封托孤遗书"},{"content":"唐伯虎在后世有两个极端版本：一个是戏曲和电影里的风流才子，一个是短视频里“史上最惨”的模板人物。前者太轻，后者又常写得太满。真史里的唐寅，当然命途多舛，但并不是每一条流传甚广的细节都同样可靠。\n比如“父母、妻子、妹妹相继去世”“会试案后仕路断绝”“应宁王之聘又佯狂脱身”“晚年卖画而困”，这些大轮廓都有比较稳定的文献可据；但像“新生儿随妻子一同夭折”“第二任妻子卷走钱财”“当众裸奔撒尿才保命”之类说法，我这次没有找到和《明史》、祝允明《唐子畏墓志并铭》同等级的一手证据，所以宁可不写死。\n而《临终诗》真正动人的地方，也恰恰不在“惨”字本身。那四句诗之所以压得住人，是因为它后面站着苏州的繁华、家门的败落、解元的荣耀、诏狱的耻辱、桃花坞的自放，以及晚年一边卖画一边自嘲的几十年。下面仍按编年写，但不只盯着临终一首，而是借几首诗，把唐寅被反复误读的一生重新串起来。\n一、先看结尾：这首《临终诗》为什么会这样轻，又这样冷 后世最爱转引的，是唐寅临终前的四句：\n生在阳间有散场，死归地府也何妨。\n阳间地府俱相似，只当漂流在异乡。\n明·唐寅《临终诗》\n活在世上，总有散场的一日；死后归于冥冥，也没有什么可怕。若说阴间和阳间原也差不太多，那便只当又换了一个异乡去漂流。\n这首诗可怕之处，不在哭号，而在平。没有“痛定思痛”的铺陈，也没有慷慨激烈的身后语，反而像一个人把生死压成了家常话，轻轻说完。可正因为说得轻，背后那种“此生已经受够了”的凉意才更重。\n如果只把它当作“史上最惨绝笔诗”，很容易读窄。它其实不是一瞬间的崩塌，而是五十四年人生慢慢压出来的结果。\n二、吴中少年：唐伯虎并不是从“惨”开始的 唐寅，字伯虎，后更字子畏，苏州吴县人。祝允明在《唐子畏墓志并铭》里说他“性绝颖利”，幼时“有一日千里气”；《明史》也说他“性颖利”。他不是后世戏文里那种只会风流的纨绔，相反，是吴中一代文艺气象里最亮的一支。\n他写苏州繁华，有一首《阊门即事》，很能看出少年唐伯虎眼里的世界，并不阴沉：\n世间乐土是吴中，中有阊门更擅雄。\n翠袖三千楼上下，黄金百万水西东。\n五更市卖何曾绝，四远方言总不同。\n若使画师描作画，画师应道画难工。\n明·唐寅《阊门即事》\n若说天下乐土，当推吴中；吴中最繁华的，又要数阊门。楼上楼下尽是歌舞红袖，水西水东满是金粉豪华，天未亮市声已起，四方口音交杂。这样的盛景，就算让画师来画，怕也难画尽。\n这首诗很重要，因为它提醒我们：唐伯虎的一生不是一条单线向下的“受难史”。他知道什么叫好地方、好日子、好声色，也真切经历过吴门才子最意气风发的文化世界。正因如此，后来的跌落才更显得真。\n三、弘治七年至八年（1494—1495）｜家门骤冷：有些细节该谨慎，有些事实已经够重 唐寅的家变，是后世最爱渲染的一段。较稳的说法，其实已经足够沉重。故宫博物院对唐寅生平的概括是：“20余岁时家中连遭不幸，父母、妻子、妹妹相继去世，家境衰败。”祝允明墓志也清楚写到“父没”，并且可见他在父死之后一度仍“落落”，直到被祝允明劝去认真应举。\n这里要稍微停一下。短视频常把这一段讲成“短短一两年五位至亲连死、新生儿也夭折”，讲得极满，可一手材料能稳稳落下来的，主要还是父、妻、母、妹先后去世这条主线。至于徐氏究竟是否难产而亡、婴儿是否随之夭折，至少我这次没有看到和墓志同等级的明确文证，因此不妨存疑。\n但就算只取最稳的部分，也已经足够解释唐寅后来的底色。一个苏州才子，并不是先遭遇科场案才知道人生会翻脸，而是先在家门里，被迫学会“人说没就没”。\n四、弘治十一年至十二年（1498—1499）｜从“唐解元”到诏狱：人生最亮的一瞬，很快就反成最深的伤 祝允明墓志记得很清楚：唐寅听劝后闭门读书，弘治十一年戊午，应天府乡试“录为第一人”。这就是后来人人都叫的“唐解元”。\n《明史》对此也有简明记载：“举弘治十一年乡试第一。”这不是民间神话，而是正史可据的高光时刻。可第二年去北京会试，局势急转直下。祝允明墓志说，江阴富人徐经与唐寅同赴会试，后来因“言与主司有私，并连子畏”，于是“付诏狱”；《明史》则概括为“徐经贿其家僮，得试题。事露……语连寅，下诏狱，谪为吏”。\n这件事最难写的，是“唐寅究竟冤不冤”。今天很多文章会直接断为“完全无辜的天才被诬陷”，但从现存史料看，最稳妥的说法仍是：唐寅卷入程敏政会试案，被逮下狱，最终“谪为吏”，而他以此为奇耻大辱，终身不就。至于案中细节，已经很难百分之百还原。\n他后来回看这一段，自己也没有装成云淡风轻。看《漫兴》其二：\n此生甘分老吴阊，万卷图书一草堂。\n秋榜才名标第一，春风弦管醉千场。\n跏趺说法蒲团软，鞋袜寻芳杏酪香。\n只此便为吾事了，孔明何必起南阳。\n明·唐寅《漫兴》其二\n这一生本也甘愿老在苏州，有书有屋便足够。秋闱时名字高高挂在第一，得意时春风里纵酒听歌，不知有过多少场。往后若只是参禅、寻芳、读书、饮酒，也未尝不是一生，何必一定学诸葛亮再去出山。\n“秋榜才名标第一”六字，轻轻一提，分量却很重。因为它后面紧接着的，并不是仕途展开，而是整条路被当场掐断。\n五、桃花庵不是“躺平圣地”：它更像仕途断裂后的自我安置 《明史》说唐寅“归家益放浪”，又记他在桃花坞筑室，与客饮酒其间。后世最熟的唐伯虎，也就是从这里开始成形：花、酒、画、美人、狂态、才子名声，全都缠在一起。\n但《桃花庵歌》如果细读，并不是没心没肺的快活词，反而像一个受过重创的人，拼命替自己找一种还能活下去的姿势：\n桃花坞里桃花庵，桃花庵里桃花仙。\n桃花仙人种桃树，又折花枝当酒钱。\n酒醒只在花前坐，酒醉还须花下眠。\n花前花后日复日，酒醉酒醒年复年。\n不愿鞠躬车马前，但愿老死花酒间。\n车尘马足贵者趣，酒盏花枝贫者缘。\n若将富贵比贫贱，一在平地一在天。\n若将贫贱比车马，他得驱驰我得闲。\n世人笑我太疯癫，我笑世人看不穿。\n不见五陵豪杰墓，无酒无花锄作田。\n明·唐寅《桃花庵歌》\n桃花坞里有桃花庵，庵里仿佛住着桃花仙。他种桃树，也折桃花换酒钱；清醒时在花前坐着，醉了便在花下睡去。日子就在花前花后、酒醒酒醉之间一天天过去。他不愿去权贵车马前低头，只愿老死在花和酒之间。世人笑他疯癫，他反笑世人看不透；再大的豪杰，死后也不过是一抔黄土。\n很多人只记得“别人笑我太疯癫，我笑他人看不穿”，于是以为这就是彻底想开了。其实通篇读下来，更像一种带伤的硬撑。前程既已断绝，那就反过来说“我本来也不愿鞠躬车马前”；被世人笑作疯癫，那就索性先把“疯癫”拿来做面具。它不是赢家的潇洒，而更像败后自保的语言。\n六、卖画、自嘲与贫困：唐伯虎确实穷过，但也不是只剩一张惨相 会试案后，唐寅仕路基本断绝，卖画成了他后半生的重要生计。这个判断并非后人脑补，故宫的生平词条也明说“此后遂绝意进取，以卖画为生”。而他自己写《言志》，更是把这件事说得非常直白：\n不炼金丹不坐禅，\n不为商贾不耕田。\n闲来写就青山卖，\n不使人间造孽钱。\n明·唐寅《言志》\n我不炼丹，不参禅，也不经商、不种田；闲来画几笔青山卖钱，也总好过赚那些昧心的钱。\n这首诗有一种很硬的穷。不是“我虽卖画，仍是高士”的漂亮话，而是直接承认自己靠笔墨吃饭，同时又死死守住一点体面：钱可以赚，但不能赚得太脏。\n可体面之外，窘迫也是真的。《开门七件事》几乎短得发凉：\n柴米油盐酱醋茶，\n般般都在别人家。\n岁暮天寒无一事，\n竹时寺里看梅花。\n明·唐寅《开门七件事》\n日子要过，总离不开柴米油盐酱醋茶，可这些好像都在别人家里。到了年关天寒，自己无事可做，也只好去寺里看看梅花罢了。\n这比任何“穷到揭不开锅”的煽情都更难受。因为它不靠夸张，只靠一句“般般都在别人家”。日常生活最琐碎、也最具体的难，忽然就全出来了。\n这里也顺手说一句：后世常讲唐寅“第二任妻子卷财而去”，但我目前看到的一手材料里，祝允明墓志只说“配徐，继沈”，并没有把这件事写实到那个程度。所以比起添枝加叶地写八卦，我更愿意让《开门七件事》自己说话。它已经够真了。\n七、正德九年（1514）｜宁王一聘：他不是“风流误国”，而是差点被卷进更大的祸 唐寅后半生最险的一次，不在科场，而在宁王朱宸濠。正史对此说得很简练：《明史》载“宁王宸濠厚币聘之，寅察其有异志，佯狂使酒，露其丑秽。宸濠不能堪，放还。”故宫词条也沿用了这个说法，说他“赴南昌半年余，后察觉宁王有图谋不轨，遂佯狂得以脱身而归”。\n这段话里最关键的是四个字：佯狂得脱。也就是说，唐寅确实不是单纯去做幕僚，而是在发现局势不对之后，靠装疯、自污、使酒，才把自己从朱宸濠身边摘出来。\n这件事后来常被民间讲得极戏剧化，什么裸奔、撒尿、彻底发癫，一层层越讲越足。但回到正史，能确定的核心其实已经很惊险：他不是在演“风流才子”，而是在逃命。\n八、晚年诗里的“笑舞狂歌”，多半不是快活，而是自嘲 唐伯虎最容易被误读的，是他诗里那些看上去很潇洒的句子。比如《言怀》其一：\n笑舞狂歌五十年，花中行乐月中眠。\n漫劳海内传名字，谁论腰间缺酒钱。\n诗赋自惭称作者，众人多道我神仙。\n些须做得工夫处，莫损心头一寸天。\n明·唐寅《言怀》其一\n我笑着舞、狂着歌，已经这样过了五十年，赏花行乐，伴月而眠。世间都在传我的名字，可谁又会管我腰间是不是连买酒的钱都不够？诗文画艺我未必自负，别人却总把我说得像个神仙。真正要紧的，不过是守住心头那一寸不肯被磨损的天地。\n表面看，这还是那个“花中行乐”的唐伯虎；可“谁论腰间缺酒钱”一句，已经把穷窘和虚名的反差说穿了。海内传名又如何，腰间照样可能没钱。众人把他当神仙、当才子、当传奇人物，可他自己知道，传奇底下是很实在的人间窘迫。\n再看《一世歌》：\n人生七十古来稀，先除幼年后除老。\n中间光景不多时，又有闲愁与烦恼。\n过了中秋月不明，过了清明花不好。\n花前月下且高歌，急须满把金樽倒。\n明·唐寅《一世歌》（节录）\n人生原本就短，去掉少年和老年，中间真正可用的辰光没剩多少，还偏偏夹着种种烦恼。既然如此，不如趁着花前月下，还能喝酒高歌时，先痛痛快快喝一场。\n这就不是单纯享乐了，而是一个深知人生逼仄的人，在用酒和笑声顶住虚空。\n《一年歌》也一样。它不是写四季之美，而是在算：一年三百六十日，真正称得上良辰的，其实少得可怜。对唐寅来说，这种“及时行乐”并不来自天生轻薄，反而往往来自太知道什么叫不由人。\n九、嘉靖二年十二月二日（1524年1月7日左右）｜绝笔之前，先有一整条被误读的一生 祝允明墓志记唐寅“卒嘉靖癸未十二月二日，得年五十四”。换到公历，大致已是1524年1月上旬。这里也顺手说明一个常见的小混乱：很多资料写他“1523年卒”，那是按嘉靖二年这个年号纪年；若换到公历，已在1524年年初。\n所以《临终诗》并不是一个人忽然有感而发的漂亮句子，它后面至少叠着这些东西：吴中的少年盛景，20多岁时家门连丧，弘治十一年的解元高光，弘治十二年的诏狱与谪吏，桃花坞里的卖画自遣，宁王府里的险地求生，以及晚年“海内传名字”而“腰间缺酒钱”的反差。\n这样再回读：\n生在阳间有散场，死归地府也何妨。\n阳间地府俱相似，只当漂流在异乡。\n明·唐寅《临终诗》\n活在世上，总有散场的一日；死后归于冥冥，也没有什么可怕。若说阴间和阳间原也差不太多，那便只当又换了一个异乡去漂流。\n它就不再只是“惨”，而是冷。不是被一下子击垮，而是把人世的热闹、荣耀、嘲笑、穷困、风险、名声都过了一遍之后，终于连生死都不想再分得太清。\n十、余墨：真正被误读的，也许不是“风流”，而是他的苦和硬 后世最喜欢消费唐伯虎的两样东西，一个是风流，一个是悲惨。风流容易拍成戏，悲惨容易剪成短视频，可这两种讲法都容易漏掉他真正硬的地方。\n他不是只会笑，也不是只会惨。他会写“世人笑我太疯癫”，也会写“闲来写就青山卖，不使人间造孽钱”；会在穷里讲体面，会在险里靠佯狂脱身，会在虚名满城时承认自己“腰间缺酒钱”。所以唐伯虎最值得写的，其实不是一个“史上最惨才子”的人设，而是一个人在荣耀断掉之后，怎样一边自嘲，一边死撑着把日子过下去。\n《临终诗》只是最后一笔。若只记得这四句，还是会把唐寅读窄。\n参考来源 这次主要取较稳的一手和官方材料，诗作页面附在后面，便于继续追读：\n祝允明《唐子畏墓志并铭》 《明史》卷286《文苑二》：唐寅传附见徐祯卿条 故宫博物院：唐寅词条 唐寅《阊门即事》 唐寅《桃花庵歌》 唐寅《言志》 唐寅《开门七件事》 唐寅《言怀》 唐寅《漫兴》 唐寅《一世歌》 唐寅《一年歌》 唐寅《临终诗》 ","permalink":"https://june6699.github.io/posts/%E6%A1%83%E8%8A%B1%E5%BA%B5%E5%A4%96%E5%94%90%E4%BC%AF%E8%99%8E%E4%B8%8E%E4%B8%B4%E7%BB%88%E8%AF%97%E8%83%8C%E5%90%8E%E7%9A%84%E4%BA%94%E5%8D%81%E5%9B%9B%E5%B9%B4/","summary":"\u003cp\u003e唐伯虎在后世有两个极端版本：一个是戏曲和电影里的风流才子，一个是短视频里“史上最惨”的模板人物。前者太轻，后者又常写得太满。真史里的唐寅，当然命途多舛，但并不是每一条流传甚广的细节都同样可靠。\u003c/p\u003e","tags":["诗","诗/人物"],"title":"桃花庵外・唐伯虎与《临终诗》背后的五十四年"},{"content":"白居易当然不只会写《长恨歌》《琵琶行》。翻开他的集子，你会发现这位写天下、写宫怨、写民生的大诗人，碰到自己家里的小女儿、夭折的幼女、出嫁后的女儿和刚满月的外孙女时，笔下忽然会变得很轻，也很软。\n这种“轻”，并不等于不痛。相反，越是家常，越容易刺人。写阿罗时，他看见的是一个会学母亲画眉、学父亲咏诗的小女孩；写金銮子时，他写“故衣犹架上，残药尚头边”，几乎没有修辞，却把一个父亲最受不了的那一下写透了；等到老来再抱上谈氏外孙女孩，他又说“怀中有可抱，何必是男儿”，像是把半生里关于“女儿”这件事的爱与失，都轻轻放回怀里。\n后人常把这位谈氏外孙女孩称作“引珠”，这个名字流传很广；这篇也沿用这个叫法。与其把白居易只记成会写大题目的诗人，不如顺着阿罗、金銮子和引珠这条线，看看一个大诗人怎样在家门之内，留下另一种更安静、也更真切的心。\n一、罗儿：白居易还没失去之前，就已经是个很会疼女儿的父亲 白居易写小女儿阿罗，有一首《吾雏》，几乎一开口就把父亲的语气定住了：\n吾雏字阿罗，阿罗才七龄。\n嗟吾不才子，怜尔无弟兄。\n抚养虽骄騃，性识颇聪明。\n学母画眉样，效吾咏诗声。\n我齿今欲堕，汝齿昨始生。\n我头发尽落，汝顶髻初成。\n老幼不相待，父衰汝孩婴。\n缅想古人心，慈爱亦不轻。\n蔡邕念文姬，于公叹缇萦。\n敢求得汝力，但未忘父情。\n唐·白居易《吾雏》\n我的小女儿叫阿罗，今年才七岁。我自叹并非什么了不起的人，只是怜她没有兄弟。她虽然还带着孩子气，却已经很聪明，会学母亲画眉，也会学我吟诗。如今我渐渐衰老，她却刚刚长大；我并不奢望将来靠她做什么，只是这份做父亲的情意，总是忘不了。\n这首诗最动人的，不是蔡邕、缇萦这些典故，而是“学母画眉样，效吾咏诗声”。一个小女孩，一边模仿母亲，一边模仿父亲，家里的日子就在这种极小的动作里活了起来。很多诗人写家人容易写成“慈父形象”，白居易这首却不是摆姿态，他真是在看一个孩子如何一天一天长出来。\n他写阿罗，不只一首。《弄龟罗》把这种日常又写深了一层：\n有侄始六岁，字之为阿龟。\n有女生三年，其名曰罗儿。\n一始学笑语，一能诵歌诗。\n朝戏抱我足，夜眠枕我衣。\n汝生何其晚，我年行已衰。\n物情小可念，人意老多慈。\n酒美竟须坏，月圆终有亏。\n亦如恩爱缘，乃是忧恼资。\n举世同此累，吾安能去之。\n唐·白居易《弄龟罗》\n我家有个六岁的侄儿叫阿龟，还有个三岁的女儿叫罗儿。一个刚会说笑，一个已经会背诗，白天抱着我的腿玩，晚上枕着我的衣裳睡。我到了年纪已衰才得他们，自然格外怜爱；可越是疼爱，越知道美酒终会坏、满月终有亏，世上的恩爱本就常和忧愁相连。只是这种牵累，人人都免不了，我又如何能躲开？\n这首诗里最值得反复看的，是“物情小可念，人意老多慈”与“酒美竟须坏，月圆终有亏”。白居易明明抱着孩子在写欢喜，却已经知道一切圆满都难久长。也就是说，后来金銮子夭折的那种剧痛，并不是毫无预兆地从天上掉下来；在阿罗还绕膝而行的时候，他其实已经隐隐知道，越爱，越有可能受伤。\n二、金銮子：白居易写丧女，真正刺人的从来不是喊痛 白居易写家门之痛，最重的一首，无疑是《病中哭金銮子》。\n金銮子是他的幼女，年纪极小便夭折。白居易那时自己也在病中，整首诗几乎没有铺排，只是一层层把丧女之痛摊开：\n岂料吾方病，翻悲汝不全。\n卧惊从枕上，扶哭就灯前。\n有女诚为累，无儿岂免怜。\n病来才十日，养得已三年。\n慈泪随声迸，悲肠遇物牵。\n故衣犹架上，残药尚头边。\n送出深村巷，看封小墓田。\n莫言三里地，此别是终天。\n唐·白居易《病中哭金銮子》\n我自己正病着，哪里料到你却先走了。我从枕上惊起，扶着身子到灯前痛哭。世人常说有女是累，可没有儿子的人，又哪里就不会怜惜女儿？你病不过十天，我却养了你整整三年。旧衣还挂在架上，残药还留在床边；把你送出村巷，看着那座小小的新坟，这一别虽然只隔三里地，却已是永诀。\n这首诗最厉害的，不是“慈泪随声迸”这种正面喊痛，而是“故衣犹架上，残药尚头边”。衣服还在，药也还在，人却没了。白居易不去写什么“天地俱悲”，只写房间里的两样东西，就已经够了。因为真正经历过失去的人都知道，最受不了的恰恰是这些一时还来不及消失的旧物。\n“病来才十日，养得已三年”也一样。十天和三年并排放在那里，几乎比任何长篇哀辞都更残酷。你花几年时间慢慢养大一个孩子，失去她却可能只要十天，甚至更短。诗写到这里，已经不是抽象的“慈父情深”，而是一个父亲对时间的不甘：为什么养这样久，去得却这样快？\n这里顺手也可以看一眼第三联：“有女诚为累，无儿岂免怜。”这两句后世最容易被拿出来单讲性别观念，但落回原诗，其实更像白居易顺手驳俗。世人惯说有女是累，可真到了自己女儿身上，哪里还有什么“累不累”的道理，剩下的只有怜。\n三、白居易不是偶然偏爱女儿，他自己写过“与女犹胜与外人” 如果说《吾雏》和《病中哭金銮子》还是纯粹的家门诗，那么《馀思未尽，加为六韵，重寄微之》里的一联，则把这种倾向说得更明白。\n那是白居易写给元稹的诗，本来不是专门写家庭，却偏偏在后半写到：\n海内声华并在身，箧中文字绝无伦。\n遥知独对封章草，忽忆同为献纳臣。\n走笔往来盈卷轴，除官递互掌丝纶。\n制从长庆辞高古，诗到元和体变新。\n各有文姬才稚齿，俱无通子继馀尘。\n琴书何必求王粲，与女犹胜与外人。\n唐·白居易《馀思未尽，加为六韵，重寄微之》\n我和你都名重一时，文章各有气象。想到你独自面对政务文书，我也忆起从前同在朝中论政的日子。说到家门，我们各自都有像文姬那样聪明年幼的女儿，却都没有儿子来承续门户。可琴书文章又何必一定求个儿子来继承？与自己的女儿相守，终究也胜过把一切都托付给外人。\n“与女犹胜与外人”六个字，分量其实很重。因为白居易并不是在私下说一句偏疼女儿的话，而是在和元稹唱和时，明白写出来：没有儿子，并不等于什么都断了。女儿并不是门户叙事里的残缺，也可以是感情、教养、记忆和文脉的一部分。\n这一点回过头来再看阿罗和金銮子，就会更清楚。白居易不是到了晚年抱外孙女才突然“温柔起来”，也不是偶然写几首家门小诗做点缀。他对女儿的爱、怜惜和看重，前后其实是一条很长的线。\n四、从家门到世情：白居易写“妇人身”，并不只在自己家里 不过，如果只把白居易写成一个疼女儿的父亲，又会把他写窄。因为他对“女子命运”的感触，也并不只来自家门。\n《太行路》是很典型的例子。它本来是一首讽谕诗，题下注得清楚：“借夫妇以讽君臣之不终也。”可诗中那几句一落下来，还是让人忘不掉：\n行路难，难重陈。\n人生莫作妇人身，百年苦乐由他人。\n行路难，难于山，险于水。\n不独人间夫与妻，近代君臣亦如此。\n唐·白居易《太行路》（节选）\n世上的路难走，难处一时说不尽。若托生为妇人，一生苦乐往往都要由别人支配。这条路比翻山涉水还难走，而这种无可自主，不只发生在夫妻之间，近世君臣关系其实也常常如此。\n这几句首先当然是譬喻，是把“妇人苦乐由人”借来写臣子际遇不由自主。但白居易写这种句子，并不是空口借典故。他长期写宫人、写闺怨、写女子在制度里的被动，比如《上阳白发人》就是极典型的一首。也就是说，白居易笔下的“女子之苦”本来就有两层：一层是家里的，一层是人间的。\n所以，把《太行路》硬说成“因为金銮子夭折，所以白居易才懂得女性命运”，当然太直；可若说他的家门经验和世情眼光毫不相干，也不对。更像是：他一面在家里疼自己的女儿，一面也确实敏感地看见了更大的礼法与制度，如何让许多女子一生不得自主。\n五、引珠：抱在怀里时，白居易终于说出“何必是男儿” 白居易晚年写谈氏外孙女孩满月，一开口就是老人家里最真实的欢喜：\n今旦夫妻喜，他人岂得知。\n自嗟生女晚，敢讶见孙迟。\n物以稀为贵，情因老更慈。\n新年逢吉日，满月乞名时。\n桂燎熏花果，兰汤洗玉肌。\n怀中有可抱，何必是男儿。\n唐·白居易《小岁日喜谈氏外孙女孩满月》\n今早家中夫妻的欢喜，外人哪里知道。我自己生女本来就晚，如今见到外孙女，也就不嫌来得迟。东西少了才更显珍贵，人年纪大了，对孩子的疼爱也更深。新年恰逢吉日，正是满月起名的时候，香火熏着花果，兰汤洗着婴儿细嫩的肌肤。怀里既然已有一个可抱的孩子，又何必一定非要是男儿呢。\n这首诗被后人记住的，常常是两句：“物以稀为贵，情因老更慈”“怀中有可抱，何必是男儿。”前一句像家常格言，后一句更是最容易被摘出来传播的名句。可如果把它们放回白居易这一整条家门时间线里，就会发现它们并不只是“温柔正确”，而是经历过失去之后的一种真正松弛。\n年轻时他写阿罗，已经写“人意老多慈”；中年时他哭金銮子，知道什么叫“此别是终天”；等到了晚年，外孙女孩抱在怀里，他才会这样平静地说出“何必是男儿”。不是在发议论，不是在写口号，而是在说：到了这个年纪，我怀里有一个孩子，已经够了。\n也正因为白居易前面写过那么多“女儿”的爱和痛，这一句才不显得轻飘。它不是观念上的漂亮话，而是生活给出来的答案。\n六、从阿罗到引珠：白乐天写天下，也写自己家的灯前和衣架 如果把阿罗、金銮子和引珠放在一起看，白居易这条线其实很完整。\n先是阿罗。那时他写的是家里有个小女孩，学画眉，学吟诗，抱着他的脚，睡在他的衣旁。接着是金銮子，那时欢喜忽然塌下来，家里还挂着旧衣，床边还放着残药，人却已经没有了。再往后是和元稹说“与女犹胜与外人”，把这种感情说得更直。到了最后，才是满月的外孙女孩，在白居易老年的怀抱里，把半生里关于“女儿”的爱、伤、惜、怜，全都轻轻接住。\n这几首诗最可贵的地方，也许正在这里：它们不是大诗人偶尔露一手“温情”。相反，它们让我们看见，大诗人也是会回家的人，会在灯前哭，会在衣架旁愣住，会抱着孩子说些很平常的话。诗意并不总在最华丽的地方，有时候就在一个父亲看孩子的眼睛里。\n所以，白居易当然还是那个写《长恨歌》《卖炭翁》的人；但如果只记得这些大题目，忘了阿罗、金銮子和引珠，就像只记得一棵树的枝叶，没看见它最软、也最疼的那一截心。\n参考 白居易《吾雏》 白居易《弄龟罗》 白居易《病中哭金銮子》 白居易《馀思未尽，加为六韵，重寄微之》 白居易《小岁日喜谈氏外孙女孩满月》 白居易《太行路》 白居易《上阳白发人》 ","permalink":"https://june6699.github.io/posts/%E7%8F%A0%E7%A2%8E%E6%85%88%E6%80%80%E7%99%BD%E5%B1%85%E6%98%93%E4%B8%8E%E5%BC%95%E7%8F%A0%E9%87%91%E9%8A%AE%E5%AD%90%E7%9A%84%E5%8D%8A%E7%94%9F%E6%83%85%E9%95%BF/","summary":"\u003cp\u003e白居易当然不只会写《长恨歌》《琵琶行》。翻开他的集子，你会发现这位写天下、写宫怨、写民生的大诗人，碰到自己家里的小女儿、夭折的幼女、出嫁后的女儿和刚满月的外孙女时，笔下忽然会变得很轻，也很软。\u003c/p\u003e","tags":["诗","诗/人物"],"title":"珠碎慈怀・白居易与引珠、金銮子的半生情长"},{"content":"这篇主要记一个很容易误判的问题：mamba activate 之后，top、find 这类系统命令突然“消失”了。\n一开始很容易怀疑是系统没装这些命令，但只要对比激活前后，就会发现真正的问题其实是 PATH 被改坏了。\n1、现象 激活前，top 是正常的：\n$ top -hv procps-ng 3.3.15 激活环境后却不行：\n$ mamba activate xj_py39 $ top -hv bash: top: 未找到命令... 继续检查 PATH：\necho \u0026#34;$PATH\u0026#34; mamba activate xj_py39 echo \u0026#34;$PATH\u0026#34; type -a top which top # 看看激活的时候会不会有什么操作 find \u0026#34;$CONDA_PREFIX/etc/conda/activate.d\u0026#34; -maxdepth 1 -type f # 激活前（已脱敏） /custom/tool/bin:/usr/bin:/opt/meme/bin:/usr/bin:/usr/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/tools:/root/bin # 激活后（已脱敏） /root/miniforge3/envs/xj_py39/bin:/custom/tool/bin:/opt/meme/bin:/usr/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/opt/tools:/root/bin 关键区别非常明显：\n激活前有 /usr/bin 激活后 /usr/bin 消失了 这就能解释为什么 top、find 都找不到了，因为这些系统命令本来就在 /usr/bin 里。\n2、真正原因 这类问题的重点不是“命令没安装”，而是：\nmamba activate 之后，PATH 没有正确保留系统路径。\n正常情况下，激活环境应该只是把环境自己的 bin 放到最前面，例如：\n/root/miniforge3/envs/xj_py39/bin:/usr/local/bin:/usr/bin:/bin:... 而不是把 /usr/bin、/bin 这类系统路径直接弄丢。\n所以如果你遇到的是这种情况：\n激活前 top 能用 激活后 top 不能用 激活后 PATH 里少了 /usr/bin 那就已经可以基本确定：问题在 PATH，而不是 top 本身。\n常见来源一般有三类：\n~/.bashrc 或 ~/.bash_profile 里有不当的 PATH 覆盖； 环境中的 etc/conda/activate.d/*.sh 改写了 PATH； 某些工具自己的初始化脚本和 conda 激活逻辑互相冲突。 3、临时修复方式 你的这个问题，直接把系统路径补回去就恢复了：\nexport PATH=$PATH:/usr/bin:/usr/sbin 然后再测：\n$ top -hv procps-ng 3.3.15 这个命令之所以有效，是因为它做的是“追加”，不是“前置”。\n这里顺带记一个很重要的区别：\n# 不推荐：把系统路径放到最前面 export PATH=/usr/bin:$PATH # 更合适：把系统路径追加到后面 export PATH=$PATH:/usr/bin:/usr/sbin 原因很简单：\n前置 /usr/bin 可能把 conda 环境里的 python、pip 顶掉； 追加 /usr/bin 则能保留环境优先级，同时让系统命令重新可用。 4、怎么定位是谁改坏了 PATH 如果只是临时用，前面的 export 已经够了。\n如果想彻底定位原因，建议按这个顺序查：\necho \u0026#34;$PATH\u0026#34; mamba activate xj_py39 echo \u0026#34;$PATH\u0026#34; type -a top which top 如果激活后 /usr/bin 消失，就继续查：\nls \u0026#34;$CONDA_PREFIX/etc/conda/activate.d\u0026#34; 再检查：\ngrep -n \u0026#39;PATH=\u0026#39; ~/.bashrc ~/.bash_profile /root/.bashrc:25:export PATH=/root/meme/bin/ /root/.bashrc:199: export PATH=\u0026#34;/usr/bin:$PATH\u0026#34; /root/.bashrc:218:export PATH=/你的路径/SAW/bin:$PATH /root/.bash_profile:10:PATH=$PATH:$HOME/bin /你的路径/SAW/bin 这种字面量占位符属于脏配置，建议后续单独清理；但它不是这次主线问题。\n重点看有没有这种危险写法：\nexport PATH=/某个路径 或者这种会覆盖而不是追加的写法：\nPATH=/某个路径:$PATH 只要写得不小心，就可能在激活 conda 环境时把系统路径链条弄断。\n5、继续往下查：真正的罪魁祸首是谁 继续排查后，问题其实已经可以实锤了。\n先看最关键的几条输出：\n$ echo \u0026#34;$CONDA_PREFIX\u0026#34; /usr $ conda info active environment : base active env location : /usr base environment : /usr (read only) conda version : 4.10.3 python version : 3.6.8 再看 conda 的来源：\n$ type -a conda conda 是函数 conda 是 /usr/bin/conda conda 是 /usr/condabin/conda 这几条信息已经足够说明：\n当前 shell 里的 (base) 不是 ~/miniforge3； 它是系统自带的那套 conda； 它的 base 前缀就是 /usr。 这就是这次问题的真正元凶。\n5.1 为什么这会导致 /usr/bin 被删掉 conda/mamba 在切换环境时，会先把“旧环境前缀”对应的 bin 从 PATH 中移除，再把“新环境前缀”的 bin 插进去。\n你当前的旧环境前缀是：\n$ echo \u0026#34;$CONDA_PREFIX\u0026#34; /usr 那么它要移除的旧环境 bin 就是：\n/usr/bin 而你激活的新环境却是：\n/root/miniforge3/envs/xj_py39 也就是说，你当前实际干的事情并不是“从 Miniforge base 切到 Miniforge 子环境”，而是：\n从系统自带 conda 的 /usr base，切到 ~/miniforge3 里的另一个环境。\n这样一来，/usr/bin 被当成“旧环境路径”删掉，就完全解释得通了。\n然后使用mamba activate xj_py39后就会把$CONDA_PREFIX/bin加到PATH前面去。\n$echo \u0026#34;$CONDA_PREFIX\u0026#34; /root/miniforge3/envs/xj_py39 5.2 为什么前面那些怀疑都可以排除了 第一，xj_py39 环境本身几乎没有可疑激活脚本：\n$ tree ~/miniforge3/envs/xj_py39/etc ~/miniforge3/envs/xj_py39/etc ├── conda │ └── test-files └── request-key.conf 也就是说，xj_py39/etc/conda/activate.d/ 并没有明显在改 PATH。\n第二，~/.bashrc 里虽然有不少 PATH 相关内容，但从这次贴出来的片段看，基本都是“追加”，并没有直接出现“把 /usr/bin 删除掉”的写法。\n这就说明：\nxj_py39 环境本身不是元凶； 你贴出来的这段 ~/.bashrc 不是直接元凶； 真正的问题是 系统 conda 的 (base) 和 Miniforge 环境被混用了。 不过补一句，~/.bashrc 虽然不是这次“删掉 /usr/bin”的直接元凶，但它本身也已经有明显的历史污染了。例如：\nexport PATH=\u0026#34;/usr/bin:$PATH\u0026#34; export PATH=/你的路径/SAW/bin:$PATH 前者会把系统路径前置，容易顶掉环境里的 python/pip；后者更像是某个教程、模板或自动生成内容里的占位符没有替换干净，属于应该尽快清掉的脏配置。\n也就是说，这次问题有两层：\n直接触发器：系统 /usr base 和 ~/miniforge3 环境混用； 背景噪音：~/.bashrc 本身也不够干净，里面混有可疑 PATH 写法。 5.3 一句话总结这次根因 这次不是某个命令坏了，而是：\n系统自带 conda 的 /usr base 和 ~/miniforge3 里的环境混用，导致环境切换时把 /usr/bin 当成旧环境路径删掉了。\n6、真正该怎么修 临时修复当然还是：\nexport PATH=$PATH:/usr/bin:/usr/sbin 但如果想从根上修，重点不是反复补 PATH，而是只保留一套 conda 初始化链路。\n这次手动验证其实已经说明问题了：\nsource /root/miniforge3/etc/profile.d/conda.sh conda activate base echo \u0026#34;$CONDA_PREFIX\u0026#34; 输出变成：\n/root/miniforge3 随后再执行：\nmamba activate xj_py39 command -v top 结果恢复正常：\n/usr/bin/top 这说明：\nxj_py39 环境本身没问题； Miniforge 这套初始化本身也没问题； 真正的问题就是 shell 启动后先进了系统 /usr 这套 conda base。 接下来可以分成两种启动状态来看。\n6.1 分支 A：新 shell 一上来就落在系统 /usr 的 (base) 这是最容易触发问题的情况。表现通常是：\necho \u0026#34;$CONDA_PREFIX\u0026#34; /usr 如果是这种状态，再去激活 ~/miniforge3/envs/xj_py39，就可能把 /usr/bin 当成旧前缀删掉。\n这种情况下，修法是：\n明确以后只用 ~/miniforge3 这套； 让 shell 初始化 ~/miniforge3/etc/profile.d/conda.sh； 不要在同一个 shell 会话里混用系统 conda 和 Miniforge mamba。 用户级最直接的修法是，在 ~/.bashrc 末尾保留：\nif [ -f \u0026#34;/root/miniforge3/etc/profile.d/conda.sh\u0026#34; ]; then . \u0026#34;/root/miniforge3/etc/profile.d/conda.sh\u0026#34; fi 如果系统脚本仍然会先把 /usr 的 base 激活起来，还可以手动执行：\nsource /root/miniforge3/etc/profile.d/conda.sh conda activate base 确认当前已经切回：\necho \u0026#34;$CONDA_PREFIX\u0026#34; /root/miniforge3 6.2 分支 B：新 shell 启动时不激活任何 base，只保留普通 PATH 这次新的 shell 窗口其实就是这种情况：\necho \u0026#34;$CONDA_PREFIX\u0026#34; echo \u0026#34;$PATH\u0026#34; /root/meme/bin:/usr/bin:... 此时没有任何旧 conda 前缀需要被移除，所以直接执行：\nmamba activate xj_py39 往往反而是最干净、最稳定的做法。\n也就是说，如果你的新 shell 默认已经满足下面三点：\nCONDA_PREFIX 为空； PATH 里保留 /usr/bin； 直接 mamba activate xj_py39 后 top 正常； 那就没必要再强行登录就 conda activate base。直接按需激活目标环境即可。\n6.3 哪种更推荐 如果能选，我更推荐分支 B：\n默认不自动激活任何 base； 需要时直接 mamba activate xj_py39； 避免系统 /usr base 和 Miniforge base 混在一起。 分支 A 也能用，但前提是你要确保进入的是 Miniforge 的 base，而不是系统 /usr 的 base。\n7、顺手记两条环境管理经验 7.1 编译型包优先用 mamba 像 cooltools、openTSNE、pytables 这类包，如果 conda-forge 里有，优先：\nmamba install -c conda-forge cooltools opentsne pytables 比直接 pip install 更省心，因为它通常能一起处理好 gcc、fftw 这类底层依赖。\n7.2 安装前先看会改哪些包 mamba install -c conda-forge 包名 --dry-run 如果你不想让已有依赖乱跳版本，可以试：\nmamba install -c conda-forge 包名 --freeze-installed 这两条命令在维护老环境时很有用。\n8、结论 这次踩坑最关键的结论其实就一句：\nmamba activate 后系统命令消失，不一定是命令没装，更可能是 PATH 在激活过程中被错误改写了。\n判断方法也很直接：\n先看激活前命令能不能用； 再看激活后 PATH 里是否还保留 /usr/bin； 如果少了，就先手动补回： export PATH=$PATH:/usr/bin:/usr/sbin 如果手动 source /root/miniforge3/etc/profile.d/conda.sh \u0026amp;\u0026amp; conda activate base 之后一切恢复正常，就说明问题确实出在 conda 初始化链路，而不是 top、find 这些命令本身。\n再进一步说，这次更像是：\n当前 (base) 其实是系统自带 conda 的 /usr，而不是 Miniforge 的 base；因此切换到 xj_py39 时，/usr/bin 被当成旧环境路径移除了。\n所以真正该修的，不是 top，而是 conda/mamba 的初始化链路混用问题。\n最后可以记成一个简单分支：\n如果新 shell 一上来就是 /usr 的 (base)，先切回 Miniforge，再激活目标环境； 如果新 shell 默认没有激活任何 base，而且 PATH 正常，那就直接 mamba activate xj_py39，不用多做一步。 9、再补一层原理：为什么“空环境”反而更安全 这次现象还有一层很值得记一下，不然很容易只记住结论，不知道背后的逻辑。\n9.1 conda 激活环境，本质上分两种情况 第一种是“0 到 1”：\n当前 shell 没有激活任何 conda 环境； CONDA_PREFIX 为空； 这时执行 mamba activate xj_py39，conda 只需要把 xj_py39/bin 加进 PATH。 第二种是“1 到 2”：\n当前 shell 已经激活了一个 conda 环境； 这时再激活另一个环境，conda 会先把旧环境对应的 bin 从 PATH 里移掉，再把新环境的 bin 加进去。 这就像：\nxj_r -\u0026gt; dy_r base -\u0026gt; xj_py39 本质上都属于“从一个已激活环境切到另一个已激活环境”。\n9.2 这次为什么会把 /usr/bin 删掉 关键不在于 conda 的逻辑错了，而在于它识别到的“旧环境”不是你以为的那个。\n这次旧环境其实是系统 conda 的：\nprefix = /usr 注意这里要分清：\nprefix 是环境根目录； bin 是这个环境里放可执行文件的目录。 所以：\nprefix = /usr bin = /usr/bin 当 conda 认为当前旧环境是 /usr 时，切换到 xj_py39 的过程中，就会把：\n/usr/bin 当成旧环境的 bin 移除。\n而 top、find、which 这类系统命令，本来就依赖 /usr/bin，所以它们就一起“消失”了。\n9.3 为什么“空环境”时反而没事 当新的 shell 窗口里：\necho \u0026#34;$CONDA_PREFIX\u0026#34; 输出为空时，含义不是“有个隐藏的 base”，而是：\n当前根本没有激活任何 conda 环境。\n这时候再执行：\nmamba activate xj_py39 conda 处理的是“0 到 1”，它只会把：\n/root/miniforge3/envs/xj_py39/bin 加进来，而不会先删一个旧环境的 bin。\n因此 /usr/bin 会继续保留，top 也就正常。\n9.4 为什么 conda activate base 不一定会暴露这个问题 这也是这次最容易让人困惑的一点。\n如果你已经处在系统 conda 的 (base)，再执行一次：\nconda activate base 很多时候不会看到 top 消失。原因不是问题不存在，而是：\n旧环境本来就是 /usr 新环境还是 /usr conda 就算重算一遍，也会把 /usr/bin 再加回来 所以这种情况下，问题会被“覆盖掉”。\n但从：\n/usr base -\u0026gt; /root/miniforge3/envs/xj_py39 切过去时就不一样了：\n它会删掉 /usr/bin 加回来的是 xj_py39/bin 而不是 /usr/bin 于是问题就暴露出来了。\n9.5 这次可以记住的一句话 这次真正该记住的不是“top 为什么坏了”，而是：\nconda 环境切换时，会先移除旧环境的 bin；如果旧环境被错误识别成系统 /usr，那 /usr/bin 也会一起被移掉。\n","permalink":"https://june6699.github.io/posts/mamba_conda_env_notes/","summary":"\u003cp\u003e这篇主要记一个很容易误判的问题：\u003ccode\u003emamba activate\u003c/code\u003e 之后，\u003ccode\u003etop\u003c/code\u003e、\u003ccode\u003efind\u003c/code\u003e 这类系统命令突然“消失”了。\u003cbr\u003e\n一开始很容易怀疑是系统没装这些命令，但只要对比激活前后，就会发现真正的问题其实是 \u003ccode\u003ePATH\u003c/code\u003e 被改坏了。\u003c/p\u003e","tags":["技术","技术/工具"],"title":"Conda/Mamba 环境管理踩坑记录与最佳实践"},{"content":"0、默认 本教程默认你已经成功实现Windows的，右键新建一个Markdown file的功能，可见教程 。 且你使用的Typora中，图片存放位置为./images/${filename}，否则需要略作修改，若全部看懂完全可以自行操作或联系作者 。 1 使用前先看 1.1 先改一个路径 如果你要使用文末“可选：右键在 Obsidian 中新建笔记”的注册表代码，请先把所有代码里的 Obsidian 安装路径替换成你自己的实际路径。\n比如我的路径如下：\nC:\\softwares\\Obsidian\\Obsidian.exe 1.2 本文最终目标 1.2.1 最终工作流 .md 文件默认仍由 Typora 打开：双击.md仍然是Typora； Obsidian 和 Typora 共用同一批 .md 文件：Obsidian和Typora都能打开.md文件； Obsidian 插入的新图片，Typora 也能正常显示； 图片保存到 ./images/{笔记名}/：类似Typora的./assets/{filename}/； 其他附件保存到 ./attachments/{笔记名}/：Typora这个没有，但是也用不着。 1.2.2 为什么这样设置 Obsidian 更偏向知识库和 vault 工作流，Typora 更偏向普通文件编辑。要让两边兼容，关键不是人为制造两种不同的 Markdown 文件，而是统一下面三件事：\n链接格式使用标准 Markdown 链接路径使用相对路径 附件目录使用固定规则 2 Obsidian 核心设置 2.1 文件与链接 打开 设置 -\u0026gt; 文件与链接，按下面设置。\n2.1.1 使用 Wiki 链接 关闭 这样 Obsidian 会生成标准 Markdown 链接，兼容 Typora。\n官方文档：https://help.obsidian.md/Linking%20notes%20and%20files/Internal%20links 2.1.2 新链接格式 选择：相对于当前文件的路径 这样图片或文件插入后，会写成相对路径，而不是只写文件名。相对路径更适合 Typora 解析。\n2.1.3 新建笔记的存放位置 按你的习惯设置即可 这一项只影响“新建笔记放在哪里”，不影响图片和附件的保存目录。\n3 第三方插件 3.1 关闭受限模式 打开 设置 -\u0026gt; 第三方插件：\n关闭 受限模式 有些中文界面里也会把这项叫作“安全模式”。\n官方文档：https://help.obsidian.md/community-plugins 插件安全说明：https://help.obsidian.md/plugin-security 3.2 安装 Attachment Management 推荐插件：Attachment Management\nGitHub：https://github.com/trganda/obsidian-attachment-management 也可以直接在 Obsidian 社区插件商店搜索 Attachment Management 安装 这个插件支持：\n${notepath}、${notename} 这类路径变量 按扩展名覆盖不同的附件规则 自动重命名附件 4 Attachment Management 推荐设置 打开 设置 -\u0026gt; 第三方插件 -\u0026gt; Attachment Management，按下面填写。\n注意下面是图片路径设置，是在第三方插件里面修改\n4.1 全局设置 4.1.1 根文件夹 ./ 这表示以当前 vault 中的当前路径为基准处理附件目录。\n4.1.2 图片的附件路径 ${notepath}/images/${notename} 这条规则可以拆开理解：\n${notepath}：当前笔记所在的文件夹路径 images：固定的图片区目录名 ${notename}：当前笔记文件名，不含 .md 也就是说，一张图片不会直接丢在笔记旁边，而是会进入：\n当前笔记所在目录/images/当前笔记名/ 例如当前笔记是：\nnotes/部署步骤.md 那么图片目录就是：\nnotes/images/部署步骤/ 这样做的好处是：\n每篇笔记的图片都集中在自己的子目录里 同名图片不容易互相冲突 Typora 和 Obsidian 都更容易用相对路径引用 4.1.3 图片的附件格式 直接原文件名==（Typora最常用）==：\n${originalname} 或保持简洁命名：\nIMG-${date} 4.1.4 日期格式 YYYYMMDDHHmmssSSS 这会生成带年月日时分秒毫秒的时间戳，基本可以避免重名。\n4.1.5 自动重命名附件 打开 4.2 扩展名覆盖 点击 添加扩展名覆盖，为非图片附件增加一条规则。\n4.2.1 为什么还要单独做 attachments images 目录只适合存图片。\n但一篇笔记除了图片，还可能会插入这些文件：\nPDF Word Excel PPT 压缩包 文本附件 音频或视频 如果这些文件也全塞进 images/{notename}，目录语义就会变乱。\n所以更适合的做法是：\n图片进入 images/{notename} 其他附件进入 attachments/{notename} 这样一篇笔记最终可能会变成：\n部署步骤.md images/部署步骤/ attachments/部署步骤/ 这就是 attachments 文件夹的意义：\n它不是第二套图片目录，而是给“非图片附件”准备的专门目录。\n4.2.2 扩展名正则 pdf|doc|docx|xls|xlsx|ppt|pptx|zip|7z|rar|csv|txt|mp3|wav|mp4 这串正则的意思不是“路径替换”，而是“匹配哪些文件扩展名要走这条覆盖规则”。\n可以逐项理解为：\npdf：PDF 文件 doc|docx：Word 文档 xls|xlsx：Excel 表格 ppt|pptx：PowerPoint 文件 zip|7z|rar：压缩包 csv|txt：文本或数据文件 mp3|wav|mp4：音频、视频文件 中间的 | 表示“或者”。\n也就是说，只要附件扩展名命中了其中任意一个，就不再走默认的图片目录规则，而是改走下面这条专门规则。\n4.2.3 覆盖规则的附件路径 我按上面设置完images后，附件自动保存在了${notepath}/附件/${notename}里面，然后我发现如果你强迫症一定要放在英文名的attachments下，需要回到设置——文件与链接重新设置附件位置。\n4.2.4 覆盖规则的附件格式 这个格式也是默认的，就是原文件名字，无法更改。\n${originalname} 4.2.5 这条覆盖规则的实际效果 默认情况下，你在全局里设置的是：\n${notepath}/images/${notename} 也就是先把“所有受插件管理的附件”默认往图片目录里放。\n而扩展名覆盖会告诉插件：\n如果扩展名命中上面那串正则 就不要再放进 images 改放到 attachments 所以这里的“替换”本质上是“规则分流”，不是文本层面的字符串替换。\n4.2.6 如果你常用其他附件类型 就在这串正则后面继续加，仍然用 | 分隔即可。\n例如你常用：\nmd epub mobi psd 那么可以扩展成：\npdf|doc|docx|xls|xlsx|ppt|pptx|zip|7z|rar|csv|txt|mp3|wav|mp4|epub|mobi|psd 4.3 排除扩展名模式 如果没有特殊需求，可以先留空。\n只有当你明确不想让某些附件类型被插件处理时，再填写排除规则。\n4.4 历史附件整理 如果需要整理已有附件，可以使用插件命令：\nRearrange linked attachments Rearrange all linked attachments 这个功能在插件说明里标注为实验性功能，正式整理前建议先备份仓库。\n插件说明：https://github.com/trganda/obsidian-attachment-management 4.5 最终效果 5 Typora 兼容的关键点 5.1 为什么 Typora 之前不显示 Obsidian 插入的图片 问题通常不在于图片目录本身，而在于链接写法。\n如果 Obsidian 生成的是这种最短链接：\n![](Pasted%20image%2020260411120248.png) 而图片实际保存在：\n./images/部署步骤/Pasted image 20260411120248.png 那么 Typora 按普通文件路径解析时，就可能找不到图。\n这实际上是他们两个内部的源码不一样，你手动修改为一样的，完全可行，但是过于麻烦。\n5.2 兼容 Typora 的两个关键设置 把 Obsidian 的这两个设置改好以后：\n使用 Wiki 链接 关闭 新链接格式 设为 相对于当前文件的路径 之后新插入的图片链接会更接近下面这种形式：\n![](./images/部署步骤/Pasted%20image%2020260411120248.png) 这种写法更适合 Typora 和 Obsidian 共用。\n6 关于“用 Obsidian 打开某个 md 文件” 6.1 结论 Obsidian 并不像 Typora、VS Code 这类编辑器那样，把“打开一个 .md 文件”作为最自然的入口。它更接近“先进入一个 vault，再在 vault 里打开或创建笔记”的工作方式。\n6.2 为什么会有这种感觉 Obsidian 启动时有“打开上次的文件”“新文件”“指定文件”“日记”等偏好选项，但通过系统文件关联或命令行去点开某个 .md 时，体验并不像 Typora 那样直接、稳定。很多时候，从使用感受上看，更像是“先把 Obsidian 打开了”，而不是真正像传统编辑器那样“精准打开这个文件”。\n6.3 为什么会这样 官方文档对 Obsidian 的描述一直围绕 vault 展开：\nVault 是 Obsidian 的核心工作单元 URI 的 open、new 等能力也是围绕 vault 或 vault 内路径设计的 path 这类能力的核心逻辑，也是先定位包含该路径的 vault，再处理 vault 内文件 官方文档：\nObsidian URI：https://help.obsidian.md/uri Manage vaults：https://help.obsidian.md/manage-vaults Data storage：https://help.obsidian.md/data-storage 更准确地说：\nTypora 更像“打开一个独立文件” Obsidian 更像“打开一个知识库，再访问其中的文件” 6.4 最终推荐的使用方式 最终更推荐的方案是：\n.md 默认打开方式继续交给 Typora Obsidian 不承担“按文件直接打开”的主入口职责 需要在 Obsidian 里工作时，先打开 Obsidian 如果你习惯一进 Obsidian 就开始写，可以把启动后的默认行为设置成你偏好的新文件、上次文件或日记 换句话说，Obsidian 更适合当“知识库入口”，而不是 Typora 那种“点哪个文件就直接编辑哪个文件”的入口。\n6.5 Obsidian 有没有类似 VS Code 的“在该处打开项目” Obsidian 里最接近 VS Code “Open Folder” 的能力，其实是：\nOpen folder as vault 官方文档：https://help.obsidian.md/manage-vaults 它的思路不是“打开一个文件”，而是“打开一个仓库或知识库目录”。\n所以如果你平时是按项目或笔记库组织内容，Obsidian 这个思路其实也说得通。\n6.6 快速切换仓库是否够用 如果你已经把常用目录都建成 vault，那么 Obsidian 底部的仓库管理和切换功能，通常已经够用了。\n这也是为什么最终更推荐把 Obsidian 当作“先进入仓库，再工作”的工具来使用。\n7 推荐的最终方案 7.1 推荐保留的内容 .md 默认打开方式保持为 Typora Windows 右键 新建 -\u0026gt; Markdown File 保留 Obsidian 负责知识库、双链、附件整理 7.2 不建议再额外区分“Obsidian 文件” Obsidian 使用的文件本质上也是普通 .md。只要图片路径、链接格式和附件目录规则一致，就没有必要人为区分“Typora 的 md”和“Obsidian 的 md”。\n7.3 为什么最后不建议保留“新建 Obsidian 笔记” 表面上看，这个功能像是在“新建一种专属于 Obsidian 的文件”，但本质上它做的事情仍然只是：\n创建一个普通 .md 再尝试交给 Obsidian 而 .md 本身并不是 Obsidian 的专有格式，所以这个动作并没有创造出一种新的文件类型。\n如果前面的图片路径、链接格式和附件规则已经统一好，那么“新建 Obsidian 笔记”带来的额外价值就很有限。\n从维护成本和系统整洁度考虑，更推荐的做法仍然是：\n保留 新建 -\u0026gt; Markdown File Typora 继续作为默认打开方式 Obsidian 作为知识库工具使用 8 可选：右键“在 Obsidian 中新建笔记” 这一部分不是必须。如果你的主工作流已经是“右键新建 Markdown，再按需用 Obsidian 打开”，可以直接跳过。\n而且有点小BUG，跟新建Markdown文件功能没有任何区别。\n8.1 这个方案与 Typora 是否冲突 不冲突。\n原因很简单：\n.md 的默认打开方式仍然是 Typora 右键菜单只是额外增加一个命令 这个命令的作用是“新建一个普通 .md，然后立即用 Obsidian 打开” 8.2 为什么不建议强行放进“新建”子菜单 Windows 的 新建 子菜单本质上是按文件扩展名和 ShellNew 规则生成的。.md 只有一种文件类型，把它强行拆成“Markdown File”和“Obsidian File”两套并不自然，也更容易和默认打开方式、文件关联、右键模板互相冲突。\n更稳妥的方式是：\n保留系统原生的 新建 -\u0026gt; Markdown File 另外加一个顶层右键命令 在 Obsidian 中新建笔记 8.3 为什么后来又不建议保留这个命令 这个命令最大的问题不是“能不能新建文件”，而是“Obsidian 对按文件路径直接打开某个 .md 的支持，并不像 Typora 或 VS Code 那样自然稳定”。\n换句话说，这个命令就算存在，它的本质也更接近：\n先启动 Obsidian 再尝试把焦点落到对应文件 而不是传统编辑器那种非常明确的“打开这个文件”。\n8.4 脚本内容 如果你仍然希望保留这个右键命令，可以先新建一个脚本文件，例如：\nC:\\Users\\你的用户名\\Desktop\\obsidian_new_note.vbs 把下面内容完整复制进去：\nOption Explicit Dim shell, fso, folderPath, noteName, fullPath, obsidianExe obsidianExe = \u0026#34;C:\\softwares\\Obsidian\\Obsidian.exe\u0026#34; If WScript.Arguments.Count = 0 Then MsgBox \u0026#34;Missing target folder.\u0026#34;, vbExclamation, \u0026#34;Obsidian New Note\u0026#34; WScript.Quit 1 End If folderPath = WScript.Arguments(0) Set shell = CreateObject(\u0026#34;WScript.Shell\u0026#34;) Set fso = CreateObject(\u0026#34;Scripting.FileSystemObject\u0026#34;) noteName = InputBox(\u0026#34;Input note name (without .md):\u0026#34;, \u0026#34;Obsidian New Note\u0026#34;, \u0026#34;New Note\u0026#34;) If Trim(noteName) = \u0026#34;\u0026#34; Then WScript.Quit 0 End If If LCase(Right(noteName, 3)) \u0026lt;\u0026gt; \u0026#34;.md\u0026#34; Then noteName = noteName \u0026amp; \u0026#34;.md\u0026#34; End If fullPath = fso.BuildPath(folderPath, noteName) If Not fso.FileExists(fullPath) Then Dim fileHandle Set fileHandle = fso.CreateTextFile(fullPath, True) fileHandle.Close End If shell.Run Chr(34) \u0026amp; obsidianExe \u0026amp; Chr(34) \u0026amp; \u0026#34; \u0026#34; \u0026amp; Chr(34) \u0026amp; fullPath \u0026amp; Chr(34), 1, False 8.5 注册表代码 把下面内容保存成 .reg 文件后导入，或直接复制到注册表脚本中使用：\nWindows Registry Editor Version 5.00 [HKEY_CURRENT_USER\\Software\\Classes\\Directory\\Background\\shell\\ObsidianNewNote] @=\u0026#34;在 Obsidian 中新建笔记\u0026#34; \u0026#34;Icon\u0026#34;=\u0026#34;C:\\\\softwares\\\\Obsidian\\\\Obsidian.exe,0\u0026#34; [HKEY_CURRENT_USER\\Software\\Classes\\Directory\\Background\\shell\\ObsidianNewNote\\command] @=\u0026#34;wscript.exe \\\u0026#34;C:\\\\Users\\\\你的用户名\\\\Desktop\\\\obsidian_new_note.vbs\\\u0026#34; \\\u0026#34;%V\\\u0026#34;\u0026#34; 8.6 卸载代码 如果以后不想要这个菜单，导入下面这段即可删除：\nWindows Registry Editor Version 5.00 [-HKEY_CURRENT_USER\\Software\\Classes\\Directory\\Background\\shell\\ObsidianNewNote] 9 为了以后重设，建议顺手备份哪些内容 9.1 这次改动里，哪些属于底层修改 这次真正涉及系统层面的修改，其实很少：\n.md 默认打开方式 可选的右键菜单注册表项 而本文的核心兼容方案，主要都不是底层 hack，而是：\nObsidian 内部设置 你的 vault 内的插件设置 所以即使以后 Obsidian 更新，最核心的东西通常也不会“突然全没了”，因为它们本质上都还是配置文件。\n9.2 最值得备份的是 .obsidian 文件夹 官方文档说明，vault 的配置数据存放在 .obsidian 目录中。\n官方文档：https://help.obsidian.md/data-storage 所以最推荐的做法是：\n备份你的 vault 根目录下 .obsidian 整个文件夹 这通常会包含：\nObsidian 的大部分本库设置 社区插件配置 工作区相关配置 9.3 如果想方便以后再次设置 建议至少保留下面三样：\n这份说明文档 你的 .obsidian 文件夹备份 如果你用了右键菜单，再单独保留一份 .reg 代码 这样以后即使重装 Obsidian、换设备、换 vault，也能很快恢复设置。\n10、最终总结 完成Typora和Obsidian的图片实际图片路径级（4.1 修改图片存放位置）和源码级（5.2 修改最短URL）大一统； 完成附件的位置自定义：4.2 4.3，与图片在同一个根目录下，一个为images，一个为attachments，名称均可自定义。图片文件夹的可个性化设置更多，附件文件夹名称在中文版中默认为附件。 可选：完成Windows用户的使用Obsidian新建Markdown文件的注册表注册和卸载命令，但是受限于Obsidian实际上是用Obsidian vault这种模式打开Markdown，导致每次使用该功能，实际上就是点击Obsidian而已，与打开Obsidian的默认行为设置有关，与你要打开的文件，没一点关系，待完善。 ","permalink":"https://june6699.github.io/posts/obsidian-typora-%E5%85%BC%E5%AE%B9%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%8D%97/","summary":"\u003ch2 id=\"0默认\"\u003e0、默认\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e本教程默认你已经成功实现\u003ccode\u003eWindows\u003c/code\u003e的，\u003ccode\u003e右键新建一个Markdown file\u003c/code\u003e的功能，可见\u003ca href=\"https://zhuanlan.zhihu.com/p/1890391736620151950\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e教程\u003c/a\u003e\n。\u003c/li\u003e\n\u003cli\u003e且你使用的\u003ccode\u003eTypora\u003c/code\u003e中，图片存放位置为\u003ccode\u003e./images/${filename}\u003c/code\u003e，否则需要略作修改，若全部看懂完全可以自行操作或联系\u003ca href=\"https://june6699.github.io/about/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e作者\u003c/a\u003e\n。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"1-使用前先看\"\u003e1 使用前先看\u003c/h2\u003e\n\u003ch3 id=\"11-先改一个路径\"\u003e1.1 先改一个路径\u003c/h3\u003e\n\u003cp\u003e如果你要使用文末“可选：右键在 Obsidian 中新建笔记”的注册表代码，请先把所有代码里的 Obsidian 安装路径替换成你自己的实际路径。\u003c/p\u003e","tags":["技术","技术/工具"],"title":"Obsidian-Typora 图片及附件位置存放兼容设置"},{"content":"作者链接：百度贴吧 三十岁的开头 今天是我的30岁生日捏，现在是24号的0点，牢。\n躺在床上睡不着，回想着这30年的人生，很好奇，满嘴喷分的8u们过着什么样的人生呢。\n楼主老了，就不和你们这些小年轻一起打了，嘿嘿嘿嘿。\n有好多想说的，话到嘴边又不知道从什么地方说起，倒也不怕笑话，鼠鼠我啊，其实挺惨的，哈哈哈哈。\n童年与离散 小学的时候真的，我爸在江阴做生意，一个星期回来一次，有时候两个星期，每次回来都会带玩具给我，那时候真开心啊，嘿嘿，嘻嘻，哈哈哈哈哈哈。\n我妈呢，那时候管着我，就是家庭主妇，对我可好了。\n小学我调皮得很，经常欺负我同桌，那个小姑娘特别瘦，然后显得头特别大，我总管她叫大头，她姓程，我就管她叫程大头，经常把她搞得脸红，哈哈哈哈。\n所以放学留堂是必然的，我妈都跟门卫混熟了，哈哈哈。\n那个场景我到现在还记得呢，放学，班主任，一个老头，带个眼镜，缠着厚厚的胶带的眼镜，和我妈抱怨我多么调皮，我妈愤怒得很，说她天天打我，家里扫帚都打坏了好几条，给这老头吓的，说了不少我的好话，哈哈哈。\n放学路上，我坐着我妈那个小的自行车，直呼我妈大名，然后问她我家啥时候扫帚打坏好几条了，给我妈急的，找了个没人的地方，下来就是给我了两个嘴巴子，好像挺疼的但不刻苦铭心。\n后来到了小学毕业，我爸妈突然离婚了，原因后面会讲，挺闹心的。\n我爸挺厉害的，那个年代就已经买车买房了，比起我爸，我确实是个废物。\n仔细想想，我95的还没到30，哈哈哈哈哈。\n我爸妈离婚的那个暑假，我玩了一个暑假的魔兽争霸和英雄无敌，吧里有玩英雄无敌的嘛，家里正常没人，我爸饭点会回来送饭，然后就急忙忙的去工作了。那时候睁眼不知道干啥，闭眼又总是睡不着，看着空荡荡的屋子，不知所措，总有种说不出的感觉。那种感觉不热烈，没有悲伤那么痛苦，没有愤怒那么强烈，不喜不悲的，就是感觉心里起了一层雾，一层很平淡的雾，雾不大，但是足以遮住太阳，却任由风雨袭来。\n后来，我才知道，那层雾叫孤独。\n初中、高中和那场坠落 然后就上了初中，对了忘了一个胖子，我邻居，小学同学，小学经常带他欺负女同学，我姓陈，他姓刘，他管我叫老大，然后初中还和我在一个班😒。\n暑假快结束的时候，我家楼下的一个老太搬走享福去了，房子空着，我爸和他朋友，也是他的生意伙伴，姓夏的一个人，拖家带口搬进来了，两人准备在这个小城搞点事业。那个老登还带了一个女儿，长得可好看了，就是脾气贼爆。\n初中开学分班，刘胖子和我还有那个漂亮妹妹都在一个班，接着就是上学放学。那时候刘胖子有家长接送，我和这个女孩，姑且就叫她夏J吧，就经常一起回家。\n那时候因为父母离婚其实我变得很安静，夏j第一天认识我就问我晚上吃什么。当时我们父母，应该说我的父亲和她的父母都很晚回家，所以经常晚上一起吃饭。这个b第一天就骗了我100元买肯德基，我那时候很内向，想着回家把昨天的菜热热也可以吃，就没管她。回家的时候，这丫头躲在我家门口，我拉开门，她立马对我就是一顿骂，然后说想看看我偷吃什么好东西，一看桌上的剩菜，估计良心发现了，说她肯德基买多了。\n这个b喜欢打游戏，她妈不让买电脑，就经常到我家来打游戏。她喜欢玩红警，那时候还玩了一个无敌浩克的游戏，我控制浩克走，她负责砸，看见人一个起跳就是砸，暴力得很，一个单人游戏在不知道任务剧情的情况下，还是没汉化，我俩能玩一天。\n初中那会，古惑仔文化盛行，班里很多男的都装流氓，我在班上很少闹腾，不过本人长得比较白净，吸引了隔壁班的一个太妹。这个太妹对我耍起了流氓，我基本都是躲着她的，然后估计看我没意思，就恼了。刘胖子这个b真仗义啊，看见了就是一通骂，唉，他不这么仗义就好了。\n刘胖子不知道咋的迷上了二次元，天天就是和人大声畅谈哪个人物可爱，接着事情不知道怎么发展的，刘胖子遭到了霸凌。起初还是桌子上被写一些话，然后越来越过分。我这个人啊，真是个废物，兄弟被人欺负了，还不去帮忙，跟个死人一样，真是个飞舞。\n后来越来越严重，已经发展到动手了。刘胖子经常青一块紫一块的，我再也看不下去了，追到实验楼去，准备拼了，不出意外，我也被打了，夏j带着老师赶来，事情才算结束。\n我叠动了点关系，让几个问题比较大的学生停学了，他们这群出生，知道我有关系，都不敢搞我了，偷着欺负刘胖子。刘胖子这个b，真的是仗义，怕我受影响，一直受着欺负，我就跟个闹参一样，啥都不懂，就这样天天和他打着哈哈，就这样初中毕业了。\n到了高中，我、刘胖子、夏j，都上了一个二流的高中。高中时的我和夏j似乎产生了感情，估计也是情窦初开。\n8u们见过尸体吗？\n我真的有点不想回忆当时的场景。\n那一天我死都不会忘的，那天我感冒，好像是高二，我中午才来的学校，到了学校以为班上都在午睡，我就偷偷地躲进了同楼的机房，耳机带上听歌，估摸着时间回到了教室。到了教室，气氛很诡异，那是一种令人窒息的安静，班上的都不像是刚睡醒的样子，夏j站起来，极力地想说什么，眼神不自觉地飘向窗外。\n刘胖子跳楼了，他安静地躺在花坛旁边，白色的野花被他的血给染了个通红，血均匀地撒在花朵上，摔得已经认不清他的脸，还有一大坨不明的液体围在他的周围，肚子因为磕到了不知道哪里的角被划开了一个大口子，那种感觉就像被人掐住了喉咙一样，说不出话，很难受，头突然就是一阵激烈的眩晕，真的很难受。\n那天，在刘胖子的尸体运走之后，学校集体开了一个会，大概是讲不要乱说，乱传这件事，会后，放了一天的小假。\n我一个人走在回家的路上，夏j跟了过来，依旧是一句话不说，只是静静地跟着我。就这样走完一小段之后，夏j开口了，声音很沙哑。\n“求你别像他那样做傻事。”\n我沉默地看着她，不理解她突然的关心，但还是点了点头。之后一路无话，直到了家，她想跟着我进来，被我挡在了门口。\n“就这样吧，放心，我很怕死的。”说罢便关上了门，在那一瞬间，我强撑的身体瞬间失去了所有力气，瘫坐在门旁，呆呆地看着天花板，家里又是死一般的寂静，忽然一阵心慌，变得难以呼吸，大口地吸着气，脑子里猛烈地嗡的一声，剧烈的头晕，胃里翻江倒海，我冲到厕所，趴在马桶上，哇的一声，吐了出来，一边吐，眼泪一边流了出来，我很想大喊大叫，来宣泄一下，我尝试过，但是失败了……\n之后，我很长时间没有去学校，我爹没去工作，这么多天在家里陪我，做好菜，放在我房间门口，我也不和他说话，躲在房间里打着游戏，那种感觉很麻木，那时候玩联盟，游戏天赋贼高，一手盖伦一直赢，赢了就呆呆地看着屏幕，然后再开一把，那时候的我，输了就喷人，赢了也喷，确实是个出生捏。\n我爹终于把我房门打开了，啥也没说，把我电脑搬到了客厅，让我想玩去客厅玩。我不知道咋的，一看见他那张脸就绷不住了，嚎哭起来。我爹，一米七多的大男人，居然抱着我也哭了，一边哭一边说他不是个好爸爸，不是个好爸爸，哈哈哈。\n人啊，就是这样，花大把时间迷茫，在几个瞬间成长。\n之后的事学校该开除的开除，该停职的停职，参与霸凌的那些出生，一个都没有好下场。\n高中就这样混过去了，刘胖子的死对我影响蛮大的，我变得极度的自卑、敏感，甚至很长的一段时间看见花还会犯恶心。高三的上学期，夏j还对我告白了，哈哈哈，不过那时候的我习惯地封闭自己的情感，后来才知道这是一种病，我拒绝了她，很怂吧。在这之后没几个月，因为她成绩特别差就出国留学了，我参加了高考，也许一辈子的好运都用在这里了，我这种中下的成绩居然给我混了一个双非。\n青春啊，看起来似乎轰轰烈烈，其实仔细回想也就这点事，不过胜在了朦胧，败给了遗憾。\n忘了说了，lz是学美术的，吧里有也有美术生的话，不懂的问题可以问我，靠艺术混上的大学捏。\n夏j这个女孩啊，真的是个好女孩，除了脾气不好其他都挺好的，绝对不是xxn。她在我最伤心的时候总是陪着我，我那时候情绪很不稳定，经常对着我爹和她发火，她这样的女孩居然忍着，安慰我。lz是个飞舞，现实生活中在最纯粹的年纪遇到这么好的女孩，大家不要学我，要好好珍惜啊。\n大学、大头和错过 他们都有朋友，每个人都在自己最后的青春时光里狂欢，而我像是一个观众，在一个人的电影院里，观看着与自己无关的幸福，傻笑着享受孤独。\n鼠鼠是在浦口上的大学，大学学的艺设，天天闲得很。宿舍四个人，三江苏的，还有一个合肥的。所以说命运总是在暗中给你写好了剧本，睡我对面那个b高中暗恋两年的女的是老子小学天天欺负的那个大头，给我看了照片。现在这个大头养好了点，不那么瘦了，所以头没那么大了，本来长得就不丑，所以确实挺好看的。\n之前提过，我这个人有点情感障碍，比起普通人，我很难对一个人产生感情，即使有好感，那也很难表述出来，所以我一般不会去追一个女孩，就算再喜欢我也不会去追，甚至不会主动找她。通俗地讲我这个人就是喜欢端着，我可以很轻松地讨好所有人，轻松地看穿很多人想要什么，钱，一些幽默的笑话，违心的认可，我习惯用一个一个的面具去伪装自己，去迎合所有人，像个没有主见的狗一样，哈哈哈。\n但是对于大头，奇怪的是，在她的身边我莫名地安心，这种感觉我极其地贪恋。我一直以来都以为我不在乎自己的情感，封闭着自己，但是我不知道的是，爱是人的本能，这种本能就算被自己遗忘了，也会在心里的某一处地方默默地成长，直至照亮那连自己都不在乎的破败不堪的心灵。\n其实认真想想也可以明白，为什么我会对大头有这种感觉，她出现的时刻是我这辈子最开心的时光，和我爸妈妈都陪着我，有好朋友，每天都是无忧无虑的。\n在那之后我其实有很长的一段时间都没有和她联系，直到有一次我半夜突然急性肠胃炎，被那个睡我对面的哥们抬到医院挂急诊的时候，那哥们发了个朋友圈，被她看见了，第二天发消息问我咋样了。可能是心有灵犀，两个孤独的灵魂恰巧找到了各自的栖息地。没有什么轰轰烈烈的爱情故事，在一次我去找她玩，吃完饭回去，在一号线的地铁上，她问我要找她做女朋友吗？我回了一个好，就这样确认了关系。\n因为两个人，一个在江宁，一个在浦口，所以我们定了一个碰头的地方，新街口。她是一个很要强的女孩，出去吃饭必须要aa，不管我送什么礼物给她，她都会有回礼。在她的眼里，付出就会有回报。我们一起去了很多地方，黄山、上海的迪士尼、乌镇、乌鲁木齐，我们的感情升温很快，要不是学校隔着很远，我们恨不得每天都在一起。\n人生啊，总有那么一刻你想反复回忆却怎么也想不起，也有那么一刻，你想把她遗忘，却又怎么也忘不掉。\n大学四年很快就过去了，临近毕业的最后一个月，我们一起出来吃饭，那是第一次我看她喝酒。我们聊了很多，也是那一刻我第一次把我的家庭情况、过去的遭遇全部和她倾诉了。我说了我很想我的妈妈，我还和她说了我对于刘胖子的内疚。我只记得我跟个疯子一样，疯狂地哭又使劲地笑，那天我喝多了，印象里我就像童年时期被狗追着跑，回到家哭着找妈妈那样，她拍拍我的头，说不怕不怕。回去之后第二天，她发给我了这样一句话。\n假如是电影，那么到这里就已经快结束了，男主和女主之后幸福地生活在了一起，可是这是人生。\n大头和我不是一类人，她是一个不安分的人，对于未来，她总是激情澎湃，她的志向很远大，她极度地渴望证明自己，所以对于学习十分认真，而且不知疲倦，考研、出国学习、打算去顶尖的医院实习工作，各种日程安排得满满的。她骄傲得就像一株寒梅，看着柔弱，其实比谁都要强。而我不一样，我没什么出息，对于未来我只想有够应付生活的钱，悠哉悠哉地混完一辈子，没什么想干的，对于生活从来就是得过且过。\n毕业之后，我找了一个教小孩画画的工作，我们俩从无话不谈到后来都明白，我们不合适，至少现在不合适。我们拥有一个美好的过去，可是爱不是回忆过去，而是创造未来，所以我们都在等对方变得更好。\n在一次我教完小孩下班的路上，她约我来到了以前我们经常去的一个烧烤店，在江宁义乌小吃街那里。她开口了，我和故事的开头一样，我回了一句好。我和她都是情绪很稳定的人，在吃完后我们在那附近漫无目的地散步。我问她接下来有什么打算，她像个孩子在炫耀新玩具一样，滔滔不绝地讲着，我静静地听。突然有点恍惚，好像我似乎一直都是这样，很少自己发表看法，一直都是听她说话，听她讲她的伟大目标，她的未来，而我只是在一边轻轻地附和，究竟是什么时候她讲述的未来里没了我的呢？\n在散步到一个小区的公园的时候，我们都意识到要分别了。她哭了，这是她第一次向我展示她的柔弱，我却没了拥抱她的资格。我转过身去，准备离开，我走得很轻，以至于公园的声控路灯都没亮。突然，她大喊了一句我的名字。我回过头来，看着她的脸，摆了摆手，向着那条被她喊亮的前方，大步流星。\n可能大伙不知道大头对我的意义，在认识她之前，我属于那种很少去和人沟通的那种人，不是不善言辞，只是习惯于封闭自己，独来独往，社恐挺严重的。但是遇到她之后，很大程度上缓解了我这种感觉，她似乎有一种能力，在她身边我变得不像我，变得开朗，变得自信。分开后，我很想她，自然也想去试着挽回，后来我想通了，其实这样挺好的，把彼此纯粹的青春看作礼物，把其余的交给时间和缘分，最后等到白头，也许是偕老晚年，就算不是，偶尔碰到对方也可以笑着谈起这段岁月，七分释然，三分回忆。\n分手后我浑浑噩噩地过了小半年，因为机构打算扩大规模，打算开始接高中外包的艺术教育，我的本科学历有点不够了，老板人挺好的，没有和我明说，我自己辞职了。毕业的小半年，我就失业了。\n回乡、创业和夏j回来 失业在家，我避免不了地想大头的事。大头的事情对我而言是有点启发的，作为一个男人，这么浑浑噩噩确实不太像话，我想我是不是也应该做出点成绩出来呢？\n失业的事情还是没有瞒住我爸，我爸算是很开明的人，只是问我有什么打算，没有什么打算的话就回来吧，这几年家乡发展得挺好的，让我去他和夏叔的公司做事，我也没挣扎什么，就回去了。\n回去之后，就混了一个厂房的头头，里面大部分都是辍学在家出来打工的一些小年轻，年纪和我差不了多少。我一个月拿8000多，比我教小孩画画赚得多一点，其实具体也没什么要干的，就是往办公室一坐，财务把报表递来，看了没什么问题就让他往上交，上面要多少产量我催催工人。这种生活，是我以前所追求的，清闲，工资也不算少，但是总有一种不甘的感觉。果然，书上说得没错，爱一个人就会潜移默化地变成她的样子，我决定了，我想干点什么。\n我的家乡，是个不算大的县城，经济发展得很好，基础设施基本和那些一线城市差不了多少。我发现了一个问题，也是我幸运的地方，这个城市的文化教育很优秀，补习班很多，而像美术、音乐这些艺术教育的机构，除了那些高端的生活区，其他生活区很少有艺术教育机构，而且高中的艺术生教育基本都是外包给苏州、扬州这些地方的教育机构来教的。我把这件事告诉了我爸爸，他没有说什么。其实我知道，他不善言辞，自己对我的关心他不知道怎么表达。关于我创业这件事，他拨了一笔钱给我，让我放心地去干。\n事情进展得很顺利，政府那里托我爸的关系也是一路绿灯，我第一家很快就开起来了，在一个不算高端的小区附近，主要还是做小孩的生意。在一系列活动举办后，我的机构第一天的课就排满了。光课费就足足有好几万，这种成功，我始料未及。机构发展得很好，开业不到一年就已经接近回本了，我马不停蹄地开了第二家门店，反响也同样可观，最好的时候基本都是一课接着一课的，每个教室从早上到晚上都有人，那时候我23岁。\n事业发展得很顺利，年少得志的我又单身。夏叔，也就是夏j她爸，我爸的生意合伙人，他打算让我和夏j结婚，我爸自然也没什么意见。关于夏j这个女孩，我那时候的回忆还停留在高中那段痛苦的经历，她的样子我已经记不清了，脑海里只是回想着初中放学和她玩游戏的欢声笑语。\n夏j这个女孩对我很好，不夸张地说，等于救了我的命。高中刘胖子自杀，我陷入了极度的自责，脾气变得反复无常，而父亲又经常要出去工作，是她一直陪着我，陪我度过了那一段令人恶心的时光。\n那天夏叔组局，请我们爷俩吃饭，说夏j和她妈从美国回来了。忘了说她妈了，她妈是个很恐怖的女人，控制欲极强，对于夏j必须要是她言听计从的，我初中那会，就经常听到她妈打夏j，然后夏j捂着屁股躲到我家里来。那次饭局在夏j她妈阴沉的脸上，和夏j的缺席，就这样散了。\n饭局散了之后，我独自坐在广场的长椅上，我很享受这样，坐在长椅上看着老年人跳着广场舞，小孩追着闹着，带小孩的大人们欢快地交谈着，那会广场舞放着《千千阙歌》，我看大妈们跳舞正看得入神，一个人熟悉的人影混在了大妈之中，夏j推掉了饭局，一个人躲在这里跳广场舞，她跳得很沉迷，不过很明显她没有这方面的天赋，把旁边的大爷都带得节奏乱了。我呆呆地看着，似乎她也发现了我，广场的灯照着所有人，人来人往，她转过了身，看着我，一动不动，一旁的人在奋力地舞着，伴随着歌曲进入高潮，她踩着来日纵使千千阙歌的音符，一步一步地走向了我，亮过今晚月亮。\n见面的第一句就是让我请她去吃饭，我被她拉着去了一个大排档，她倒是没客气，把店里的菜基本都点了一遍。我看着她吃，一边听她滔滔不绝，说她在美国的奇闻趣事，光说还不够，她还要喝酒，喝着喝着，她又哭了，说她有神经病。我知道她的酒量基本是一瓶啤酒就晕，我在制止她喝酒的时候，看到了她手臂上有一道一道的刀痕，她倒也没避嫌，直接就是露了出来，炫耀地说到她是个神经病，哈哈哈。\n之后，她说她确诊了双相，情绪很不稳定。之前说了，她妈妈是个控制欲极其强的人，去美国这件事属于是她妈妈一个人的决定，所以说她的这个病有她妈的一半。\n估计8u们不知道这种病，简单来说就是情绪极其的不稳定，可能上一秒还在嘻嘻哈哈的，下一秒就要拿刀捅你的那种，而且这种病发作基本还伴随着抑郁，晚上睡不着，思维很活跃，会经常因为一些小事动了想死的念头，客观地说比抑郁症更危险。\n夏j回来后一个人住在老房子里，她的爸爸每天很少回家，后来才知道是出轨了。当然那时候的夏j刚回来是不知道的这件事的，她妈是那种很经典的父母，对于孩子，只要她自己觉得不愧对于她，那她就觉得自己是个好妈妈。尽管她知道她的女儿得了这个病，但是她并没有给予相应的关怀，在她的认知里这种病就是矫情，所以夏j一个人呆在老房子里，就在我家的楼下。\n那天晚上，我奶奶在前几天走了，和我爸处理完一些事情后，我独自回到了家。我奶奶很疼我，那天心情不算好，所以很晚才睡觉。夏j在半夜发了很长的话，大概就是说很对不起我各种各种的，我很不理解地发了一个问号，在这之后她就没回我了。我越想越奇怪，便下楼去找她，发现她明显在哭，而且餐桌上还有一把触目惊心的刀。在经历了一段沉默后，我说我睡不着了，想找她出去玩玩。她有点慌乱，在简单地整理后，在车上我问她想去哪，她就这样在副驾驶睡着了。\n从那之后，我开始查关于她这个病的一些事，看了很多关于这个病的帖子，一查才知道几乎所有的人都在说，这个病很麻烦，假如不是什么至亲的人，还是远离的好。我很犹豫，因为这个病似乎是会伴随终身，不过想起以前她对我的好，这次也该换我来救她了。\n事情进展得很不顺利，她似乎把我当成了一个依靠。她会随便花钱去买一些没用又很贵的东西，会半夜敲我家的门让我陪她打游戏，更要命的是还差点被骗到传销。最恐怖的是，她怕变胖，她私自停药，导致了很严重的躯体化症状，那段时间我深刻意识到了这玩意有多恐怖。\n她是属于二型双相，经常性的抑郁和间接的躁狂，我能做的很少，只是陪着她做那些她想一出是一出的事情。好在老天开眼，发病从一周三四次减少到一周一次，到最后几个月都没有发病，她脑子也清醒了不少。一年多的时间，在一次复查后，医生说可以停药了，她的这个病终于算是告一段落了。\n她在我机构找了一个助教的工作，对于她，我有点说不清楚自己的感情。我这个人有点贱，对于自己的付出从来不奢求回报，这也是大头看不惯我的原因之一，所以在她有意无意地表达自己的意思的时候，尽管我看出来了，却还是本能地闪躲。我还是时不时地想着大头，尽管夏j一直从来在我的心里，没离开过。\n夏j在回来后就一直住在我家楼下，她生病那会也好，痊愈了也好，我的晚饭一直都是她来安排的，那时候我因为害怕伤害到她，所以每次无论多晚我都尽量回来吃。这用她的话来说就是，小女子无言以报，唯有一饭送给公子。\n她在我的机构工作了没几个月就说不干了，想自己去找个工作，我自然同意了。又想起她被传销骗的经历，提了一路，让她小心。她忽然就扑向了我，把我按在了墙上，我很慌，看着她的脸，很红，眼神里透着一丝愤怒，还夹杂着一丝泪花。她有点抖地说：\n“我爸说让我和你结婚，你爸也同意了，你怎么跟个死人一样？一次都不和我提？”\n“是不是我有神经病你嫌弃我？”\n“我问过我爸妈了，这不是遗传的，对孩子没影响。”\n然后她大声喊了我的名字。\n“我想和你结婚。”\n我被这突如其来的一幕吓到了，赶忙问她这是什么新型的神经病。她没好气地瞪着我，又说道：\n“我上高中的时候表白被你拒绝了，这次结婚你也拒绝，我现在就杀了你，然后说我有神经病。”\n我看着她认真的脸，问我自己做好结婚的准备了吗？我说到：\n“我们慢慢来好吗？”\n她看着我，沉默了很久，说到：\n“明天陪我去看电影。”\n我们俩就这样迷迷糊糊地确认了关系，我才意识到，她其实不是一个外表坚强、内心柔弱的女孩，而是一个本来就爱哭，善良的女孩在努力地变得坚强。她爸爸出轨的事情，在她妈回国没几天就发现了，她每次回她爸妈住的那套房子，她爸妈基本都是一见面就是吵，把家里砸得七零八落，而她也总是偷偷地躲在房间里哭。我因为害怕她旧病复发就打开房门关心一下她，而她就像小孩做了错事一样看着我。后来她想哭的时候就把房门锁住了，我问她为什么，她说：\n“眼泪是大人用来洗掉悲伤的，只有小孩才会大庭广众的哭以此来博取关心。”\n那一刻我才知道原来被逼着成长的小孩，不止我一个。\n父亲、日记和老家 20年，过年那会因为我爷爷奶奶全走了，所以那个年是我和我爸两个人过的。武汉传来了那个消息，我们这里也是火速封控，夏j和她爸妈回了无锡。那是我第一次这么长的时间和我爸呆在一起，认真的回想我们父子俩很少一起聊天。上学时他努力赚钱告诉我出了事情他来摆平，工作了他也在努力赚钱告诉我让我大胆地干，出了事情他来兜底。他好像一直在为我付出，自从和我妈妈离婚后到现在也没有再婚。他沉默寡言，小时候只想着留点家产给我。我好像从来没有和这一位已经50岁的老头谈谈他自己，谈谈我自己，一直在跑的我，什么时候忘记回头看看已经不能陪着你跑的他了呢？\n年后，我发现老头经常半夜起来，就坐在阳台的椅子上看着我小时候写作业的桌椅，外面微微的灯光照着他，照着他的光头和那张桌椅。他坐的位置就是小时候他辅导我作业的位置。窗外的光轻轻地洒在他的身上，他坐在那里像个雕塑。他好像真的变年轻了，走样的身材变得健硕，脸上没了皱纹，笑着骂着我这题都能错，厨房传来妈妈的烧菜的声音，妈妈走出来笑着招呼我们吃饭，而我把笔一扔，大喊大叫地走向妈妈。\n人生啊，有太多不得已了，不得已地来，不得已地走，生死听天，来去由命，码的真没意思。\n我在他车的后备箱里发现了一张报告单，临床诊断一栏赫然地写着骨癌。我早该知道的，吃饭那会就应该发现他的饭量变得小得多。我拿着这张报告单说让他和我去医院，他淡然地说没得治了，是晚期。我大吼到没得治也要治。那一刻我觉得我好无助。\n癌细胞扩散得很快，医院已经回绝了。回去的路上，他还说打算我结婚了之后再告诉我的。\n接着就是封控过了几天再封控，父亲每天都在肉眼可见地衰老，因为疫情的原因，所以我和他住在了医院。看着他眼神变得混沌，看着他疼得满床打滚，我只能看着，责怪自己还未能尽孝。\n原来顶天立地的爸爸，也是个小孩。\n那天我照常出去买饭，被打电话告知他已经走了，都没有陪着他失去呼吸。\n推开了那扇门，那扇隔绝了生死的门，我的父亲，就这样静静地躺在病床上。原本嘈杂的仪器显得那么安静，整个房间久违的宁静。医生走进来，没有任何情感地通报了他的死亡。在结清一些杂乱的费用，和拿到那一张薄薄的死亡证明之后，我搬了个椅子，悄悄地放在他的旁边，似乎他还在睡觉一样，我不忍心惊扰到他的酣眠，静静地看着这个与我十分相似的男人。这是我第一次面对至亲的死亡，心情意外地平静，也许我应该痛哭一下？不过我似乎哭不出来。我想着用以前和父亲的点点滴滴来回忆让自己变得悲伤起来，我惊奇地发现，我竟忘得一干二净，只是坐在椅子上，看着父亲苍白的脸，微微喘息。\n火葬完之后，就是守夜。老家父亲几个儿时的玩伴也来了，我和他们打着牌，静静地听着他们说父亲小时候的事。有一个个子有点矮的叔叔，说着说着就哭了，我也很想哭，但是，说来奇怪，眼泪似乎不想出来。\n整理他遗物的时候发现除了留给我的大把的钱，和一本日记，就没有任何属于他的东西了。他的爱好、喜欢吃什么我一概不知。我翻开了那本日记。\n日记摘录 2008年3月4日\n奥运的票真难搞啊，搞到了小崽子会不会开心点呢，他刚好过生日，那几天带他去北京转转吧。\n2008年5月9日\n下午要去给李校送礼，崽子能不能上实验就看这个死老头了。\n2009年3月11日\n崽子这几天不开心，还老是朝我吼，会不会是叛逆期到了。\n2010年10月12日\n气死我了这几个b，崽子欺负我家小孩，真想抽他们。\n2010年11月21日\n又要去求爷爷拜奶奶地要账了，崽子这几天感觉心情挺好的，会不会和老夏女儿谈上了。\n2011年12月10日\n生意真难做啊，天天一堆破事。\n2012年4月4日\n出差遇到了xxx，算了，崽子估计不喜欢有后妈。\n2013年3月19日\n崽子躲在房间里不出来，我该怎么说呢，查网上感觉都不靠谱，好急啊，我对他的关心太少了。\n2014年4月19日\n崽子马上高考了，加油啊，考不上倒也无所谓，你爸给你铺路。\n崽子去南京了，第一次一个人出门，到现在也不知道打个电话给我。\n听说崽子谈恋爱了，还是小学同学，哈哈，问他要照片还不给。\n崽子马上毕业了，随他去吧，给他介绍工作又不乐意。\n这几天浑身不得劲啊，崽子和夏家那个好上了，真想抱孙子啊。\n真想看看崽子结婚啊，真想看看崽子的孩子是男孩是女孩啊，不知道还能撑到那个时候吗，我要把一些资产卖了，给崽子留一笔钱，崽子的结婚钱，儿媳的坐月子钱，孩子的奶粉钱，我孙子还是孙女的学费。\n崽子啊，爸爸好想你啊，安心不了啊，你胆子这么小，爸爸真放心不下。\n崽子啊，不知道你能不能看到这个日记，看得到的话，爸爸求求你，遇到什么事情都不要放弃自己，你才二十多岁啊，我不在了，一定要活得开心，遇到事情了，能让让别人就让让别人，我不在了，出了事，你没有谁来护着你了。\n崽子啊，你说在那边爸爸还能看得见你嘛？\n爸爸的老家在农村。那一觉睡得很沉，谁也没有梦到，第二天一早我就醒了，起床，看着空荡荡的房子，我终于意识到这个世界，我已经没有亲人了。我麻木地嘲笑着自己，然后简单洗漱了一下，推开了大门，一阵风迎面而来，阳光刺入了我的眼睛直通心脏，盛开的云，滑过麦田，随风肆意地往前方。田里已经有农民开始了劳作，邻居的奶奶早早就起来了，看到了我，招呼我来她家吃早饭。我有了留在这里安静地渡过一辈子的想法，这个哺育我父亲的小村庄，我从来没有认真地了解过，就像我从来没有认真地了解过我的父亲一样。\n奶奶家是一栋比较老的平房，据爸爸所说，已经有七八十年的历史。家门口的小道旁就是广阔的麦田，房子静静地立在那里，旁边长满了油菜花，后面是一条河，与其说河，不如说是一条大型的溪流，因为河的水很浅但却很清，有一个很长的木头做的桥搭在河上。河道两旁长满了树，走上桥，总是会有一股清凉的风。河道很长，爸爸说这条河的尽头是海，我小时候一直不信，海是咸的，而这水没味。爸爸说这是殊途同归，但是它和海一样的是，也同样一眼望不到尽头。自从回来后，我很喜欢偷偷来到河边，偷偷坐在桥上，似乎有人会制止我，说河边危险一样，然后看着那存在又不存在的河的尽头，什么也不想，就这样吹着风，发着呆。\n自从爷爷奶奶走后，房子里已经很久没住人了，令人纳闷的是，他们生前种下的大白菜、青菜，和房子两旁的油菜花长得很好，似乎一直有人打理。房子并不算大，有两层，一楼是厨房、会客厅和一个供着菩萨的大堂屋，二楼则是睡觉的地方。来时的第一天我花了很大的力气把屋子上下全都打扫了一下，打扫得很仔细。我还发现了一把用木头做的刀，做得很粗拙，刀柄上刻着一行字“陈xx之刀”。我拿起了这把木刀，轻轻地擦去了上面的灰尘，小心翼翼地挥动着，突然，紧紧地抓着刀，冲出门去，以极快的速度跑向油菜花田，朝着油菜花群狠狠地砍去，一颗又一颗的油菜花倒下了，我像个发疯的武士，木刀在我剧烈的挥砍下，因为岁月，断了。我没了力气，跪坐在泥地上，泪流满面……似乎又有了力气，抓起坏了的刀，朝着周围没断的油菜花砸去，我哭得无声，又怕没有哭的声音爸爸注意不到我在哭，便站了起来，朝天，用生平最大的音量，颤抖地喊道：\n“爸爸，你不够意思，你真他妈的不够意思。”\n我在想，当父亲走出时间的那一刻开始，当我亲手给父亲下葬的那一刻开始，当我看见一件衣服很适合他穿的时候却发现他已经不在了的那一刻开始，当夕阳落西山，我独自回到家翻着他日记想哭却哭不出来那一刻开始，我心里的那一片虚空，该用什么填满，我好像真的欠他太多了，他却觉得是他欠我太多。\n我有呆在父亲的老家好几天。那里似乎是一个世外桃源，疫情对这里没有什么影响，邻里很关照我，隔壁的奶奶对我很好。那几天，我经常在这个奶奶家吃饭，每天早上八点准时起来，沿着田走，村里有很多老人，都会招呼我到家坐坐，听他们讲起我爸爸小时候的事，日子过得很慢，也很平静。\n夏j留下来了 我越来越想在这里呆上一辈子，直到有一天夏j来了，她带着一个大大的粉色行李箱，就这样出现在我面前。\n“你怎么知道这里的？”\n“你上学那会说过，进入xx村直走，到头左拐，第三家就是你奶奶家。”\n“你来干什么？”\n“无锡就这天才解除了风控。”\n“我知道。”\n“嗯，我来晚了吗？”\n她总是这样，像第一波春雨过后的微风，轻轻地吹化了寒冬，抚摸着我的冻疮，在盛夏来临之际悄然退场。\n她就这样住了进来，给我父亲上了一炷香，问我：\n“你打算在这里呆多长时间。”\n我迟疑了，说到。\n“一辈子。”\n她看着我，嘿嘿一笑。\n“明天和我去趟城里，拿衣服，带的衣服不够一辈子，你呢？你带的衣服够一辈子吗？”\n“我不知道。”\n“回头记得拉个网络，热水器都是坏的，你这几天不洗澡的吗，还是洗的冷水澡？呆这里机构的事你没法管了，你找人转手，我爸妈那里我等会说，你应该也有存款，我也有不少钱，我们在这里开个小卖铺，你会种地不？种地的事情我不干，我负责你的饮食，一些家务活，其他的事情你别让我做，不然我就回去了。”\n她在那里说了很多，吃住行，以后的孩子在哪上学。她的未来里，每一句都有我。\n有人溺于三生桥下清湖，也有人溺于过往，我不该溺于过往，生为死，死为生，我涓滴自己的一生所汇成的河流，最终还是会流向大海，和其他河流汇聚，途径大河弯弯，小溪潺潺，总有一天，会在那里和兄弟笑骂一辈子的荒唐，总有一天家人会重新摸着我的头，心疼道一路上辛苦了，也总有一天我可以大胆地哭，放心地笑，眼泪和海水去构成下一个我，再去看那人间，总有一天，是的，总有一天。。。。。。\n第二天我们就领了证，坐在车上，她拿着那本证书，一下拍在了我的头上，说：\n“现在老娘就是你的亲人啦。”\n我真没出息，眼泪没有憋住，夏j坐在副驾驶上，摸着我的头，什么也没说。\n婚礼与收束 接下来就是准备婚礼，那时候已经全面放开了，我的机构经历了一波亏损，关掉了两个门店，从第一个门店开始，重新做起。\n我们是爱的产物，是生死间瞭望的灯塔，是无数次日落升起的瞬间，亦是在虚无中突破重重阻碍所诞生的奇迹。我想，我不该这么消极，前进也好，后退也罢，只要面朝前方，那就是向前。\n婚礼选了个好日子，台下坐了很多人，我妈妈来了，作为我的家属，在离开我和我爹之后，她和一个扬州的叔叔结了婚，而且生了一对双胞胎。见了面，她变得好老，而她摸了摸我的脸，眼含热泪地说了句：\n“长大了。”\n夏叔牵着夏j进场的时候，那是我一生都无法忘记的画面，洁白的婚纱，庄严的音乐，纯净的灯光，所有美好，所有风景都穿透了我的每一寸肌肤，照向了夏j。当我从夏叔手上牵起她的手的那一刻，她抬眼望着我的那一刻，我说出我愿意的那一刻，笑眼盈盈，漫漫年华，从此只有死别，没有生离。\n27岁，我结婚了。\n之后的事情就没什么好说的了，我和夏j很幸福，机构因为以前积累的一些口碑，也在慢慢地好转。\n谨以此贴，献给我那不完美的三十年。\n岁月慢慢悠长，千里人生路，不问苍茫，只教生死淡然，不负期许，问自己，何须叹离殇？\n岁月源远流长，万里悲秋，道不尽，多少佳人叹情伤，问自己，不负一人，不做多情郎！\n岁月漫漫远兮，道阻且难，生离死别，多少伤心事，笑问上苍，活一世，荒唐又何妨？\n岁月推着我们前进，慢慢走，莫回头，慢慢走，莫回头。。。。。。\n","permalink":"https://june6699.github.io/posts/%E8%B4%B4%E5%90%A7%E4%BD%99%E5%8D%8E/","summary":"\u003cp\u003e作者链接：\u003ca href=\"https://tieba.baidu.com/p/9101254039?share=9105\u0026amp;fr=sharewise\u0026amp;see_lz=0\u0026amp;share_from=post\u0026amp;sfc=copy\u0026amp;client_type=2\u0026amp;client_version=12.75.1.0\u0026amp;st=1775807032\u0026amp;is_video=false\u0026amp;unique=875A00D83703C121D0207B0BBDE740CA\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e百度贴吧\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/images/%e8%b4%b4%e5%90%a7%e4%bd%99%e5%8d%8e/1.jpg\" alt=\"1\" width=\"1264\" height=\"882\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch2 id=\"三十岁的开头\"\u003e三十岁的开头\u003c/h2\u003e\n\u003cp\u003e今天是我的30岁生日捏，现在是24号的0点，牢。\u003c/p\u003e\n\u003cp\u003e躺在床上睡不着，回想着这30年的人生，很好奇，满嘴喷分的8u们过着什么样的人生呢。\u003c/p\u003e","tags":["生活","生活/文章"],"title":"《三十岁生日帖》整理"},{"content":"LiMCA：单细胞三维基因组与基因表达联合测量揭示嗅觉受体选择背后的动态增强子连接 1. 文章信息 标题： Simultaneous single-cell three-dimensional genome and gene expression profiling uncovers dynamic enhancer connectivity underlying olfactory receptor choice 中文题目可写为： 单细胞三维基因组与基因表达联合测量揭示嗅觉受体选择背后的动态增强子连接 作者： Honggui Wu, Jiankun Zhang, Fanchong Jian, Jinxin Phaedo Chen, Yinghui Zheng, Longzhi Tan, X. Sunney Xie 年份： 2024 期刊： Nature Methods 21: 974-982 DOI / 链接： https://doi.org/10.1038/s41592-024-02239-0 本地 PDF： /root/.openclaw/workspace/skills/bioinfo-singlecell/reports/article-explainers/pdf/simultaneous-single-cell-3d-genome-gene-expression-olfactory-receptor-choice.pdf 2. 一句话总述 这篇文章最重要的贡献，是提出了高灵敏度单细胞联合测量方法 LiMCA，并用它证明嗅觉受体基因的“单神经元只选一个受体”过程，并不是一次性完成的，而是伴随增强子可及性和三维连接逐步重排的分阶段竞争过程。\n3. 研究背景 3.1 这篇文章要解决什么问题 嗅觉受体神经元有一个非常经典、也非常难解释的规则，叫做“one neuron-one receptor”，也就是一个成熟神经元最终只表达一个嗅觉受体基因。但是在发育早期，前体细胞其实会短暂表达多个嗅觉受体基因，之后才慢慢收敛到单一受体。问题就在于，这个“从多到一”的选择过程究竟是如何发生的。\n过去大家已经知道，嗅觉受体基因与增强子之间存在复杂的三维相互作用，而且跨染色体增强子聚集体对最终的单受体表达很重要。但真正缺的，是来自同一个单细胞的、同时包含三维基因组结构和基因表达的信息。没有这一层，我们就很难回答“哪个受体在什么阶段先被激活”“增强子在什么阶段参与竞争”“三维连接和转录到底是谁先变化”这些问题。\n3.2 之前的方法缺什么 作者在引言里明确点名了旧方法的两个问题。第一类是成像法，虽然直观，但能覆盖的基因组位点和转录本数量都有限，缺少真正全基因组尺度的视野。第二类是测序法，尤其是之前发表的 HiRES，虽然已经迈出了单细胞 Hi-C 与 RNA 联测的一步，但灵敏度仍有限，且对低输入样本不够友好，还只捕获转录本的 3\u0026rsquo; 端。\n对嗅觉受体这种系统来说，这个限制尤其致命，因为它存在大量截短转录本和非功能性转录本。如果只有 3\u0026rsquo; 端信息，很容易把“看起来像表达”误判成“真的激活了某个功能性嗅觉受体基因”。所以这篇文章要解决的，不只是“再做一个联合测量方法”，而是要做一个足够高灵敏度、能区分真正受体表达、还能在低输入样本中稳定工作的联合方法。\n3.3 为什么这件事重要 这件事的重要性有两层。对技术层面来说，能在同一个单细胞里同时看到三维结构和全长转录信息，本身就是理解结构-功能关系的关键升级。对生物学层面来说，嗅觉受体选择是单细胞命运决定中非常漂亮的一类模型问题，它把增强子、染色质可及性、跨染色体连接和转录竞争都压缩在了一个很清晰的系统里。\n如果这篇文章讲清楚了 OR 基因如何从“多基因短暂激活”走向“单基因稳定表达”，那它对理解单细胞层面的基因调控竞争、增强子选择、三维基因组重排都会有很高的参考价值。\n4. 核心结论 作者提出了 LiMCA，能够在同一单细胞中高灵敏度地联合测量三维基因组结构和全长转录组。 LiMCA 在接触数和检测到的基因数上都明显优于之前的 HiRES，并且能用于低输入样本。 作者联合 LiMCA 与 METATAC，构建了发育中嗅觉感觉神经元的多组学图谱。 嗅觉受体增强子和受体基因在早期分化阶段可及性最高，这为多受体短暂激活创造了条件。 OR 基因选择不是一步到位，而是经历“多基因激活 -\u0026gt; 竞争性沉默 -\u0026gt; 单一受体确定”三个阶段。 在多基因激活早期，更多是同染色体增强子先帮助受体基因启动；到了后续竞争阶段，占优的 OR 往往能获得更多增强子连接。 最终被选中的 OR 并不一定处于最大的增强子聚集体里，这修正了之前的一些推测。 5. 正文主线讲解 5.1 作者首先提出了一个比 HiRES 更灵敏的联合测量方法：LiMCA 这篇文章的第一步，是先证明 LiMCA 在技术上确实比已有方案更适合研究单细胞结构-功能关系。作者的方法核心思路，是把同一个细胞的细胞核和细胞质物理分开，分别测量三维基因组和转录组。这样做的关键好处是，避免了旧方法在逆转录过程中损伤基因组 DNA、或者因为处理方式导致 RNA 检测灵敏度下降的问题。\n图 1 给出的就是这条技术主线。图 1a 先画出 LiMCA 的流程图，说明它如何在同一细胞里同时拿到 Hi-C 和全长 RNA 信息；图 1b 和图 1c 证明，LiMCA 的 ensemble Hi-C 与 bulk in situ Hi-C 在区室、TAD 乃至 loop 层面都高度一致；图 1d 则说明 RNA 部分和 bulk RNA-seq 也有很高的一致性。\n图注：Fig. 1 Development of LiMCA. 图 1 主要证明 LiMCA 在结构与表达两种模态上都能给出可靠、可复现的数据。\n作者进一步把 LiMCA 与 HiRES、Dip-C、Smart-seq2、10x 做了横向比较。结果很明确：LiMCA 检测到的接触数比 HiRES 高 2 到 5 倍，而且检测到的基因数也更高，同时还能提供全长转录本信息。这个点非常重要，因为后面关于 OR 基因选择的很多结论，都依赖作者能区分“真正的功能性 OR 表达”与“截短或非功能性转录”。\n所以图 1 这部分不是在炫技，而是在建立全文的可信前提：后面所有关于增强子、OR 基因竞争和三维连接的推断，必须先建立在“这套联测真的比以前看得更准”这个基础上。\n5.2 作者接着证明，LiMCA 不只是一项方法，还能直接读出结构与表达的对应关系 文章没有停留在“方法做成了”，而是马上问了一个更有生物学含义的问题：在单细胞尺度上，基因表达和三维位置到底有没有可解释的对应关系。\n作者在 GM12878 细胞中以 NFKB1 为例，把高表达和低表达细胞分开比较。结果看到，高表达 NFKB1 的细胞更频繁地与上游增强子发生接触。与此同时，表达基因在细胞核内部更密集，且在给定三维距离内拥有更多邻近基因。也就是说，LiMCA 不只是能同时测到两种模态，而是真的能在单细胞层面把结构状态和表达状态挂上钩。\n这一层结果虽然看起来像技术验证，但其实很关键，因为它说明作者后面去讨论 OR 基因和增强子的空间关系，并不是空想，而是建立在一个已经被单细胞案例支持的结构-表达联系框架上。\n5.3 作者用 LiMCA 与 METATAC 建立了发育中嗅觉感觉神经元的多组学图谱 在把方法站稳之后，文章真正进入了嗅觉系统。作者围绕小鼠主嗅上皮的发育过程，收集了多个时间点的单细胞，构建了包含三维基因组、基因表达和染色质可及性的多组学图谱。\n图 2 展示的是这部分工作的总览。图 2a 和 2b 先说明实验设计和各时间点采到的细胞数量。图 2c 给出 LiMCA 数据在 RNA 与 3D 结构两个空间中的嵌入结果，说明作者可以稳定分出非神经元、前体、未成熟 OSN 和成熟 OSN 等主要群体。图 2e 以后则引入 METATAC，把染色质可及性也拉进来，形成真正的多组学图谱。\n图注：Fig. 2 Multi-omics profiling of the developing OSNs at single-cell resolution. 图 2 把 LiMCA 与 METATAC 结合起来，建立了发育中 OSN 的多组学图谱。\n这张图最重要的生物学信息有三条。\n第一，作者确实恢复出了 OSN 发育的连续轨迹，从基底细胞、即时神经前体，到未成熟和成熟 OSN，轨迹是连续的。第二，已知的 OR 相关染色质重排特征也在这套数据中被完整重现，比如染色体间混合增加、OR-OR 相互作用增强、增强子-增强子互作增强。第三，作者不仅看到了已知增强子，还借助 METATAC 识别出新的候选 OR 增强子，并且发现这些增强子上的 Lhx2/Ebf 相关 motif 富集明显。\n更有意思的是，图 2i 到 2l 说明 OR 增强子和 OR 基因的可及性并不是在成熟阶段最高，反而是在较早的分化阶段达到高峰。也就是说，系统会先创造一个“很容易把多个 OR 都短暂点亮”的染色质环境，然后再慢慢进入竞争、沉默和单一选择阶段。这是全文后面所有“分阶段 OR 选择”模型的基础。\n5.4 作者提出：OR 基因选择是一个分阶段过程，而不是突然从 0 跳到 1 图 3 是这篇文章最核心的生物学结果。作者根据同一个细胞中的 OR 表达谱，把发育中的 OSN 分成三个阶段：\n多基因 OR 激活阶段 沉默阶段 单一 OR 确定阶段 这个划分很重要，因为它把“一个成熟神经元最后只表达一个 OR”这件事，拆成了一个动态竞争过程，而不是静态终点。\n图 3a 定义了这三个阶段。图 3b 说明，在最早的多基因激活阶段，很多被激活的 OR 基因附近已经能看到增强子，而且这些增强子主要还是同染色体增强子。也就是说，OR 启动的第一步并不依赖大型跨染色体增强子聚集体，局部 cis-enhancer 就已经足以让多个 OR 短暂启动。\n图注：Fig. 3 Stepwise OR determination observed with single-cell joint profiling of chromatin architecture and gene expression. 图 3 是全文最关键的一张图，直接提出了 OR 选择的“三阶段模型”。\n接下来作者看第二阶段，也就是“一个 OR 开始占优，其他 OR 逐步被压下去”的过程。图 3d 和图 3f 给出的信息非常清楚：在沉默阶段，占优的 OR 基因周围通常会比那些即将被沉默的 OR 关联到更多增强子。作者在 150 nm 和 300 nm 这两个尺度都看到了这种趋势。换句话说，谁能连上更多增强子，谁就更可能在竞争中赢下来。\n再往后到第三阶段，也就是单一 OR 最终确定阶段，作者原本想验证一个旧猜想：最终胜出的 OR 会不会一定处在最大的增强子聚集体里。结果图 3e 和图 3g 反而说明，这个猜想并不成立。最终选中的 OR 通常并不住在“最大”的增强子聚集体里。这个结果很重要，因为它修正了之前比较粗略的模型。真正关键的可能不是“最大聚集体”，而是“是否连接到活跃且有效的增强子网络”。\n所以图 3 真正讲清楚的是一个更细致的过程：先是 OR 基因和增强子在早期都高度开放，允许多个 OR 暂时启动；随后少数 OR 基因通过获得更多增强子连接而在竞争中占优；最后系统再收缩到单一 OR 稳定表达。这个模型比过去“最后只剩一个受体”那种静态描述丰富得多。\n5.5 作者最终把增强子可及性、三维连接和 OR 选择串成了一个统一模型 图 2 和图 3 合起来，文章最后得出的模型其实很漂亮。作者认为，嗅觉受体选择并不是某个受体基因突然“天选中签”，而是经过了一个被染色质环境精细塑形的动态过程。\n在 GBC 和早期前体阶段，Lhx2/Ebf 等转录因子先驱动 OR 增强子变得可及；随后系统进入一个高可及、高竞争的窗口，多个 OR 都有机会被短暂激活；再之后，部分 OR 通过获得更多增强子支持而成为“dominant OR”；最终染色质环境继续收缩，只留下一个真正被确定下来的 OR。\n这个模型的价值在于，它第一次把 OR 增强子的可及性变化、OR 基因的分阶段表达、以及 OR 与增强子之间的三维空间关系，放到了同一个单细胞框架里统一解释。\n6. 方法详细拆解 6.1 样本与实验设计 这篇文章的方法设计有两个核心目标。第一，要在同一个单细胞里同时测到三维基因组和基因表达。第二，要能用于低输入材料，并且在转录本信息上足够完整，能区分真正的功能性 OR 转录本。\n为此，作者设计了 LiMCA。和 HiRES 不同，LiMCA 的关键点在于物理上把同一个细胞的细胞核和细胞质分离。细胞核部分用于做 3D 基因组测量，细胞质部分用于做 RNA 测量。这样做避免了一个模态的处理过程破坏另一个模态的检测灵敏度。\n6.2 LiMCA 的核心实验步骤 从图 1a 和正文可以反推出这条实验主线：\n先分离同一细胞的细胞核和细胞质。 在细胞核部分做交联、酶切、连接等步骤，获得 Hi-C 型三维接触信息。 在细胞质部分进行逆转录和全长转录本建库，得到比只测 3\u0026rsquo; 端更完整的 RNA 信息。 最后把结构和表达在单细胞层面重新配对，形成 paired multi-omics 数据。 这套方案的关键优势是，不像旧方法那样在一个流程里互相牵制结构和表达检测，而是先物理分流，再在单细胞层面合流。\n6.3 为什么全长转录本信息在这里特别关键 这篇文章的研究对象是嗅觉受体基因。这个系统里有大量截短和非功能性转录本，如果只测 3\u0026rsquo; 端，很容易把“似乎有表达”误判成“真的激活了某个 OR”。而 LiMCA 提供的全长转录信息，正好解决了这个问题。\n作者在图 3 前面的正文里明确说，这一点是 LiMCA 相比 HiRES 的独特优势之一，因为它直接决定了作者后续能否准确判断某个 OR 处于“多基因激活”“沉默中”还是“最终选中”状态。\n6.4 METATAC 在这里承担了什么角色 LiMCA 负责把三维结构和表达联起来，但作者还需要第三层信息来解释“为什么某个增强子在这个阶段活跃”。这就是 METATAC 的作用。\n作者把 METATAC 和 droplet-based scRNA-seq 用在发育中的主嗅上皮，得到单细胞层面的染色质可及性和表达图谱。借助这套图谱，作者才能识别新的候选 OR 增强子，评估 Lhx2/Ebf motif 的富集，并沿发育轨迹观察 OR 增强子与 OR 基因可及性的动态变化。\n所以方法上真正的组合不是单独的 LiMCA，而是：\nLiMCA：结构 + 表达 METATAC：可及性 scRNA-seq：更稳的细胞类型和轨迹参考 6.5 计算分析主线 这篇文章的分析主线可以概括成六步。\n先验证 LiMCA 的结构和表达两种模态是否都可靠。 再建立发育中 OSN 的多组学图谱，恢复连续发育轨迹。 识别 OR 相关增强子，并分析其可及性与 motif 特征。 根据单细胞中的 OR 表达谱，把细胞分为多基因激活、沉默和单一确定三个阶段。 在每个阶段中比较 OR 与增强子的三维邻近关系，统计 cis / trans enhancer 的参与模式。 最后把增强子可及性、三维连接和 OR 表达模式整合成一个统一的机制模型。 6.6 相对旧方法的创新点 第一，LiMCA 在灵敏度上明显优于 HiRES。 第二，它保留了全长转录本信息，这对 OR 系统尤其关键。 第三，它能处理低输入样本，而不仅限于大量细胞。 第四，这篇文章不是只展示一个技术，而是把结构、表达和可及性三层信息联合起来讲清了一个动态发育过程。 6.7 潜在局限 这篇文章虽然把结构、表达和可及性串起来了，但功能因果验证仍然有限，很多结论依旧主要基于相关和时序推断。 关于“最终哪一个 OR 胜出”的机制，这篇文章已经显著推进了理解，但还没有把所有竞争因素完全拆开，例如转录因子网络、染色质重塑因子和反馈抑制机制之间的精确层级。 主文中的方法细节有限，真正要完全复现时，仍需要结合 online methods、补充材料和源码数据。 7. 这篇文章适合什么样的研究问题 7.1 适合直接借鉴的场景 如果你的问题是“一个细胞为什么最终只选一个调控对象”“增强子和目标基因之间的三维连接如何参与单细胞命运竞争”“染色质可及性变化和三维连接变化谁先介入”，这篇文章很值得借鉴。\n7.2 对你当前 skill 体系的启发 这篇 PDF 本身就说明，HiRES 更适合作为旧方法参考，而真正当前要讲的文章应该是 LiMCA 这篇。换句话说，references/articles/article1-hires-hic-rna-seq-linking-genome-structures.md 现在更像是背景参考，而不是默认输出目标。\n7.3 方法学上的启发 这篇文章最值得带走的，不只是 LiMCA 这个名字，而是它处理复杂单细胞问题的方式：先把多组学信息配准到同一个单细胞，再把轨迹、可及性、三维连接和表达按时间顺序串起来，最后才去谈机制。这个顺序非常值得学。\n8. 术语解释 LiMCA： Linking mRNA to Chromatin Architecture，作者提出的单细胞三维基因组与全长转录组联合测量方法。 METATAC： 作者使用的高分辨率单细胞染色质可及性测定方法，用于补足增强子活性信息。 OSN： olfactory sensory neuron，嗅觉感觉神经元。 OR： olfactory receptor，嗅觉受体基因。 cis-enhancer： 与目标基因位于同一条染色体上的增强子。 trans-enhancer： 与目标基因位于不同染色体上的增强子。 one neuron-one receptor： 一个成熟嗅觉神经元最终只稳定表达一个嗅觉受体基因的经典规则。 ","permalink":"https://june6699.github.io/posts/article2_limca_hic+rna_atac_openclaw/","summary":"\u003ch1 id=\"limca单细胞三维基因组与基因表达联合测量揭示嗅觉受体选择背后的动态增强子连接\"\u003eLiMCA：单细胞三维基因组与基因表达联合测量揭示嗅觉受体选择背后的动态增强子连接\u003c/h1\u003e\n\u003ch2 id=\"1-文章信息\"\u003e1. 文章信息\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e标题：\nSimultaneous single-cell three-dimensional genome and gene expression profiling uncovers dynamic enhancer connectivity underlying olfactory receptor choice\u003c/li\u003e\n\u003cli\u003e中文题目可写为：\n单细胞三维基因组与基因表达联合测量揭示嗅觉受体选择背后的动态增强子连接\u003c/li\u003e\n\u003cli\u003e作者：\nHonggui Wu, Jiankun Zhang, Fanchong Jian, Jinxin Phaedo Chen, Yinghui Zheng, Longzhi Tan, X. Sunney Xie\u003c/li\u003e\n\u003cli\u003e年份：\n2024\u003c/li\u003e\n\u003cli\u003e期刊：\n\u003cem\u003eNature Methods\u003c/em\u003e 21: 974-982\u003c/li\u003e\n\u003cli\u003eDOI / 链接：\n\u003ca href=\"https://doi.org/10.1038/s41592-024-02239-0\" target=\"_blank\" rel=\"noopener noreferrer\"\u003ehttps://doi.org/10.1038/s41592-024-02239-0\u003c/a\u003e\n\u003c/li\u003e\n\u003cli\u003e本地 PDF：\n\u003ccode\u003e/root/.openclaw/workspace/skills/bioinfo-singlecell/reports/article-explainers/pdf/simultaneous-single-cell-3d-genome-gene-expression-olfactory-receptor-choice.pdf\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2-一句话总述\"\u003e2. 一句话总述\u003c/h2\u003e\n\u003cp\u003e这篇文章最重要的贡献，是提出了高灵敏度单细胞联合测量方法 \u003ccode\u003eLiMCA\u003c/code\u003e，并用它证明嗅觉受体基因的“单神经元只选一个受体”过程，并不是一次性完成的，而是伴随增强子可及性和三维连接逐步重排的分阶段竞争过程。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/论文"],"title":"LiMCA单细胞三维基因组与基因表达联合测量解析嗅觉受体选择"},{"content":"0、一些链接 重要 文档手册：JavaScript 和 HTML DOM 参考手册 | 菜鸟教程 廖雪峰（本笔记来源）：廖雪峰 JavaScript教程 菜鸟教程：JavaScript 教程 | 菜鸟教程 1、标准对象 特别注意\nJavaScript的Date对象月份值从0开始，牢记0=1月，1=2月，2=3月，……，11=12月。\n2、JavaScript函数、对象与原型完整核心总结 2.1 函数与Object的本质关系 JS 遵循万物皆对象规则，函数本身就是一类特殊的 Object；普通对象只能挂载属性，函数既可以当对象挂载自定义属性，又能加 () 执行调用。 所有函数能调用 apply/call/bind，不是函数自身自带，而是靠原型链继承而来。 代码验证： // 函数是对象 function Student(name) { this.name = name; this.hello = function () { alert(\u0026#39;Hello, \u0026#39; + this.name + \u0026#39;!\u0026#39;); } } // 检测类型 console.log(typeof Student); // function console.log(Student instanceof Object); // true 函数属于Object 2.2 函数prototype属性本质 只有函数天生自带 prototype 显式属性，函数的 prototype 不是函数，就是一个普通Object对象。 函数默认的 prototype 对象自带 constructor 属性，默认指向构造函数自身。 代码验证： // prototype 是普通对象 console.log(typeof Student.prototype); // object // constructor 指向自己 console.log(Student.prototype.constructor === Student); // true 2.3 显式原型与隐式原型核心区别 显式原型 prototype：仅构造函数独有，作用是作为模板，给 new 出来的实例共享属性和方法。 隐式原型 proto：JS 所有东西都有（普通对象、实例、函数、数组），是引擎内置隐藏属性；作用是串联原型链，对象自身找不到属性时，顺着 __proto__ 向上逐级查找。 通用规则：任何对象的 __proto__ 永远指向创建它的构造函数的 prototype。 let obj = {}; console.log(obj.__proto__ === Object.prototype); // true let arr = []; console.log(arr.__proto__ === Array.prototype); // true 2.4 对象实例本身没有prototype的原因 设计定位：prototype 是构造函数（工厂） 的专属模具，用来统一给实例提供公共模板；而 new 出来的实例只是「产品」，只需要使用模具，不需要自己再拥有一个模具。 功能冗余：实例已经通过隐式原型 __proto__ 指向构造函数的 prototype，完全能实现继承；如果再给实例加 prototype 属性，毫无实际作用，还浪费内存。 代码验证实例无prototype： let xiaoming = new Student(\u0026#39;小明\u0026#39;); console.log(xiaoming.prototype); // undefined 实例没有prototype 2.5 构造函数、原型、实例三者关联 基于你写的 Student 构造函数与 xiaoming 实例，完整原型关系：\nStudent.prototype 是普通对象，constructor 指向 Student； 实例 xiaoming.__proto__ 直接指向 Student.prototype； xiaoming 自身没有 constructor，沿原型链向上查找，最终指向 Student。 let xiaoming = new Student(\u0026#39;小明\u0026#39;); console.log(xiaoming.__proto__ === Student.prototype); // true console.log(xiaoming.constructor === Student); // true // 实例可以正常访问属性和方法 console.log(xiaoming.name); // 小明 xiaoming.hello(); // 弹出 Hello, 小明! 补充：你代码里 this.hello 是绑定在每个实例自身，不是挂载在原型上，每个实例都会单独生成一份函数。\n2.6 apply/call/bind 的原型来源 apply、call、bind 这些方法，定义在 Function.prototype 上； 所有普通函数的隐式原型 __proto__ 都指向 Function.prototype，通过原型链继承，所以所有函数天生能调用这三个方法。 console.log(Student.__proto__ === Function.prototype); // true ","permalink":"https://june6699.github.io/posts/%E5%BB%96%E9%9B%AA%E5%B3%B0-javascript-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-2--%E5%AF%B9%E8%B1%A1/","summary":"\u003ch2 id=\"0一些链接\"\u003e0、一些链接\u003c/h2\u003e\n\u003cdiv class=\"callout callout-important\" data-callout=\"important\" role=\"note\" aria-label=\"重要\"\u003e\n  \u003cdiv class=\"callout-head\"\u003e\n    \u003cspan class=\"callout-icon\"\u003e\u003csvg viewBox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M8 10h8\"/\u003e\u003cpath d=\"M8 14h5\"/\u003e\u003cpath d=\"M6 19h8a4 4 0 0 0 4-4V9a4 4 0 0 0-4-4H10a4 4 0 0 0-4 4z\"/\u003e\u003cpath d=\"m6 19-2 2v-5\"/\u003e\u003c/svg\u003e\u003c/span\u003e\n    \u003cspan class=\"callout-title\"\u003e重要\u003c/span\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"callout-body\"\u003e\u003cp\u003e文档手册：\u003ca href=\"https://www.runoob.com/jsref/jsref-tutorial.html\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eJavaScript 和 HTML DOM 参考手册 | 菜鸟教程\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e廖雪峰（本笔记来源）：\u003ca href=\"https://liaoxuefeng.com/books/javascript\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e廖雪峰 JavaScript教程\u003c/a\u003e\n\u003c/p\u003e","tags":["技术","技术/前端","技术/前端/JavaScript"],"title":"JavaScript学习笔记：对象及面向对象编程"},{"content":"阅读说明：本文已按层级加入编号，格式为「一级标题：1、标题」「二级标题：1.1 标题」「三级标题：1.1.1 标题」，方便快速定位章节。\n1、问题现象 这次故障的表象很简单：在 WSL 里执行 openclaw tui，本地网关已经连上，模型也选到了 custom-api-vibelearning-top/gpt-5.4，但一发消息就直接报：\nHTTP 403: Your request was blocked. 从界面看，这个报错像是 “OpenClaw 不认这个 key” 或 “base URL 写错了”。但真正情况不是这样。\n这类错误要先分层看：\nopenclaw tui 连的是本地 gateway，不是直接连上游模型接口。 TUI 里显示 gateway connected | idle，说明本地网关本身是通的。 真正返回 403 的，往往是更后面的 provider 上游接口。 也就是说，403 出现在 OpenClaw 界面里，不代表问题一定在 OpenClaw 本体，很多时候只是 OpenClaw 把上游 API 的拒绝结果原样抛了出来。\n2、先讲清楚几个基础概念 2.1 OpenClaw 里的 Gateway 是什么 OpenClaw 的 gateway 可以理解成它在本机上的“统一入口”。TUI、agent、session 先连到本地 gateway，再由 gateway 按 provider 配置去访问真正的大模型接口。\n这次链路可以简化成下面这样：\nopenclaw tui -\u0026gt; ws://127.0.0.1:18789 -\u0026gt; OpenClaw gateway -\u0026gt; provider(baseUrl/apiKey/api) -\u0026gt; 上游 API 所以只要 TUI 能连上 gateway，就说明本地前半段通了，但后半段仍然可能因为 provider 配置、请求头、上游风控而失败。\n2.2 Proxy 是什么，为什么这里需要它 这里说的 proxy 不是浏览器里常见的“翻墙代理”，而是一个放在 OpenClaw 和上游 API 之间的“兼容代理”。\n它做的事情很少，但很关键：\n接收 OpenClaw 发出的 HTTP 请求。 保留原本的请求 body 和鉴权头。 只改写少数容易触发上游拦截的请求头。 再把请求转发到真正的上游接口。 这次真正有用的代理只有一个目的：把 OpenClaw 发出的 User-Agent: OpenAI/JS ... 改成一个不会被上游拦截的普通值。\n2.3 OpenAI 兼容接口、API Key 与 /v1/responses VibeLearning 这里走的是 OpenAI 兼容接口。OpenClaw provider 配成 api: openai-responses 时，核心就是向类似下面的地址发请求：\nPOST https://api.vibelearning.top/v1/responses Authorization: Bearer sk-xxxx Content-Type: application/json 请求体通常是 JSON，例如：\n{ \u0026#34;model\u0026#34;: \u0026#34;gpt-5.4\u0026#34;, \u0026#34;input\u0026#34;: \u0026#34;hello\u0026#34; } 返回体也是 JSON。和老一点的 chat/completions 不同，responses 风格一般会在 output 里放模型输出内容，客户端再从 output_text 或文本块里取最终文本。\n这里有两个排障要点：\nAPI key 只是鉴权材料，通常通过 Authorization: Bearer ... 传递。 即便 key 和 body 都是对的，上游仍然可能因为请求头、风控策略、User-Agent 或网关策略返回 403。 2.4 为什么“同一个 key，在别的工具里能通”仍然不能排除问题 很多人一看到 403 就先换 key。这当然值得试，但不能就此下结论。\n因为不同客户端发出去的请求，除了 key 和 body，还有很多差异：\nUser-Agent Accept Connection 是否走 SDK 是否带某些默认 header 只要上游风控针对的是其中某个 header，那么“同一个 key 在 curl 里能通、在 OpenClaw 里不通”就完全可能发生。\n3、这次 403 的真正根因 3.1 不是 key 问题 这次真正修好 403 的操作，并不是换 key。\n排查时可以确认两件事：\n只换 key 不能稳定解决问题。 同一个 key，在不同 User-Agent 下会出现完全不同的结果。 这说明问题不在“这个 key 本身一定无效”，而在“这个 key 搭配某种请求特征会被上游挡掉”。\n3.2 不是 baseUrl 写错了 如果是 baseUrl 明显写错，常见结果更像是：\n404 502 连接失败 路径不匹配 但这次并不是这样。/v1/responses 路由本身是对的，请求确实打到了上游，只是被上游拒绝了。\n3.3 也不是 /v1/responses 的 JSON body 本身有问题 这次最关键的定位动作，是拿同一个请求体做对比测试，只改 User-Agent。\n下面这两条命令就是定位核心。文中的 key 我已经脱敏，真正使用时请换成你自己的，若你的旧 key 曾出现在聊天记录、截图或仓库里，建议马上轮换。\n3.3.1 用普通 curl 风格的 User-Agent export VIBE_API_KEY=\u0026#39;sk-REPLACE_ME\u0026#39; curl -i \u0026#39;https://api.vibelearning.top/v1/responses\u0026#39; \\ -H \u0026#34;Authorization: Bearer ${VIBE_API_KEY}\u0026#34; \\ -H \u0026#39;Content-Type: application/json\u0026#39; \\ -H \u0026#39;User-Agent: curl/8.7.1\u0026#39; \\ -d \u0026#39;{\u0026#34;model\u0026#34;:\u0026#34;gpt-5.4\u0026#34;,\u0026#34;input\u0026#34;:\u0026#34;hello\u0026#34;}\u0026#39; 这类请求可以得到正常响应。\n3.3.2 只把 User-Agent 改成 OpenAI/JS export VIBE_API_KEY=\u0026#39;sk-REPLACE_ME\u0026#39; curl -i \u0026#39;https://api.vibelearning.top/v1/responses\u0026#39; \\ -H \u0026#34;Authorization: Bearer ${VIBE_API_KEY}\u0026#34; \\ -H \u0026#39;Content-Type: application/json\u0026#39; \\ -H \u0026#39;User-Agent: OpenAI/JS 6.26.0\u0026#39; \\ -d \u0026#39;{\u0026#34;model\u0026#34;:\u0026#34;gpt-5.4\u0026#34;,\u0026#34;input\u0026#34;:\u0026#34;hello\u0026#34;}\u0026#39; 这时就会返回 HTTP 403: Your request was blocked.\n3.4 最终定位到被上游拦截的是 User-Agent 到这里，结论就很清楚了：\n同一个 baseUrl 同一个 key 同一个 /v1/responses 同一个 JSON body 唯一差异只是 User-Agent 而结果一个是正常响应，一个是 403。\n所以这次 bug 的真正根因不是 OpenClaw 不会调接口，而是上游对 OpenAI/JS 6.26.0 这个 User-Agent 做了拦截或风控处理。\n这也是为什么“换 key”看起来像有时有效、有时无效，但始终不稳定。真正决定这次成败的变量，并不是 key，而是请求头。\n4、真正修好 403 的方案 4.1 方案总览 真正修好这次 403 的有效方案只有一个：\n如果你是通过 Windows 上的 v2rayN 给 WSL 提供代理网络，端口要以 v2rayN -\u0026gt; 参数设置 -\u0026gt; 本地混合监听端口 为准。我这台机器这里实际是 51888，所以下文示例统一按 51888 来写；如果你的环境不同，把文中的端口替换成你自己的即可。 代理把 OpenClaw 发来的请求原样转发到 https://api.vibelearning.top。 只有当请求头里出现 User-Agent: OpenAI/JS ... 时，把它改写成 curl/8.7.1。 再把 OpenClaw 的 provider baseUrl 改到 http://127.0.0.1:51888/v1。 链路变成这样：\nOpenClaw -\u0026gt; 本地 gateway -\u0026gt; http://127.0.0.1:51888/v1 -\u0026gt; 兼容代理改写 User-Agent -\u0026gt; https://api.vibelearning.top/v1 这个方案之所以稳，是因为它没有去碰 OpenClaw 安装目录里的 dist 文件，也没有硬改 SDK 行为，而是把兼容层独立放在用户目录里，更新 OpenClaw 时更不容易一起被覆盖。\n4.2 第一步：部署兼容代理 可直接下载的代理脚本在这里：\nopenclaw-vibelearning-proxy.py 如果想手动创建，也可以直接用下面这组命令：\nmkdir -p ~/.local/bin /tmp/openclaw cat \u0026gt; ~/.local/bin/openclaw-vibelearning-proxy.py \u0026lt;\u0026lt;\u0026#39;PY\u0026#39; #!/usr/bin/env python3 import json from pathlib import Path from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError UPSTREAM = \u0026#34;https://api.vibelearning.top\u0026#34; LOG_PATH = \u0026#34;/tmp/openclaw/vibelearning-proxy-log.jsonl\u0026#34; class ProxyHandler(BaseHTTPRequestHandler): protocol_version = \u0026#34;HTTP/1.1\u0026#34; def _write_log(self, payload): Path(LOG_PATH).parent.mkdir(parents=True, exist_ok=True) with open(LOG_PATH, \u0026#34;a\u0026#34;, encoding=\u0026#34;utf-8\u0026#34;) as f: f.write(json.dumps(payload, ensure_ascii=False) + \u0026#34;\\n\u0026#34;) def _handle(self): length = int(self.headers.get(\u0026#34;Content-Length\u0026#34;, \u0026#34;0\u0026#34;) or \u0026#34;0\u0026#34;) body = self.rfile.read(length) if length \u0026gt; 0 else b\u0026#34;\u0026#34; upstream_url = f\u0026#34;{UPSTREAM}{self.path}\u0026#34; headers = { k: v for k, v in self.headers.items() if k.lower() not in {\u0026#34;host\u0026#34;, \u0026#34;connection\u0026#34;, \u0026#34;proxy-connection\u0026#34;, \u0026#34;content-length\u0026#34;} } if headers.get(\u0026#34;User-Agent\u0026#34;, \u0026#34;\u0026#34;).startswith(\u0026#34;OpenAI/JS\u0026#34;): headers[\u0026#34;User-Agent\u0026#34;] = \u0026#34;curl/8.7.1\u0026#34; if headers.get(\u0026#34;user-agent\u0026#34;, \u0026#34;\u0026#34;).startswith(\u0026#34;OpenAI/JS\u0026#34;): headers[\u0026#34;user-agent\u0026#34;] = \u0026#34;curl/8.7.1\u0026#34; record = { \u0026#34;method\u0026#34;: self.command, \u0026#34;path\u0026#34;: self.path, \u0026#34;headers\u0026#34;: headers, \u0026#34;body_text\u0026#34;: body.decode(\u0026#34;utf-8\u0026#34;, errors=\u0026#34;replace\u0026#34;), } try: req = Request( upstream_url, data=body if self.command != \u0026#34;GET\u0026#34; else None, headers=headers, method=self.command, ) with urlopen(req, timeout=120) as resp: resp_body = resp.read() status = resp.status resp_headers = dict(resp.headers.items()) except HTTPError as e: resp_body = e.read() status = e.code resp_headers = dict(e.headers.items()) except URLError as e: msg = str(e).encode(\u0026#34;utf-8\u0026#34;, errors=\u0026#34;replace\u0026#34;) self.send_response(502) self.send_header(\u0026#34;Content-Type\u0026#34;, \u0026#34;text/plain; charset=utf-8\u0026#34;) self.send_header(\u0026#34;Content-Length\u0026#34;, str(len(msg))) self.end_headers() self.wfile.write(msg) record[\u0026#34;proxy_error\u0026#34;] = str(e) self._write_log(record) return record[\u0026#34;response_status\u0026#34;] = status record[\u0026#34;response_body_text\u0026#34;] = resp_body.decode(\u0026#34;utf-8\u0026#34;, errors=\u0026#34;replace\u0026#34;) self._write_log(record) self.send_response(status) hop_by_hop = { \u0026#34;transfer-encoding\u0026#34;, \u0026#34;connection\u0026#34;, \u0026#34;keep-alive\u0026#34;, \u0026#34;proxy-authenticate\u0026#34;, \u0026#34;proxy-authorization\u0026#34;, \u0026#34;te\u0026#34;, \u0026#34;trailers\u0026#34;, \u0026#34;upgrade\u0026#34;, } for key, value in resp_headers.items(): if key.lower() in hop_by_hop: continue self.send_header(key, value) self.send_header(\u0026#34;Content-Length\u0026#34;, str(len(resp_body))) self.end_headers() self.wfile.write(resp_body) def do_POST(self): self._handle() def do_GET(self): self._handle() def log_message(self, format, *args): return if __name__ == \u0026#34;__main__\u0026#34;: server = ThreadingHTTPServer((\u0026#34;127.0.0.1\u0026#34;, 51888), ProxyHandler) server.serve_forever() PY chmod +x ~/.local/bin/openclaw-vibelearning-proxy.py 这段脚本里真正决定修复是否成功的关键逻辑只有两行：\nif headers.get(\u0026#34;User-Agent\u0026#34;, \u0026#34;\u0026#34;).startswith(\u0026#34;OpenAI/JS\u0026#34;): headers[\u0026#34;User-Agent\u0026#34;] = \u0026#34;curl/8.7.1\u0026#34; 4.3 第二步：注册 systemd 用户服务 可下载的服务文件在这里：\nopenclaw-vibelearning-proxy.service 手动创建命令如下：\nmkdir -p ~/.config/systemd/user cat \u0026gt; ~/.config/systemd/user/openclaw-vibelearning-proxy.service \u0026lt;\u0026lt;\u0026#39;SERVICE\u0026#39; [Unit] Description=OpenClaw VibeLearning compatibility proxy After=network-online.target Wants=network-online.target [Service] Type=simple ExecStart=/usr/bin/python3 /root/.local/bin/openclaw-vibelearning-proxy.py Restart=always RestartSec=2 [Install] WantedBy=default.target SERVICE systemctl --user daemon-reload systemctl --user enable --now openclaw-vibelearning-proxy.service systemctl --user status openclaw-vibelearning-proxy.service 这里用用户级 systemd 的好处是：\n不需要把逻辑塞进 OpenClaw 包目录。 开机后能自动拉起。 OpenClaw 升级时，这个代理服务通常不会跟着消失。 4.4 第三步：把 OpenClaw provider 改走本地代理 真正需要改的不是上游地址本身，而是让 OpenClaw 不再直接打上游，而是先打到本地代理：\n原来: https://api.vibelearning.top/v1 现在: http://127.0.0.1:51888/v1 这次实际涉及的配置文件主要是：\n~/.openclaw/openclaw.json ~/.openclaw/agents/main/agent/models.json 下载版的脱敏配置片段在这里：\nopenclaw-provider-snippets.txt 如果不想手改 JSON，直接用我保存好的恢复脚本最快：\nopenclaw-vibelearning-403-quick-restore.sh 使用方法：\nexport VIBE_API_KEY=\u0026#39;sk-REPLACE_ME\u0026#39; bash ./openclaw-vibelearning-403-quick-restore.sh 如果你更想看配置应该改成什么样，最关键的 provider 片段是下面这样：\n{ \u0026#34;baseUrl\u0026#34;: \u0026#34;http://127.0.0.1:51888/v1\u0026#34;, \u0026#34;apiKey\u0026#34;: \u0026#34;sk-REPLACE_ME\u0026#34;, \u0026#34;api\u0026#34;: \u0026#34;openai-responses\u0026#34;, \u0026#34;models\u0026#34;: [ { \u0026#34;id\u0026#34;: \u0026#34;gpt-5.4\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;gpt-5.4 (Custom Provider)\u0026#34;, \u0026#34;reasoning\u0026#34;: false, \u0026#34;input\u0026#34;: [\u0026#34;text\u0026#34;], \u0026#34;cost\u0026#34;: { \u0026#34;input\u0026#34;: 0, \u0026#34;output\u0026#34;: 0, \u0026#34;cacheRead\u0026#34;: 0, \u0026#34;cacheWrite\u0026#34;: 0 }, \u0026#34;contextWindow\u0026#34;: 128000, \u0026#34;maxTokens\u0026#34;: 4096, \u0026#34;api\u0026#34;: \u0026#34;openai-responses\u0026#34; } ] } 真正起决定作用的是 baseUrl 从上游地址改成了本地代理地址。\n4.5 第四步：验证是否真的修好了 真正有意义的验证，不是看配置文件“像不像对了”，而是直接跑一次模型请求。\n先看服务状态：\nsystemctl --user status openclaw-vibelearning-proxy.service 再直接走 OpenClaw 的本地推理命令：\nopenclaw infer model run \\ --local \\ --model custom-api-vibelearning-top/gpt-5.4 \\ --prompt \u0026#34;hello\u0026#34; \\ --json 这次修复后的实际表现是：命令可以拿到正常模型输出，不再出现 HTTP 403: Your request was blocked.\n如果还想进一步确认代理确实接管了流量，可以看代理日志：\ntail -n 5 /tmp/openclaw/vibelearning-proxy-log.jsonl 5、可下载文件 为了避免下次排障时还得重新翻聊天记录，我把这次真正有用的文件单独存到了本文资源目录里：\n兼容代理脚本 openclaw-vibelearning-proxy.py systemd 服务文件 openclaw-vibelearning-proxy.service 一键恢复脚本 openclaw-vibelearning-403-quick-restore.sh 脱敏 provider 配置片段 openclaw-provider-snippets.txt 这些文件放在博客仓库的：\ncontent/posts/images/openclaw-vibelearning-403修复记录/ 这样 Hugo 站点可以直接给出下载链接，同时仓库里也保留了完整修复记录。\n6、OpenClaw 更新后如何快速恢复 6.1 哪些文件可能被覆盖 这次真正需要担心被覆盖的，主要是 OpenClaw 的用户配置：\n~/.openclaw/openclaw.json ~/.openclaw/agents/main/agent/models.json 相对不容易被覆盖的是：\n~/.local/bin/openclaw-vibelearning-proxy.py ~/.config/systemd/user/openclaw-vibelearning-proxy.service 所以正确思路不是去改 OpenClaw 安装目录里的 dist 文件，而是：\n把兼容逻辑放在用户目录。 把 provider 修复动作做成脚本。 每次更新后只重跑恢复脚本。 6.2 一键恢复命令 如果后面 OpenClaw 更新后又把 provider 配置改回去了，最快的恢复方式就是：\nexport VIBE_API_KEY=\u0026#39;sk-REPLACE_ME\u0026#39; bash openclaw-vibelearning-403-quick-restore.sh systemctl --user restart openclaw-vibelearning-proxy.service 然后再跑一次：\nopenclaw infer model run \\ --local \\ --model custom-api-vibelearning-top/gpt-5.4 \\ --prompt \u0026#34;hello\u0026#34; \\ --json 如果这一步通了，说明本次恢复已经完成。\n6.3 本博客里这些附件如何生效 这个博客是 Hugo 站点，文章附件采用的是：\ncontent/posts/images/\u0026lt;文章目录名\u0026gt;/ 正文里则用相对路径 ./images/... 链接。这个仓库已经配好了同步脚本，运行：\npython scripts/sync_images.py 就会把 content/posts/images/... 同步到 static/images/...。如果你直接在 Windows 下运行：\nrun_server.bat 脚本会自动先做图片同步，再启动本地 Hugo 预览服务。\n7、总结 这次 OpenClaw 的 HTTP 403: Your request was blocked.，真正根因不是 key、不是 baseUrl、也不是 responses body 写法，而是上游拦截了 OpenAI/JS 6.26.0 这个 User-Agent。\n真正有效的修复动作只有三步：\n在 WSL 里部署一个本地兼容代理。 把 OpenAI/JS 改写成不会被拦截的 User-Agent。 把 OpenClaw provider 的 baseUrl 改到本地代理。 如果你以后再遇到“同一个 key 在 curl 里能用，在 OpenClaw 里却是 403”这类问题，最快的排查顺序就是：\n先确认 gateway 是否正常连上。 再用同一个 key、同一个 body，只改 User-Agent 做对照实验。 一旦确认是 header 风控，就不要继续死磕换 key，而是直接上兼容代理。 最后补一句安全建议：如果 API key 曾经出现在聊天、终端回显、截图或仓库里，排障结束后最好主动轮换一次，别把“能跑起来”当成“已经安全”。\n8、openclaw-qqbot安装 项目地址：tencent-connect/openclaw-qqbot: qqbot APPID和key获取：QQ开放平台｜机器人列表 教程（看到创建机器人就可以回到我这个教程了）：手把手教你 OpenClaw 接入 QQ 机器人，让本地 AI 在 QQ 里听你指挥把本地 OpenClaw 接到一个「 - 掘金 从源码安装\ncd / source ~/.bashrc cd /data/softwares/openclaw-qqbot cd data/softwares git clone https://github.com/tencent-connect/openclaw-qqbot.git cd openclaw-qqbot bash ./scripts/upgrade-via-source.sh --appid {你的APPID} --secret {你的APPKey} 一些qqbot的skills安装\nopenclaw skills install rss-monitor openclaw skills install site-monitor openclaw skills install openclaw-github-assistant openclaw skills install browser-automation # 已经安装的 # site-monitor # openclaw-github-assistant # browser-automation openclaw skills update --all ","permalink":"https://june6699.github.io/posts/openclaw-vibelearning-403%E4%BF%AE%E5%A4%8D%E8%AE%B0%E5%BD%95/","summary":"\u003cp\u003e阅读说明：本文已按层级加入编号，格式为「一级标题：\u003ccode\u003e1、标题\u003c/code\u003e」「二级标题：\u003ccode\u003e1.1 标题\u003c/code\u003e」「三级标题：\u003ccode\u003e1.1.1 标题\u003c/code\u003e」，方便快速定位章节。\u003c/p\u003e\n\u003ch2 id=\"1问题现象\"\u003e1、问题现象\u003c/h2\u003e\n\u003cp\u003e这次故障的表象很简单：在 WSL 里执行 \u003ccode\u003eopenclaw tui\u003c/code\u003e，本地网关已经连上，模型也选到了 \u003ccode\u003ecustom-api-vibelearning-top/gpt-5.4\u003c/code\u003e，但一发消息就直接报：\u003c/p\u003e","tags":["技术","技术/AI","技术/AI/工具"],"title":"OpenClaw 连接 VibeLearning 出现 HTTP 403 的真正修复记录"},{"content":"0、一些链接 重要 文档手册：JavaScript 和 HTML DOM 参考手册 | 菜鸟教程 廖雪峰（本笔记来源）：廖雪峰 JavaScript教程 菜鸟教程：JavaScript 教程 | 菜鸟教程 1、快速入门阶段 https://liaoxuefeng.com/books/javascript/quick-start/index.html 1.1 循环 for循环里面需要用 ;，而非,； for循环对于array的循环，一般用\u0026lt; arr.length而非\u0026lt;= arr.length，因为length不存在0，但是index存在0（与python一样）； let arr = [\u0026#39;Apple\u0026#39;, \u0026#39;Google\u0026#39;, \u0026#39;Microsoft\u0026#39;]; let i, x; for (i=0; i\u0026lt;arr.length; i++) { x = arr[i]; console.log(x); } 1.2 对象 对象里面需要用,隔开各个属性，尾部用;结尾； let xiaohong = { name: \u0026#39;小红\u0026#39;, \u0026#39;middle-school\u0026#39;: \u0026#39;No.1 Middle School\u0026#39; }; 1.3 Map和Set、Iterable 1.3.1 Map Map可以用来快速使用两个array创建一个object let names = [\u0026#39;Michael\u0026#39;, \u0026#39;Bob\u0026#39;, \u0026#39;Tracy\u0026#39;]; let scores = [95, 75, 85]; // 方法零 let m = new Map([[\u0026#39;Michael\u0026#39;, 95], [\u0026#39;Bob\u0026#39;, 75], [\u0026#39;Tracy\u0026#39;, 85]]); m.get(\u0026#39;Michael\u0026#39;); // 95 // 方法一 let m = new Map(); for (let i = 0; i \u0026lt; names.length; i++) { m.set(names[i], scores[i]); } // 方法二 let m = new Map(names.map((name, index) =\u0026gt; [name, scores[index]])); console.log(m.get(\u0026#39;Michael\u0026#39;)); // 输出 95 console.log(m); // 打印完整Map（可选） 方法二讲解\nnames.map() = 遍历 names 数组里的每一个名字，循环处理，并拿到index 012 它会自动循环 3 次（因为 names 有 3 个元素）\nnames.map((name, index) =\u0026gt; [name, scores[index]]) 会自动生成一个二维数组（正好是 Map 需要的格式）：\n[ [\u0026#39;Michael\u0026#39;, 95], [\u0026#39;Bob\u0026#39;, 75], [\u0026#39;Tracy\u0026#39;, 85] ] 1.3.2 Set Set类似python元组，自动过滤重复元素 let s = new Set([1, 2, 3, 3, \u0026#39;3\u0026#39;]); s; // Set {1, 2, 3, \u0026#34;3\u0026#34;} 遍历Array可以采用下标循环，遍历Map和Set就无法使用下标。为了统一集合类型，ES6标准引入了新的iterable类型，Array、Map和Set都属于iterable类型。 let a = [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;]; let s = new Set([\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;]); let m = new Map([[1, \u0026#39;x\u0026#39;], [2, \u0026#39;y\u0026#39;], [3, \u0026#39;z\u0026#39;]]); for (let x of a) { // 遍历Array console.log(x); } for (let x of s) { // 遍历Set console.log(x); } for (let x of m) { // 遍历Map console.log(x[0] + \u0026#39;=\u0026#39; + x[1]); } for ... of循环它只循环集合本身的元素： let a = [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;]; a.name = \u0026#39;Hello\u0026#39;; for (let x of a) { console.log(x); // \u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39; } 1.3.3 forEach 更好的方式是直接使用iterable内置的forEach方法，它接收一个函数，每次迭代就自动回调该函数 let a = [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;]; a.forEach(function (element, index, array) { // element: 指向当前元素的值 // index: 指向当前索引 // array: 指向Array对象本身 console.log(`${element}, index = ${index}`); }); A, index = 0 B, index = 1 C, index = 2 // Set与Array类似，但Set没有索引，因此回调函数的前两个参数都是元素本身： let s = new Set([\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;]); s.forEach(function (element, sameElement, set) { console.log(element); }); // Map的回调函数参数依次为value、key和map本身： let m = new Map([[1, \u0026#39;x\u0026#39;], [2, \u0026#39;y\u0026#39;], [3, \u0026#39;z\u0026#39;]]); m.forEach(function (value, key, map) { console.log(value); }); 2、函数 JavaScript函数允许接收任意个参数，而且只会用到\u0026lt;= arguments.length个数的参数，如下面的abs(10,-100)只会用到10，二忽视-100，剩下的这些不要的参数我们放到了rest里面去。\nfunction abs(x) { if (x \u0026gt;= 0) { return x; } else { return -x; } } 2.1 arguments JavaScript里面的函数，自动带一个参数arguments，且永远指向当前函数的调用者传入的所有参数，这也说明了即使函数不定义任何参数，还是可以拿到参数的值。\nfunction foo(x) { if (arguments.length === 0) { return 0; } else { console.log(\u0026#39;x = \u0026#39; + x); // 10 } for (let i=0; i\u0026lt;arguments.length; i++) { console.log(\u0026#39;arg \u0026#39; + i + \u0026#39; = \u0026#39; + arguments[i]); // 10, 20, 30 } } foo(10, 20, 30); foo(); x = 10 arg 0 = 10 arg 1 = 20 arg 2 = 30 而且在ES6中，可以用...rest来指代这些被忽略的剩余参数，因为他们也有未竟的作用，注意在使用的时候应该用rest而非...rest。\nfunction foo(a, b, ...rest) { console.log(\u0026#39;a = \u0026#39; + a); console.log(\u0026#39;b = \u0026#39; + b); console.log(rest); } foo(1, 2, 3, 4, 5); // a = 1 // b = 2 // Array [ 3, 4, 5 ] 2.2 return的坑 JavaScript引擎有一个在行末自动添加分号的机制，这可能让你栽到return语句的一个大坑：\nfunction foo() { return { name: \u0026#39;foo\u0026#39; }; } foo(); // { name: \u0026#39;foo\u0026#39; } 如果把return语句拆成两行：\nfunction foo() { return { name: \u0026#39;foo\u0026#39; }; } foo(); // undefined 要小心了，由于JavaScript引擎在行末自动添加分号的机制，上面的代码实际上变成了：\nfunction foo() { return; // 自动添加了分号，相当于return undefined; { name: \u0026#39;foo\u0026#39; }; // 这行语句已经没法执行到了 } 所以正确的多行写法是：\nfunction foo() { return { // 这里不会自动加分号，因为{表示语句尚未结束 name: \u0026#39;foo\u0026#39; }; } 2.3 变量提升 JavaScript的函数定义有个特点，它会先扫描整个函数体的语句，把所有用var申明的变量“提升”到函数顶部：\nfunction foo() { var x = \u0026#39;Hello, \u0026#39; + y; console.log(x); var y = \u0026#39;Bob\u0026#39;; } foo(); // Hello, undefined 虽然是strict模式，但语句var x = 'Hello, ' + y;并不报错，原因是变量y在稍后申明了。但是console.log显示Hello, undefined，说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明，但不会提升变量y的赋值。\n如果后续不声明y，会报错。\n由于JavaScript的这一怪异的“特性”，我们在函数内部定义变量时，请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var申明函数内部用到的所有变量。\n2.4 全局变量 全局变量都绑定在window身上的。\nfunction foo() { alert(\u0026#39;foo\u0026#39;); } foo(); // 直接调用foo() window.foo(); // 通过window.foo()调用 2.5 局部作用域 由于JavaScript的变量作用域实际上是函数内部，我们在for循环等语句块中是无法定义具有局部作用域的变量的，但是改成ES6中的let就可以做到，for循环里面的let变量在外部无法访问。\nfunction foo() { for (var i=0; i\u0026lt;100; i++) { // for (let i=0; i\u0026lt;100; i++) { // } i += 100; // 仍然可以引用变量i } 2.6 解构赋值 2.6.1 array let [x, [y, z]] = [\u0026#39;hello\u0026#39;, [\u0026#39;JavaScript\u0026#39;, \u0026#39;ES6\u0026#39;]]; x; // \u0026#39;hello\u0026#39; y; // \u0026#39;JavaScript\u0026#39; z; // \u0026#39;ES6\u0026#39; 2.6.2 对象 如果需要从一个对象中取出若干属性，也可以使用解构赋值，便于快速获取对象的指定属性：\nlet person = { name: \u0026#39;小明\u0026#39;, age: 20, gender: \u0026#39;male\u0026#39;, passport: \u0026#39;G-12345678\u0026#39;, school: \u0026#39;No.4 middle school\u0026#39; }; let {name, age, passport} = person; // name, age, passport分别被赋值为对应属性: console.log(`name = ${name}, age = ${age}, passport = ${passport}`); // name = 小明, age = 20, passport = G-12345678 果要使用的变量名和属性名不一致，可以用下面的语法获取\nlet {name, passport:id} = person; name; // \u0026#39;小明\u0026#39; id; // \u0026#39;G-12345678\u0026#39; // 注意: passport不是变量，而是为了让变量id获得passport属性: passport; // Uncaught ReferenceError: passport is not defined 如果person对象没有single属性，默认赋值为true\nlet {name, single=true} = person; 有些时候，如果变量已经被声明了，再次赋值的时候，正确的写法也会报语法错误\n// 声明变量: let x, y; {x, y} = { name: \u0026#39;小明\u0026#39;, x: 100, y: 200}; // 语法错误: Uncaught SyntaxError: Unexpected token = 这是因为JavaScript引擎把{开头的语句当作了块处理，于是=不再合法。解决方法是用小括号括起来：\nlet x, y; ({x, y} = { name: \u0026#39;小明\u0026#39;, x: 100, y: 200}); 2.7 this? that? 2.7.1 古老方法 在一个方法内部，this是一个特殊变量，它始终指向当前对象，也就是xiaoming这个变量。所以，this.birth可以拿到xiaoming的birth属性。\nlet xiaoming = { name: \u0026#39;小明\u0026#39;, birth: 1990, age: getAge = function () { let y = new Date().getFullYear(); return y - this.birth; } }; console.log(xiaoming.age); // function xiaoming.age() console.log(xiaoming.age()); // 今年调用是36,明年调用就变成37了 // 但是直接用getAge会爆粗，因为他的this没来 如果对象内部属性指向一个函数，且函数内部使用了this，此时如果从外部去获取这个对象里面的这个属性（函数），会报错，因为那个函数里面使用的this指向那个对象，你在外部调用就指向了window了！\n而且，对象属性里面函数如果嵌套了一个函数，嵌套函数里面用this是拿不到这个对象的，而是指向window，除非提前用that捕获这个对象，然后通过内部函数可以访问外部变量，外部函数不能访问内部变量的特性，从而让嵌套函数内的this重新指向该对象，即that。\n\u0026#39;use strict\u0026#39;; let xiaoming = { name: \u0026#39;小明\u0026#39;, birth: 1990, age: function () { let that = this; // 在方法内部一开始就捕获this function getAgeFromBirth() { let y = new Date().getFullYear(); return y - that.birth; // 用that而不是this } return getAgeFromBirth(); } }; xiaoming.age(); // 25 2.7.2 apply 可以用apply改变this的指向对象，它接收两个参数，第一个参数就是需要绑定的this变量，第二个参数是Array，表示函数本身的参数。\nfunction getAge() { let y = new Date().getFullYear(); return y - this.birth; } let xiaoming = { name: \u0026#39;小明\u0026#39;, birth: 1990, age: getAge }; console.log(xiaoming.age()); // 25 console.log(getAge.apply(xiaoming, [])); // 25, this指向xiaoming, 参数为空 2.7.3 call 类似apply，区别在于：\napply()把参数打包成Array再传入； call()把参数按顺序传入。 比如调用Math.max(3, 5, 4)，分别用apply()和call()实现如下：\nMath.max.apply(null, [3, 5, 4]); // 5 Math.max.call(null, 3, 5, 4); // 5 对普通函数调用，我们通常把this绑定为null\n2.7.4 装饰器 JavaScript的所有对象都是动态的，即使内置的函数，我们也可以重新指向新的函数。\n\u0026#39;use strict\u0026#39;; let count = 0; let oldParseInt = parseInt; // 保存原函数 window.parseInt = function () { count += 1; return oldParseInt.apply(null, arguments); // 调用原函数 }; // 测试: parseInt(\u0026#39;10\u0026#39;); parseInt(\u0026#39;20\u0026#39;); parseInt(\u0026#39;30\u0026#39;); console.log(\u0026#39;count = \u0026#39; + count); // 3 2.8 高阶函数 JavaScript的函数其实都指向某个变量。既然变量可以指向函数，函数的参数能接收变量，那么一个函数就可以接收另一个函数作为参数，这种函数就称之为高阶函数。\n2.8.1 map/reduce 如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clusters ”，你就能大概明白map/reduce的概念。\nMapReduce 就是： 把超级大的数据，先拆开来并行算（Map），再把结果汇总到一起（Reduce）\n假如你有 100 亿行日志，要统计：\n每个单词出现多少次 每个IP访问了多少次 每个商品卖了多少 但问题来了：\n数据怎么切分？ 机器之间怎么传数据？ 某台机器挂了怎么办？ 结果怎么合到一起？ 经典例子：统计单词次数（WordCount）\nMap（映射） 把一大段文本，拆成很多小片段，丢给很多机器并行处理。每台机器做一件简单的事，遇到一个词，就输出 (单词, 1)，比如一句话：\u0026quot;I love JS I love MapReduce\u0026quot;，map 之后输出：\n(I, 1) (love, 1) (JS, 1) (I, 1) (love, 1) (MapReduce, 1) Shuffle（洗牌，系统自动做） 系统自动把相同 key 的数据，分到同一台机器。比如所有 I 放一起，所有 love 放一起：\nI: [1, 1] love: [1, 1] JS: [1] MapReduce: [1] Reduce（归约） 每台机器拿到一组相同 key 的数据，做聚合，把一堆 1 加起来。\nI: 1+1 = 2 love: 1+1 = 2 JS: 1 MapReduce: 1 JS array.map()：逐个处理元素，输出新数组 → 对应分布式 Map\nJS array.reduce()：把一堆值聚合成一个结果 → 对应分布式 Reduce\nGoogle 那篇论文，就是把这个简单思路，放大到几千台机器的大数据场景。\nlet arr = [1, 3, 5, 7, 9]; arr.reduce(function (x, y) { return x * 10 + y; }); // 13579 一个作业：字符串转数字\nfunction string2int(s) { let res = []; return s.split(\u0026#34;\u0026#34;).reduce(function(first, second) { return first * 10 + second * 1; }, 0); } s=\u0026#34;12345\u0026#34;; console.log(string2int(s)); // 12345 // 测试: if (string2int(\u0026#39;0\u0026#39;) === 0 \u0026amp;\u0026amp; string2int(\u0026#39;12345\u0026#39;) === 12345 \u0026amp;\u0026amp; string2int(\u0026#39;12300\u0026#39;) === 12300) { if (string2int.toString().indexOf(\u0026#39;parseInt\u0026#39;) !== -1) { console.log(\u0026#39;请勿使用parseInt()!\u0026#39;); } else if (string2int.toString().indexOf(\u0026#39;Number\u0026#39;) !== -1) { console.log(\u0026#39;请勿使用Number()!\u0026#39;); } else { console.log(\u0026#39;测试通过!\u0026#39;); } } else { console.log(\u0026#39;测试失败!\u0026#39;); } 2.9 map与parseInt 2.9.1. 错误代码 let arr = [\u0026#39;1\u0026#39;, \u0026#39;2\u0026#39;, \u0026#39;3\u0026#39;]; let r; r = arr.map(parseInt); console.log(r); [1, NaN, NaN] 2.9.2 核心错误原因分析 2.9.2.1 map 回调函数的传参规则 map 遍历数组时，会自动向回调函数传递3个参数：\n当前元素的值 当前元素的索引 原数组本身 2.9.2.2 parseInt 函数的参数规则 parseInt 是原生转换函数，接收两个必填参数：\n待转换的字符串 基数（进制数，如10代表十进制、2代表二进制） 2.9.2.3 逐次执行过程拆解 arr.map(parseInt) 等价于把索引当成进制传给 parseInt，执行流程：\nparseInt('1', 0)：基数0默认按十进制解析 → 结果 1 parseInt('2', 1)：基数1为无效进制 → 结果 NaN parseInt('3', 2)：基数2（二进制），但3不是有效二进制数 → 结果 NaN 2.9.3 正确使用方法 1. 显式指定十进制调用 parseInt 通过箭头函数包裹，固定进制为10，屏蔽索引干扰：\nlet arr = [\u0026#39;1\u0026#39;, \u0026#39;2\u0026#39;, \u0026#39;3\u0026#39;]; let r = arr.map(x =\u0026gt; parseInt(x, 10)); console.log(r); // [1, 2, 3] 2. 直接使用 Number 函数（推荐） Number 函数只接收1个参数，不受 map 索引影响，更简洁：\nlet arr = [\u0026#39;1\u0026#39;, \u0026#39;2\u0026#39;, \u0026#39;3\u0026#39;]; let r = arr.map(Number); console.log(r); // [1, 2, 3] 禁止直接用 arr.map(parseInt)，会因索引被当作进制导致转换失败 用 parseInt 必须通过箭头函数手动传参+指定十进制 简单字符串转数字，优先用 arr.map(Number)，无参数陷阱 2.10 filter filter只能在数组上用。\n和map()类似，Array的filter()也接收一个函数。和map()不同的是，filter()把传入的函数依次作用于每个元素，然后根据返回值是true还是false决定保留还是丢弃该元素。\n所以iilter需要的函数里面必须返回的是true或者false值以供判断。\n2.10.1 去空字符串 把一个Array中的空字符串删掉，可以这么写：\nlet arr = [\u0026#39;A\u0026#39;, \u0026#39;\u0026#39;, \u0026#39;B\u0026#39;, null, undefined, \u0026#39;C\u0026#39;, \u0026#39; \u0026#39;]; let r = arr.filter(function (s) { return s \u0026amp;\u0026amp; s.trim(); // 注意：IE9以下的版本没有trim()方法 }); r; // [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;] trim() 方法用于删除字符串的头尾空白符，空白符包括：空格、制表符 tab、换行符等其他空白符等。\ntrim() 方法不会改变原始字符串。\ntrim() 方法不适用于 null, undefined, Number 类型。\n2.10.2 去重复元素 利用filter，可以巧妙地去除Array的重复元素：\nlet r, arr = [\u0026#39;apple\u0026#39;, \u0026#39;strawberry\u0026#39;, \u0026#39;banana\u0026#39;, \u0026#39;pear\u0026#39;, \u0026#39;apple\u0026#39;, \u0026#39;orange\u0026#39;, \u0026#39;orange\u0026#39;, \u0026#39;strawberry\u0026#39;]; r = arr.filter(function (element, index, self) { return self.indexOf(element) === index; }); console.log(r); 函数中的参数element来自每次对arr的遍历，index是这个遍历拿到的参数在arr的索引（当前索引），self指代arr本身。 尽管arr遍历只能拿到一个参数，但是index、self这些是自己出来的，所以不会保参数未定义的的错误。 但是这只是对于数组array有的，对于对象这种没有索引的，他是没用的。 indexOf可以拿到该元素在参数（此处是self，即arr）里面的第一次出现的位置。 2.10.3 非要用filter处理对象 const obj = { name: \u0026#34;xujun\u0026#34;, age: 15, school: \u0026#34;SICAU\u0026#34;, null: false, }; // obj --\u0026gt; array const objToArray = Object.entries(obj); objToArray.filter(function (element, index, self) { console.log(`元素: ${element}，索引: ${index}，原数组:`, self); // 注意self在模版字符串外面 return element[1]; // 注意这里必须加索引，不然每次的element是一个数组，如[\u0026#39;null\u0026#39;, false]，他是true的 }); console.log(obj); 2.10.4 找素数 function get_primes(arr) { const result = arr.filter(function (x) { if (x === 2) { return true; //2 是素数 } else if (x === 1) { return false; // 1 不是素数 } const max = Math.sqrt(x); // 用当前数x的平方根，不是数组最大值！ for (let i = 2; i \u0026lt;= max; i++) { // i从2开始 //for (let i = 2; i * i \u0026lt;= x; i++) { 评论区看到的，这个方便 if (x % i === 0) { // 取模判断整除（最标准） return false; // 能整除 → 不是质数，直接过滤 } } return true; // 循环结束都没整除 → 是质数，保留 }); return result; // 返回筛选后的质数数组 } let x, r, arr = []; for (x = 1; x \u0026lt; 100; x++) { arr.push(x); } r = get_primes(arr); if (r.toString() === [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97].toString()) { console.log(\u0026#39;测试通过!\u0026#39;); } else { console.log(\u0026#39;测试失败: \u0026#39; + r.toString()); } 2.11 sort Array的sort()方法默认把所有元素先转换为String再排序。\n注意风险 奇怪的结果：\n'10'排在'2'的前面，因为字符'1'比字符'2'的ASCII码小。 apple在Google后面（确实如此，但是顺序是实力从强到弱还是从弱到强？） [\u0026#39;Google\u0026#39;, \u0026#39;apple\u0026#39;, \u0026#39;Microsoft\u0026#39;].sort(); // [\u0026#39;Google\u0026#39;, \u0026#39;Microsoft\u0026#34;, \u0026#39;apple\u0026#39;] [10, 20, 1, 2].sort(); // [1, 10, 2, 20] 注意 最后友情提示，sort()方法会直接对Array进行修改，它返回的结果仍是当前Array：\nlet a1 = [\u0026#39;B\u0026#39;, \u0026#39;A\u0026#39;, \u0026#39;C\u0026#39;]; let a2 = a1.sort(); a1; // [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;] a2; // [\u0026#39;A\u0026#39;, \u0026#39;B\u0026#39;, \u0026#39;C\u0026#39;] a1 === a2; // true, a1和a2是同一对象 2.12 forEach forEach()和map()类似，它也把每个元素依次作用于传入的函数，但不会返回新的数组。forEach()常用于遍历数组，因此，传入的函数不需要返回值：\nlet arr = [\u0026#39;Apple\u0026#39;, \u0026#39;pear\u0026#39;, \u0026#39;orange\u0026#39;]; arr.forEach(x=\u0026gt;console.log(x)); // 依次打印每个元素 2.13 闭包函数 Closure 高阶函数：将函数作为参数\n闭包函数：将函数作为返回值，可以就可以让他不会立刻执行，只有再次调用才会执行。\nfunction lazy_sum(arr) { let sum = function () { return arr.reduce(function (x, y) { return x + y; }); } return sum; } let f = lazy_sum([1, 2, 3, 4, 5]); // function sum() 重要 返回闭包时牢记的一点就是：返回函数不要引用任何循环变量，或者后续会发生变化的变量。\n因为这种闭包的返回函数是最后执行的，他每次指向的循环变量是最后一次循环的那个变量，而非循环中的变量。\n错误示范（这里面的i都是3：\nfunction count() { let arr = []; for (var i=1; i\u0026lt;=3; i++) { arr.push(function () { return i * i; }); } return arr; } let results = count(); let [f1, f2, f3] = results; f1(); // 16 f2(); // 16 f3(); // 16 正确示范方法一： 把i参数传给函数，然后把这个参数保存在闭包里面，而且这里使用了一个立即执行的函数语法\n(function (x) { return x * x; })(3); // 9 function count() { let arr = []; for (var i=1; i\u0026lt;=3; i++) { arr.push((function (n) { return function () { return n * n; } })(i)); } return arr; } let [f1, f2, f3] = count(); f1(); // 1 f2(); // 4 f3(); // 9 正确示范方法二： 跟错误示范里面差别在var和let\n循环声明 作用域 闭包捕获 f1() f2() f3() var i 函数作用域（共用） 同一个 i 16 16 16 let i 块级作用域（独立） 独立的 i 1 4 9 function count() { let arr = []; for (let i=1; i\u0026lt;=3; i++) { arr.push(function () { return i * i; }); } return arr; } let [f1, f2, f3] = count(); f1(); // 16 2.14 箭头函数 (x, y, ...rest) =\u0026gt; { let i, sum = x + y; for (i=0; i\u0026lt;rest.length; i++) { sum += rest[i]; } return sum; } 箭头函数看上去是匿名函数的一种简写，但实际上，箭头函数和匿名函数有个明显的区别：箭头函数内部的this是词法作用域，由上下文确定。\n回顾前面的例子 ，由于JavaScript函数对this绑定的错误处理，下面的例子无法得到预期结果：\nlet obj = { birth: 1990, getAge: function () { let b = this.birth; // 1990 let fn = function () { return new Date().getFullYear() - this.birth; // this指向window或undefined }; return fn(); } }; 现在，箭头函数完全修复了this的指向，this总是指向词法作用域，也就是外层调用者obj：\nlet obj = { birth: 1990, getAge: function () { let b = this.birth; // 1990 let fn = () =\u0026gt; new Date().getFullYear() - this.birth; // this指向obj对象 return fn(); } }; obj.getAge(); // 25 重要 对象的普通方法（外层函数） → this 指向 调用它的对象（obj） 嵌套的普通函数（内部显式函数） → 单独执行时，this 丢失绑定 → 指向 window / undefined 嵌套的箭头函数 → 没有自己的 this，直接继承外层的 this → 指向 obj 2.15 标签函数 标签函数和普通函数的定义区别仅仅在于参数,它接收的参数是 JS 引擎自动传入的 [静态文本数组, 插值1, 插值2, ...]。\n如果我们想对数据库进行修改，完全可以定义一个标签函数如下：\nfunction update(strings, ...exps) { let sql = strings.join(\u0026#39;?\u0026#39;); // 执行数据库更新 // TODO: } 函数调用可以简化为带标签的模板字符串：\nlet id = 123; let age = 21; let score = \u0026#39;A\u0026#39;; update`UPDATE users SET age=${age}, score=${score} WHERE id=${id}`; 2.16 生成器 生成器（generator）是ES6标准引入的新的数据类型。一个生成器看上去像一个函数，但可以返回多次。\ngenerator跟函数很像，定义如下：\n注意多出的*号），并且，除了return语句，还可以用yield返回多次。\nfunction* foo(x) { yield x + 1; yield x + 2; return x + 3; } ","permalink":"https://june6699.github.io/posts/%E5%BB%96%E9%9B%AA%E5%B3%B0-javascript-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-1--%E5%85%A5%E9%97%A8+%E5%87%BD%E6%95%B0/","summary":"\u003ch2 id=\"0一些链接\"\u003e0、一些链接\u003c/h2\u003e\n\u003cdiv class=\"callout callout-important\" data-callout=\"important\" role=\"note\" aria-label=\"重要\"\u003e\n  \u003cdiv class=\"callout-head\"\u003e\n    \u003cspan class=\"callout-icon\"\u003e\u003csvg viewBox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M8 10h8\"/\u003e\u003cpath d=\"M8 14h5\"/\u003e\u003cpath d=\"M6 19h8a4 4 0 0 0 4-4V9a4 4 0 0 0-4-4H10a4 4 0 0 0-4 4z\"/\u003e\u003cpath d=\"m6 19-2 2v-5\"/\u003e\u003c/svg\u003e\u003c/span\u003e\n    \u003cspan class=\"callout-title\"\u003e重要\u003c/span\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"callout-body\"\u003e\u003cp\u003e文档手册：\u003ca href=\"https://www.runoob.com/jsref/jsref-tutorial.html\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eJavaScript 和 HTML DOM 参考手册 | 菜鸟教程\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e廖雪峰（本笔记来源）：\u003ca href=\"https://liaoxuefeng.com/books/javascript\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e廖雪峰 JavaScript教程\u003c/a\u003e\n\u003c/p\u003e","tags":["技术","技术/前端","技术/前端/JavaScript"],"title":"JavaScript学习笔记：入门+函数"},{"content":"🚀 使用 CC Switch 配置共享 API Key 完整指南 重要 这只是针对于vibe-coding供应商提供的codex API使用的教程，其他更加官方的站点如ClaudeCode、OpenAI-codex这些，教程更多，此处就不讲了。\n站长教程：使用文档 · VibeLearning 这套流程的核心逻辑是：让 CC Switch 在后台做“系统环境变量劫持”，把本来要发给官方服务器的请求，自动转接给群主的代理服务器（并附上群主买单的 API Key）。\n开源工具出处：\nCC Switch 源码与下载地址：https://github.com/farion1231/cc-switch 第一步：安装终端 AI 工具 群主分享的是用来调 OpenAI 大模型的 Key，你需要先在电脑上全局安装 Codex 的命令行工具（确保已安装 Node.js）。 打开你的 Windows 命令提示符（CMD），运行：\nnpm install -g @openai/codex 第二步：在 CC Switch 中配置“中转站” 打开 CC Switch 软件，点击添加新的供应商配置。 应用类型选择 Codex。 填写核心参数： API 端点 (Base URL)：https://api.vibelearning.top/v1 (注意：Codex 必须带 /v1 后缀) API 令牌 (API Key)：填入群主分享的 sk- 开头的密钥。 保存配置，并点击让该卡片处于 “使用中”（打勾状态）。 (此时，CC Switch 已经默默把这俩参数写进你 Windows 的系统环境变量里了。) 第三步：进入你的真实工作目录（关键！） 不要直接在默认的用户目录（~）下启动工具，否则 AI 会找不到你要改的代码文件。\n关闭之前打开的所有黑框框（确保 CMD 能重新读取刚被 CC Switch 修改的环境变量）。 打开一个全新的 CMD 窗口。 使用 cd 命令，切换到你真正要干活的文件夹。比如你的某个单细胞数据分析目录，或是 Jekyll 博客的根目录： cd D:\\MyProjects\\Bioinformatics\\scRNA_Analysis 第四步：唤醒 AI 开始干活 在切好目录的 CMD 中，直接输入启动命令：\ncodex 敲下回车后，耐心等待几分钟让它在后台构建沙盒（Sandbox）。一旦显示完成，你就可以直接用自然语言吩咐它去读取你目录下的 R 脚本或 Python 文件帮你写代码和 Debug 了。\n💡 避坑与常识补充 关于查余额：手里只有 sk- 开头的 Key 是无法查余额的，在终端里输入 /status 只能看到你的 Token 消耗。用量查询需要站长的“访问令牌 (Access Token)”，如果站长没发，那就放开手脚直接用，直到终端报错提示没钱为止。 关于切换模型：在 Codex 交互界面里输入 /model 即可切换系统支持的其他模型（如 gpt-5.4）。 关于断开：在终端里输入 /exit 可以安全关闭 AI 的沙盒环境，不会影响你的本地代码。 第五步：配置用量查询方式 上图中的访问令牌不是API-key，而是在个人设置——安全设置——系统访问令牌中获取，如下图。\n而用户ID是一个整数，猜测应该是注册的顺序。\n配置完成后，在CC Switch中即可查询用量，类似网站里面的数据看板。\n","permalink":"https://june6699.github.io/posts/%E9%85%8D%E7%BD%AE-cc_switch-%E5%8F%8A%E5%85%B6api/","summary":"\u003ch3 id=\"-使用-cc-switch-配置共享-api-key-完整指南\"\u003e🚀 使用 CC Switch 配置共享 API Key 完整指南\u003c/h3\u003e\n\u003cdiv class=\"callout callout-important\" data-callout=\"important\" role=\"note\" aria-label=\"重要\"\u003e\n  \u003cdiv class=\"callout-head\"\u003e\n    \u003cspan class=\"callout-icon\"\u003e\u003csvg viewBox=\"0 0 24 24\" aria-hidden=\"true\"\u003e\u003cpath d=\"M8 10h8\"/\u003e\u003cpath d=\"M8 14h5\"/\u003e\u003cpath d=\"M6 19h8a4 4 0 0 0 4-4V9a4 4 0 0 0-4-4H10a4 4 0 0 0-4 4z\"/\u003e\u003cpath d=\"m6 19-2 2v-5\"/\u003e\u003c/svg\u003e\u003c/span\u003e\n    \u003cspan class=\"callout-title\"\u003e重要\u003c/span\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"callout-body\"\u003e\u003cp\u003e这只是针对于\u003ccode\u003evibe-coding\u003c/code\u003e供应商提供的\u003ccode\u003ecodex API\u003c/code\u003e使用的教程，其他更加官方的站点如\u003ccode\u003eClaudeCode\u003c/code\u003e、\u003ccode\u003eOpenAI-codex\u003c/code\u003e这些，教程更多，此处就不讲了。\u003c/p\u003e","tags":["技术","技术/AI","技术/AI/工具"],"title":"CC Switch 导入 API Key 使用 Claude/Codex"},{"content":"这个页面不再只是“换背景色”，而是做成真正可交互的 pretext 实验：你可以拖动滑块，实时改变文本容器宽度，观察行数和高度的动态变化。\nPretext Demo 扩展展示 Shrinkwrap Showdown（紧凑宽度） 演示效果 左侧是普通块级文本，右侧启用 pretext 的气泡收紧，行数尽量保持一致但宽度更紧凑。\n普通文本块 在普通布局里，文本块会倾向占满父容器宽度。虽然可读性不差，但很多时候会显得版面“松散”。 Pretext 收紧块 在 pretext 收紧模式里，文本会在不明显增加行数的前提下，自动寻找更合适的紧凑宽度，让信息密度和视觉重心更平衡。 源码（HTML） \u0026lt;div class=\u0026#34;pretext-card\u0026#34;\u0026gt; \u0026lt;h2\u0026gt;Pretext 收紧块\u0026lt;/h2\u0026gt; \u0026lt;p data-pretext-bubble=\u0026#34;1\u0026#34;\u0026gt; 在 pretext 收紧模式里，文本会自动寻找更合适的紧凑宽度... \u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; Justification Compared（对齐对比） 演示效果 列宽（Justification 对比） 列宽：364px CSS 行数：-- Pretext 行数：-- CSS / Greedy Typography rivers happen when spacing is stretched unevenly. Native greedy justification resolves line by line, which is fast but often produces local artifacts. When the column width changes quickly, visual rhythm can jump between lines. Pretext (Hyphenation) Pretext first measures text arithmetically, then writes stable dimensions back to the DOM. With controlled width and deterministic reflow, transitions are smoother, and spacing variance is lower during interaction. Pretext (Knuth-Plass) Global line breaking chooses a better overall set of breaks instead of committing greedily at each line. That tends to reduce harsh rivers and keeps the paragraph color more even across dynamic width changes. 源码（HTML） \u0026lt;input data-pretext-just-slider=\u0026#34;1\u0026#34; type=\u0026#34;range\u0026#34; min=\u0026#34;240\u0026#34; max=\u0026#34;520\u0026#34; value=\u0026#34;364\u0026#34; step=\u0026#34;2\u0026#34; /\u0026gt; \u0026lt;div class=\u0026#34;pretext-just-grid\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;pretext-card pretext-justify-box\u0026#34; data-pretext-just-col=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;p class=\u0026#34;pretext-justify-text\u0026#34; data-pretext-just-css=\u0026#34;1\u0026#34;\u0026gt;...\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;pretext-card pretext-justify-box\u0026#34; data-pretext-just-col=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;p class=\u0026#34;pretext-justify-text\u0026#34; data-pretext-height=\u0026#34;1\u0026#34; data-pretext-just-pretext=\u0026#34;1\u0026#34;\u0026gt;...\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;pretext-card pretext-justify-box\u0026#34; data-pretext-just-col=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;p class=\u0026#34;pretext-justify-text\u0026#34; data-pretext-height=\u0026#34;1\u0026#34; data-pretext-just-pretext=\u0026#34;1\u0026#34;\u0026gt;...\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; Editorial Engine（实时重排） 演示效果 有趣的 Pretext Reflow Lab 拖动下面滑块，文本会实时重排。右侧指标会同步更新当前宽度、行数与高度。 容器宽度 宽度：520px 行数：-- 高度：-- 你拖动宽度时，脚本会实时测量文本并更新高度与行数，避免传统布局抖动。这个 demo 只作用于“有趣的”这篇文章，其他文章不会被影响。它适合做交互写作、排版实验和阅读器组件。 源码（HTML） \u0026lt;input data-pretext-slider=\u0026#34;1\u0026#34; type=\u0026#34;range\u0026#34; min=\u0026#34;220\u0026#34; max=\u0026#34;900\u0026#34; value=\u0026#34;520\u0026#34; /\u0026gt; \u0026lt;div data-pretext-stage=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;div data-pretext-height=\u0026#34;1\u0026#34; data-pretext-target=\u0026#34;1\u0026#34; data-pretext-scroll=\u0026#34;1\u0026#34;\u0026gt; 你拖动宽度时，脚本会实时测量文本并更新高度与行数... \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; 源码（JS 片段） const slider = demoRoot.querySelector(\u0026#39;[data-pretext-slider=\u0026#34;1\u0026#34;]\u0026#39;); const target = demoRoot.querySelector(\u0026#39;[data-pretext-target=\u0026#34;1\u0026#34;]\u0026#39;); slider.addEventListener(\u0026#34;input\u0026#34;, () =\u0026gt; run()); async function run() { target.style.width = `${slider.value}px`; await applyHeight(pretext, target); } Dragon Flight（巨龙飞行风格） 演示效果 飞行速度 🐉 夜色里，龙翼掠过手抄页的边缘，墨迹像被风掀起的波纹。随着巨龙在页面中飞行，正文块会同步偏移，形成“飞行轨迹影响排版”的动态效果。这个变化不是单纯动画贴图，而是把排版位移与文本高度回写联动起来：龙靠近时，正文左侧留白增大；龙远离时，正文回归中轴。这样在保持可读性的同时，页面会呈现更明显的活体叙事感。 源码（HTML） \u0026lt;input data-pretext-dragon-speed=\u0026#34;1\u0026#34; type=\u0026#34;range\u0026#34; min=\u0026#34;4\u0026#34; max=\u0026#34;14\u0026#34; value=\u0026#34;8\u0026#34; step=\u0026#34;1\u0026#34; /\u0026gt; \u0026lt;div class=\u0026#34;pretext-card pretext-dragon-scene\u0026#34; data-pretext-dragon-scene=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;pretext-dragon-flyer\u0026#34; data-pretext-dragon-flyer=\u0026#34;1\u0026#34;\u0026gt;🐉\u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;pretext-dragon-body\u0026#34; data-pretext-dragon-body=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;p data-pretext-height=\u0026#34;1\u0026#34; class=\u0026#34;pretext-dragon-text\u0026#34; data-pretext-dragon-text=\u0026#34;1\u0026#34;\u0026gt;...\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; 源码（JS 片段） const scene = root.querySelector(\u0026#39;[data-pretext-dragon-scene=\u0026#34;1\u0026#34;]\u0026#39;); const flyer = root.querySelector(\u0026#39;[data-pretext-dragon-flyer=\u0026#34;1\u0026#34;]\u0026#39;); const body = root.querySelector(\u0026#39;[data-pretext-dragon-body=\u0026#34;1\u0026#34;]\u0026#39;); const speedCtl = root.querySelector(\u0026#39;[data-pretext-dragon-speed=\u0026#34;1\u0026#34;]\u0026#39;); function tick(ts) { const dt = ts / 1000; const speed = Number(speedCtl?.value || 8); const width = Math.max(320, scene.clientWidth || 700); const x = ((dt * (40 + speed * 8)) % (width + 160)) - 90; flyer.style.transform = `translate(${x}px, 10px)`; body.style.setProperty(\u0026#34;--dragon-shift\u0026#34;, `${Math.sin((x / width) * Math.PI) * 46}px`); requestAnimationFrame(tick); } requestAnimationFrame(tick); 原理与复用 项目原理 核心机制 pretext 先根据字体、文本、容器宽度做纯计算，得到行数和高度。 页面侧只接收计算结果并写回 style.height/width，避免频繁读写布局。 在本项目里，运行时入口是 static/js/pretext-runtime.js，通过 data-pretext-* 标记按需启用。 运行流程 扫描标记：data-pretext-height=\u0026quot;1\u0026quot; / data-pretext-bubble=\u0026quot;1\u0026quot;。 首次计算：prepare + layout 得到高度、行数。 变化重算：滑块事件、窗口 resize、ResizeObserver 触发增量重算。 为什么能做到丝滑 关键点 计算与渲染分离：先算后写，减少布局抖动（layout thrashing）。 requestAnimationFrame：把尺寸写回安排到浏览器绘制节奏里。 CSS 过渡：height/width 使用 transition，视觉上连续。 约束保护：宽度上限跟随容器变化，避免超出显示范围导致跳变。 其他地方怎么用 最小用法 \u0026lt;div data-pretext-height=\u0026#34;1\u0026#34;\u0026gt;你的多行文本...\u0026lt;/div\u0026gt; \u0026lt;div data-pretext-bubble=\u0026#34;1\u0026#34;\u0026gt;你的气泡文本...\u0026lt;/div\u0026gt; 交互用法 \u0026lt;input data-pretext-slider=\u0026#34;1\u0026#34; type=\u0026#34;range\u0026#34; min=\u0026#34;220\u0026#34; max=\u0026#34;900\u0026#34; value=\u0026#34;520\u0026#34; /\u0026gt; \u0026lt;div data-pretext-stage=\u0026#34;1\u0026#34;\u0026gt; \u0026lt;div data-pretext-height=\u0026#34;1\u0026#34; data-pretext-target=\u0026#34;1\u0026#34; data-pretext-scroll=\u0026#34;1\u0026#34;\u0026gt; 交互文本... \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; 相关参考：\nPretext Demos chenglou/pretext ","permalink":"https://june6699.github.io/posts/pretext-demo/","summary":"\u003cp\u003e这个页面不再只是“换背景色”，而是做成真正可交互的 \u003ca href=\"https://github.com/chenglou/pretext\" target=\"_blank\" rel=\"noopener noreferrer\"\u003epretext\u003c/a\u003e\n 实验：你可以拖动滑块，实时改变文本容器宽度，观察行数和高度的动态变化。\u003c/p\u003e\n\u003ch3 id=\"pretext-demo-扩展展示\"\u003ePretext Demo 扩展展示\u003c/h3\u003e\n\u003ch4 id=\"shrinkwrap-showdown紧凑宽度\"\u003eShrinkwrap Showdown（紧凑宽度）\u003c/h4\u003e\n\u003ch5 id=\"演示效果\"\u003e演示效果\u003c/h5\u003e\n\u003cdiv class=\"pretext-demo\"\u003e\n\u003csection class=\"pretext-page\"\u003e\n\u003cdiv class=\"pretext-card\"\u003e\n\u003cp class=\"pretext-intro\"\u003e左侧是普通块级文本，右侧启用 pretext 的气泡收紧，行数尽量保持一致但宽度更紧凑。\u003c/p\u003e","tags":["技术","技术/前端","技术/前端/项目"],"title":"Pretext 实时重排互动实验"},{"content":"本地化动态字符视频渲染系统：开发与迭代实录 本文档完整记录了“本地化动态 ASCII 字符视频渲染系统”从最初的构想、踩坑、架构推翻到最终实现纯前端视频压制、字幕解析完全体的全过程。\n项目起源与初探：基于 Pretext 的构想 在项目初期，我们的核心诉求是将视频的每一帧转化为 ASCII 字符并在浏览器中高帧率播放。前端渲染大量长文本换行时，极易触发 DOM 回流（Reflow），导致页面卡顿甚至崩溃。\n因此，最初的架构设计引入了 @chenglou/pretext —— 一个纯算术排版引擎，试图在内存中瞬间计算文本边界以规避 DOM 性能瓶颈。\n踩坑 1：ESM 模块加载与依赖缺失 在最初编写了 index.html 并使用 Live Server 启动后，系统一直卡在“系统环境挂载中，请稍候\u0026hellip;”。 Bug 分析： 代码中使用了 \u0026lt;script type=\u0026quot;module\u0026quot;\u0026gt; 导入 layout.js。而 ES Module 要求严格的依赖解析，由于本地缺失了 pretext 引擎的底层依赖（如 bidi.js, analysis.js 等），导致浏览器抛出 404 错误并直接中断了整段脚本的执行。 修复方案： 严格按照包版本（@0.0.3），使用 PowerShell 补齐了所有的前置依赖文件：\nInvoke-WebRequest -Uri \u0026#34;https://cdn.jsdelivr.net/npm/@chenglou/pretext@0.0.3/dist/analysis.js\u0026#34; -OutFile \u0026#34;analysis.js\u0026#34; # ... 同理补齐 measurement.js, bidi.js, line-break.js 踩坑 2：FFmpeg (v0.12) 的隐藏 Worker 线程 依赖补齐后，Pretext 引擎成功启动，但 ffmpegInstance.load() 陷入了无限期的死等（Promise 既不 Resolve 也不 Reject）。 Bug 分析： 版本兼容性问题。@ffmpeg/ffmpeg@0.12.x 的 UMD 打包版本在底层会默认拉起一个名为 814.ffmpeg.js 的 Web Worker 子线程。本地缺少该文件导致 Worker 启动失败，主线程死锁。 修复方案： 单独下载补齐该 Worker 文件，系统环境终于成功挂载。\n核心引擎点亮：从假数据到真像素提取 修复 1：File API 读取陷阱 在选中视频准备解析时，触发了 currentVideoFile.arrayBuffer is not a function 的报错。 Bug 分析： videoInput.files 返回的是一个 FileList 对象，而非单个 File 对象。 代码修正：\n// 错误代码 currentVideoFile = videoInput.files; // 正确代码：获取数组第一个元素 currentVideoFile = videoInput.files[0]; 进化 1：灰度算法与字符映射引擎 初版代码中，系统只是在死循环里打印 动态文本渲染中... 的假数据。为了真正将视频变成字符，我们引入了离屏 Canvas （Offscreen Canvas）进行像素级验血。\n// 核心像素提取与转译代码 const offscreenCanvas = document.createElement(\u0026#39;canvas\u0026#39;); const offCtx = offscreenCanvas.getContext(\u0026#39;2d\u0026#39;, { willReadFrequently: true }); const chars = \u0026#34; .:-=+*#%@\u0026#34;; // 引入10级留白灰度表增强对比度 offCtx.drawImage(img, 0, 0); const imageData = offCtx.getImageData(0, 0, img.width, img.height).data; let asciiFrame = \u0026#34;\u0026#34;; for (let y = 0; y \u0026lt; img.height; y++) { for (let x = 0; x \u0026lt; img.width; x++) { const offset = (y * img.width + x) * 4; const r = imageData[offset], g = imageData[offset + 1], b = imageData[offset + 2]; // 经典心理学灰度公式 const gray = 0.299 * r + 0.587 * g + 0.114 * b; const charIndex = Math.floor((gray / 255) * (chars.length - 1)); asciiFrame += chars[charIndex]; } asciiFrame += \u0026#34;\\n\u0026#34;; } 破除封印与架构重构：全片解析与内存溢出 解决 1：30 帧鬼畜与 NaN 进度条 初期硬编码了 -vframes 30 导致无论视频多长只渲染前 30 帧（疯狂鬼畜）。 改版优化： 将参数改为 -r 15（设置采样率），并采用 while(true) 动态读取，直到 FFmpeg 抛出找不到文件的异常才停止。同时修复了 FFmpeg v0.12 中进度变量名变更导致的 NaN% Bug：\n// FFmpeg v0.12 版本进度监听 ffmpegInstance.on(\u0026#39;progress\u0026#39;, ({ progress }) =\u0026gt; { // 变量名从 ratio 变为了 progress if (progress !== undefined \u0026amp;\u0026amp; !isNaN(progress)) { const percent = Math.max(0, Math.min(100, Math.round(progress * 100))); progressText.innerText = `视频解帧进度: ${percent}%`; } }); 架构顿悟：Pretext 的退役 随着开发的深入，我们发现字符视频实际上是一个绝对完美的矩形矩阵。 如果我们强制使用等宽字体（monospace），画面的物理宽高就可以通过极简的乘法直接算出：宽度 = 列数 * 单字符宽，根本不需要动态折行。 历史性优化： 彻底删除了重金求来的 pretext 引擎及那 5 个 *.js 依赖，改用 1:1 的网格强制映射，不仅彻底消灭了黑边，还将渲染性能提升到了极限。\n// 大道至简的网格布局引擎 ctx.font = \u0026#39;12px monospace\u0026#39;; const charWidth = ctx.measureText(\u0026#39;M\u0026#39;).width; const lineHeight = charWidth; // 强行设为 1:1 正方形，消除画面拉伸畸变 renderCanvas.width = cachedAsciiFrames[0].split(\u0026#39;\\n\u0026#39;)[0].length * charWidth; renderCanvas.height = cachedAsciiFrames[0].split(\u0026#39;\\n\u0026#39;).length * lineHeight; 体验飞跃：绝对同步与交互系统 核心黑科技：音频时间戳驱动的音画同步 传统的 requestAnimationFrame 死循环无法保证音画同步（浏览器一卡顿就会声画分离）。 最终方案： 将提取出的原视频作为背景音频偷偷播放，以音频的当前时间戳逆向推算当前应该渲染哪一帧。\nlet frameIndex = Math.floor(globalAudio.currentTime * cachedFps); if (frameIndex \u0026gt;= cachedAsciiFrames.length) frameIndex = cachedAsciiFrames.length - 1; // 画面永远跟着 globalAudio 走，哪怕拖动进度条也能瞬间对齐 沉浸式全屏与本地指纹点赞 (Q键) 安全沙盒绕过： 浏览器无法获取绝对路径，因此使用 ${File.name}_${File.size} 生成唯一数字指纹，以此作为 localStorage 记录点赞数的 Key。 全屏 API： 挂载 renderCanvas.requestFullscreen() 实现 B 站级别的纯黑沉浸式观影。 极客狂欢：秒读存档、MP4硬编与外挂字幕 内存溢出 (OOM) 引发的“外挂音轨”架构 为了实现“渲染一次，下次秒看”，我们开发了导出 .asciivid 的功能。 灾难发生： 最初试图将几百兆的音频转为 Base64 塞进 JSON 一起导出，导致 V8 引擎字符串长度超限，浏览器瞬间崩溃，存档损坏。 优雅降维： 存档文件只保存纯文本矩阵。读取存档时，玩家可以手动传入原视频文件作为“外挂音轨”。若无音轨，则启用高精度时钟 performance.now() 进行纯视觉无声播放。\n解析外挂 SRT 字幕 利用正则手搓了 SRT 时间轴解析器，并将字幕强行绘制在 Canvas 的最上层：\nfunction parseSrtTimecode(timeString) { const parts = timeString.replace(\u0026#39;,\u0026#39;, \u0026#39;.\u0026#39;).split(\u0026#39;:\u0026#39;); return parseFloat(parts[0]) * 3600 + parseFloat(parts[1]) * 60 + parseFloat(parts[2]); } // 使用正则提取开始时间、结束时间和字幕文本 const regex = /(\\d+)\\r?\\n(\\d{2}:\\d{2}:\\d{2},\\d{3}) --\u0026gt; (\\d{2}:\\d{2}:\\d{2},\\d{3})\\r?\\n([\\s\\S]*?)(?=(?:\\r?\\n\\r?\\n\\d+|$))/g; 终极暴力美学：浏览器端压制 MP4 这是最挑战性能的一环。我们将几千帧 ASCII 字符串逆向画在离屏 Canvas 上，转成 JPEG 喂回 FFmpeg，最后混入 AAC 音轨，调用 libx264 导出真正的 MP4 视频（实现硬字幕烙印）。\n// 离屏渲染 JPEG 帧 (采用纯黑底色) expCtx.fillStyle = \u0026#34;#000000\u0026#34;; expCtx.fillRect(0, 0, expCanvas.width, expCanvas.height); // ... 绘制字符和字幕 ... const imgData = await canvasToUint8Array(expCanvas); await ffmpegInstance.writeFile(`out_${i.toString().padStart(5, \u0026#39;0\u0026#39;)}.jpg`, imgData); // 极速硬编指令 (preset ultrafast 缓解浏览器 CPU 压力) await ffmpegInstance.exec([ \u0026#39;-framerate\u0026#39;, cachedFps.toString(), \u0026#39;-i\u0026#39;, \u0026#39;out_%05d.jpg\u0026#39;, \u0026#39;-i\u0026#39;, virtualAudioName, \u0026#39;-c:v\u0026#39;, \u0026#39;libx264\u0026#39;, \u0026#39;-preset\u0026#39;, \u0026#39;ultrafast\u0026#39;, \u0026#39;-crf\u0026#39;, \u0026#39;28\u0026#39;, \u0026#39;-pix_fmt\u0026#39;, \u0026#39;yuv420p\u0026#39;, \u0026#39;-shortest\u0026#39;, \u0026#39;ascii_output.mp4\u0026#39; ]); 终结 UI 阻塞：纯 Canvas 重绘原生交互 恶性 Bug： 在全屏模式下，按 Q 连续点赞触发的原生 confirm() 弹窗会阻塞主线程，导致全屏状态锁死、页面卡死（但声音还在播）。 极客修复： 彻底抛弃 DOM 弹窗，采用游戏开发的思路，在 Canvas 的 renderLoop 中增加了一个 isPromptingLike 状态锁。当状态触发时，停止画面更新，直接在 Canvas 中心用 fillRect 和 fillText 绘制出一个黑客帝国风格的交互界面，通过监听 Y / N 键完成闭环，彻底告别阻塞。\n开发与运行注意事项 1. 跨域隔离 (COOP/COEP) 策略 FFmpeg.wasm 需要 SharedArrayBuffer 才能运行，这要求网页必须处于严苛的跨域隔离环境中。\n项目必须依赖 coi-serviceworker.js。 注意： 首次启动或强制刷新后，Service Worker 才会接管网络。如果在 VSCode 的 Live Server 中遇到死循环挂载，建议开启无痕模式或按下 Ctrl + F5 强制刷新。 2. 内存管理与资源泄漏 WebAssembly 虚拟文件系统 (MEMFS) 在浏览器中有内存上限（通常 2GB-4GB）。 在循环处理（如抽帧、渲染 JPEG）后，务必使用 await ffmpegInstance.deleteFile(fileName) 及时删除内存中的文件。 大量生成 Blob URL 后，务必调用 URL.revokeObjectURL(url) 释放显存，否则处理长视频必崩。 3. 字幕与格式限制 SRT 文件需确保为 UTF-8 编码，否则正则匹配中文字符时可能会出现乱码。 导出的 MP4 使用了 yuv420p 像素格式，以确保主流播放器（如 QuickTime, Windows 媒体播放器）的兼容性。 ","permalink":"https://june6699.github.io/posts/vid2ascii-gif%E6%9E%84%E5%BB%BA%E6%97%A5%E5%BF%97/","summary":"\u003ch2 id=\"本地化动态字符视频渲染系统开发与迭代实录\"\u003e本地化动态字符视频渲染系统：开发与迭代实录\u003c/h2\u003e\n\u003cp\u003e本文档完整记录了“本地化动态 ASCII 字符视频渲染系统”从最初的构想、踩坑、架构推翻到最终实现纯前端视频压制、字幕解析完全体的全过程。\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"项目起源与初探基于-pretext-的构想\"\u003e项目起源与初探：基于 Pretext 的构想\u003c/h2\u003e\n\u003cp\u003e在项目初期，我们的核心诉求是将视频的每一帧转化为 ASCII 字符并在浏览器中高帧率播放。前端渲染大量长文本换行时，极易触发 DOM 回流（Reflow），导致页面卡顿甚至崩溃。\u003c/p\u003e","tags":["技术","技术/前端","技术/前端/项目"],"title":"本地化动态 ASCII 字符视频渲染系统"},{"content":"欧美主流 AI 模型 Claude（Anthropic） 中文常译：克劳德。由美国公司 Anthropic 开发，以信息论之父 Claude Elwood Shannon（克劳德·香农）命名，致敬其对通信与计算理论的奠基性贡献。\nClaude 系列目前分为 Haiku、Sonnet、Opus 三档，分别对应轻量、均衡、旗舰能力。Opus 并非独立模型，而是 Claude 系列的最高规格档位，拉丁语原意为\u0026quot;作品/杰作\u0026quot;，暗指其为 Anthropic 当前最具代表性的成果。\nGPT / ChatGPT（OpenAI） 中文常译：无固定译名，口语常称\u0026quot;ChatGPT\u0026quot;或\u0026quot;챗지피티\u0026quot;。GPT 是 Generative Pre-trained Transformer（生成式预训练变换器）的缩写，直接描述了模型的核心架构与训练范式。ChatGPT 是 OpenAI 在 2022 年底推出的对话产品，将 GPT 技术包装为聊天界面，\u0026ldquo;Chat\u0026quot;点明交互形式。GPT-4o 中的 o 代表 omni（全模态），意指同时处理文本、图像、语音。\nGemini（Google DeepMind） 中文常译：双子座。由 Google DeepMind 开发，取名自双子座（Gemini）星座，一方面契合其多模态设计——如同双子并存般同时理解文本与图像；另一方面也与 Google 早期探索多模态 AI 的项目代号相呼应。分为 Nano、Flash、Pro、Ultra 四档。\nGrok（xAI） 中文常译：格罗克。由埃隆·马斯克创立的 xAI 开发。\u0026ldquo;Grok\u0026quot;一词来源于罗伯特·海因莱因 1961 年科幻小说《异乡异客》（Stranger in a Strange Land），火星语中意为\u0026quot;彻底地、直觉性地理解某事\u0026rdquo;，暗示该模型追求对世界的深层理解，而非表面检索。\nLlama（Meta） 中文常译：骆马 / 羊驼。由 Meta（原 Facebook）开发，全称 Large Language Model Meta AI，首字母缩写恰好拼出南美动物\u0026quot;羊驼（Llama）\u0026quot;，兼顾了品牌辨识度与幽默感。Llama 系列以开源著称，是目前开源社区使用最广泛的基础模型之一。\nMistral（Mistral AI） 中文常译：密斯特拉尔风 / 米斯特拉。由法国初创公司 Mistral AI 开发，取名自密斯特拉尔风——一种席卷法国南部地中海沿岸的强劲西北风，象征速度、力量与法国本土属性。Mistral 系列以高效小参数著称，旗舰模型 Mixtral 采用混合专家（MoE）架构。\nCopilot（Microsoft） 中文常译：副驾驶。由微软整合 OpenAI GPT-4 能力推出，定位为工作效率\u0026quot;副驾驶\u0026rdquo;——不替代人类决策，而是坐在副驾驶席位协助操控，贯穿于 Office、Windows、Bing 等微软生态。\nPerplexity（Perplexity AI） 中文常译：困惑度。由同名公司开发，名称直接借用了自然语言处理领域衡量语言模型不确定性的经典指标 Perplexity（困惑度），既是技术术语的自我致敬，也暗示其产品核心——通过实时检索消解用户的\u0026quot;困惑\u0026quot;。\nMythoMax（社区模型） 中文常译：神话极限。并非商业公司产品，而是 Hugging Face 社区开发者基于 Llama 深度微调的开源模型，\u0026ldquo;Mytho\u0026quot;取自 mythology（神话），\u0026ldquo;Max\u0026quot;指参数规模上限，整体传达出超越常规的雄心。是目前开源角色扮演和创意写作领域热门的社区模型之一。\nCommand R（Cohere） 中文常译：指令R。由加拿大公司 Cohere 开发，面向企业 RAG（检索增强生成）场景。Command 强调其遵循指令的能力，R 代表 Retrieval（检索），直接点明其核心设计目标。\nPhi（Microsoft Research） 中文常译：φ / 斐。微软研究院开发的小参数高效模型系列，以希腊字母 φ（phi） 命名，在数学与物理学中象征黄金比例与基本常数，暗示用\u0026quot;小而精\u0026quot;的参数实现\u0026quot;大而优\u0026quot;的效果。\n中国主流 AI 模型 DeepSeek（深度求索） 中文官方名：深度求索。由量化私募公司幻方科技孵化，名称出自屈原《离骚》\u0026rdquo;路漫漫其修远兮，吾将上下而求索\u0026quot;，\u0026ldquo;深度\u0026quot;既指深度学习技术，也呼应诗句中对真理的不懈追寻。DeepSeek-R1 系列以极低训练成本达到与 GPT-4 级别相近的推理能力，引发全球关注。\nKimi（月之暗面 Moonshot AI） 中文常用名：Kimi。由月之暗面（Moonshot AI）开发，\u0026ldquo;Kimi\u0026quot;在日语中意为\u0026rdquo;你\u0026quot;，亲切随和；英文发音轻盈，易于记忆。公司名\u0026quot;Moonshot\u0026rdquo;（登月计划）与模型名形成反差——宏大愿景配以温柔称谓，强调人机对话的亲密感。\n文心一言 / ERNIE Bot（百度） 中文官方名：文心一言。百度大模型产品，\u0026rdquo;文心\u0026ldquo;取自文心雕龙，象征中国文学与思想传统；\u0026rdquo;一言\u0026ldquo;强调一言即可触达知识。底层模型英文名 ERNIE（增强知识融合表示）是 Enhanced Representation through kNowledge IntEgration 的缩写，技术层面强调知识图谱与语言模型的融合。\n通义千问 / Qwen（阿里巴巴） 中文官方名：通义千问。阿里巴巴云开发，\u0026rdquo;通义\u0026ldquo;意为通情达义、融会贯通；\u0026rdquo;千问\u0026ldquo;呼应《天问》典故，寓意可回答千万种问题。英文缩写 Qwen（Qian Wen）直接音译自\u0026quot;千问\u0026rdquo;。目前已开源，是全球最活跃的开源模型系列之一。\n讯飞星火（科大讯飞） 中文官方名：讯飞星火。科大讯飞开发，\u0026quot;讯飞\u0026ldquo;为公司名；\u0026rdquo;星火\u0026ldquo;取自\u0026rdquo;星星之火，可以燎原\u0026quot;，强调 AI 从小火种到燎原之势的发展愿景，同时暗指知识如星火般点亮智慧。\n混元（腾讯） 中文官方名：混元。腾讯开发，取自道家哲学\u0026quot;混沌初开，乾坤始奠\u0026ldquo;中的\u0026quot;混元\u0026rdquo;——宇宙未分阴阳之前的原始整体状态，象征模型融合万物、包罗万象的能力。\n豆包（字节跳动） 中文官方名：豆包。字节跳动开发，面向 C 端用户的对话产品。\u0026quot;豆包\u0026ldquo;是中国传统小吃，亲切、接地气、无门槛感，刻意与高冷的技术形象拉开距离，强调日常陪伴属性。底层模型代号为 Doubao。\n智谱清言 / GLM（智谱 AI） 中文官方名：智谱清言。清华系初创公司智谱 AI 开发，\u0026rdquo;智谱\u0026ldquo;意为智慧图谱；\u0026rdquo;清言\u0026ldquo;取自魏晋清谈之风，寓意清晰、雅正的表达。底层模型 GLM（General Language Model）是清华大学自研的通用语言模型架构。\nYi（零一万物） 中文官方名：零一万物 Yi。由前 Google 中国区总裁李开复创立，模型命名为 Yi——中文\u0026rdquo;一\u0026ldquo;的拼音，取自《道德经》\u0026rdquo;道生一，一生二，二生三，三生万物\u0026quot;，寓意从模型基座出发衍生无限可能。\n其他国家 AI 模型 Falcon（阿联酋 TII） 中文常译：猎鹰。由阿联酋技术创新研究院（TII）开发，以阿联酋国鸟猎鹰命名——猎鹰在阿拉伯文化中是智慧、速度与荣耀的象征，也是阿联酋国徽的核心图腾。Falcon 180B 曾短暂登顶开源模型榜首。\nAya（Cohere / 加拿大） 中文常译：阿雅。由 Cohere 联合全球研究者共建，\u0026quot;Aya\u0026ldquo;在斯瓦希里语、阿拉伯语等多种语言中均有\u0026rdquo;奇迹、礼物\u0026ldquo;之意，象征该模型对全球多语言社区的普惠承诺，覆盖 100 余种语言。\n","permalink":"https://june6699.github.io/posts/%E5%B8%82%E9%9D%A2ai%E5%8F%8A%E5%85%B6%E5%8F%96%E5%90%8D/","summary":"\u003ch3 id=\"欧美主流-ai-模型\"\u003e欧美主流 AI 模型\u003c/h3\u003e\n\u003ch4 id=\"claudeanthropic\"\u003eClaude（Anthropic）\u003c/h4\u003e\n\u003cp\u003e\u003cstrong\u003e中文常译：克劳德\u003c/strong\u003e。由美国公司 Anthropic 开发，以信息论之父 \u003cstrong\u003eClaude Elwood Shannon\u003c/strong\u003e（克劳德·香农）命名，致敬其对通信与计算理论的奠基性贡献。\u003c/p\u003e\n\u003cp\u003eClaude 系列目前分为 Haiku、Sonnet、Opus 三档，分别对应轻量、均衡、旗舰能力。\u003cstrong\u003eOpus\u003c/strong\u003e 并非独立模型，而是 Claude 系列的最高规格档位，拉丁语原意为\u0026quot;作品/杰作\u0026quot;，暗指其为 Anthropic 当前最具代表性的成果。\u003c/p\u003e","tags":["技术","技术/AI","技术/AI/分析"],"title":"2026 全球主流 AI 大模型总览"},{"content":"问题 最近219服务器貌似内存越来越冗余，造成往上传文件比较慢（直接复制这种很慢，scp还是速度可以的，但是scp有时候不稳定，老是断连），经过网上找了一些解决方案，最后发现了rsync-win版，链接在rn7s2/rsync-win: Rsync for Windows. 这是一个基于著名的 Linux 同步神器 rsync，专门为 Windows 环境开发的版本（通常是用 Rust 或 Go 等语言重写的开源 GitHub 项目）。\n它的核心作用是高效、增量地进行文件和目录的同步或备份。所谓“增量”，就是它在传输前会对比源头和目标端的文件，只传输被修改过的那部分数据，而不是每次都把所有文件重新拷一遍，这在传大文件或大量文件时极其节省时间。\n安装方法 下载其release ，整个解压到你的软件目录，如D盘。\n在windows上搜索编辑系统环境变量，进入环境变量。\n看下面的系统变量里面的Path，对其双击进入编辑页面，点击新建。 然后把你解压的rsync-win的文件夹的路径放上去，例如C:\\softwares\\rsync-win\\。尽量与我保持一致，前缀就不必要一致了。 使用方法 rsync-win --archive --partial --progress --src \u0026#34;C:/Users/June/Downloads/xxx/\u0026#34; --dest root@10.xxx.0.xxx:/data/xxx 1. 基本用法 (Usage) 所有的同步任务都遵循一个核心逻辑：把源（SRC）同步到目标（DEST）。\n命令格式：\nBash\nrsync-win [各种选项] --src \u0026lt;源路径\u0026gt; --dest \u0026lt;目标路径\u0026gt; -s, --src: 源文件/目录的路径。 -d, --dest: 目标文件/目录的路径。 2. 支持的三种路径格式 (Allowed formats) 由于跨平台的原因，请注意路径一定要使用正斜杠 /，而不是 Windows 习惯的反斜杠 \\。\n本地到本地 (local)：比如把 C 盘同步到 D 盘。格式：C:/path/to/file 本地与远程服务器 (ssh)：通过 SSH 协议传输（最常用，极其安全）。格式：用户名@服务器IP:/远程/路径 Rsync 守护进程模式 (rsync)：连接到专门的 rsync 服务端。格式：rsync://用户名@服务器IP:端口/路径 3. 核心功能选项参数 (Options) 为了方便理解，我把它们分成了几大类：\n🌟 核心同步控制（最常用的）\n-a, --archive：归档模式。这是最常用的参数！它相当于打包了一系列功能：递归目录、保留文件的权限、修改时间、软链接等。一般做备份必加。 -r, --recursive：递归模式。同步文件夹及其里面的所有子文件夹（如果你用了 -a，就不需要再单独写 -r 了）。 --delete：镜像删除。非常强大但也危险！如果源端删除了某个文件，目标端也会把对应的文件删掉，保持两边一模一样。 --exclude \u0026lt;EXCLUDE\u0026gt;：排除特定文件。比如 --exclude \u0026quot;*.tmp\u0026quot; 不覆盖临时文件。 🌐 远程连接相关\n-i, --identity：指定 SSH 密钥文件。默认去读你 Windows 用户目录下的 id_rsa 私钥。如果你用密钥免密登录服务器，通常不用改。 --ssh-port：指定 SSH 端口。如果你的服务器 SSH 不是默认的 22 端口，用这个指定。 -4, --ipv4 / -6, --ipv6：强制使用 IPv4 或 IPv6 网络。 📊 传输与显示相关\n-v, --verbose：显示详细信息。想知道它具体传了哪些文件，加这个。 -q, --quiet：静默模式。除了报错什么都不打印，适合写成后台自动脚本。 -c, --checksum：校验和对比。默认情况 rsync 是通过对比文件大小和修改时间来判断文件变没变；加了这个参数，它会读取文件内容计算哈希值对比，极其严谨但非常慢。 --partial：断点续传。传大文件中断了，下次可以接着传，保留未传完的临时文件。 --progress：显示进度条。看着进度条走让人安心。 --bwlimit \u0026lt;BWLIMIT\u0026gt;：限制带宽。怕同步把网速占满了，可以限制速度（比如设为 1000 就是 1000KB/s）。 💡 实用场景演示 场景 1：把本地的工作目录备份到外接硬盘\nrsync-win -a -v --progress --src C:/Users/June/WorkData --dest E:/Backup/WorkData 场景 2：把本地代码推送到 Linux 服务器（保持完全一致，本地删了的服务器也删）\nrsync-win -a -v --delete --progress --src C:/Users/June/MyProject --dest root@192.168.1.100:/opt/MyProject ","permalink":"https://june6699.github.io/posts/rsync-win%E7%9A%84%E5%AE%89%E8%A3%85/","summary":"\u003ch3 id=\"问题\"\u003e问题\u003c/h3\u003e\n\u003cp\u003e最近219服务器貌似内存越来越冗余，造成往上传文件比较慢（直接复制这种很慢，scp还是速度可以的，但是scp有时候不稳定，老是断连），经过网上找了一些解决方案，最后发现了\u003ccode\u003ersync-win\u003c/code\u003e版，链接在\u003ca href=\"https://github.com/rn7s2/rsync-win\" target=\"_blank\" rel=\"noopener noreferrer\"\u003ern7s2/rsync-win: Rsync for Windows.\u003c/a\u003e\n\u003c/p\u003e","tags":["技术","技术/工具"],"title":"rsync-win的安装"},{"content":"一、问题背景 在使用 SCENIC+ (pycisTopic) 的 export_pseudobulk() 函数，按细胞类型拆分 ATAC fragment 文件并准备进行 consensus peak calling 时，常常遭遇一系列难以排查的“幽灵”错误。\n主要表现为：明明输入的数据没有任何问题，程序却频繁提示临时文件不存在，或者在刚创建好临时文件准备写入时直接崩溃闪退。根本原因是底层的 scatac_fragment_tools 解析器对输入文件的格式、字典匹配以及 DataFrame 的索引有着极其严苛（且缺乏友好报错提示）的硬编码限制。\n二、报错流程与解决方案 1. split_pattern 与 DataFrame 索引的隐蔽冲突 报错信息\nValueError: Fragment file /data/xujun/.../tmp/F32/F32_Cardiomyocyte.fragments.tsv.gz does not exist. 原因\nexport_pseudobulk 默认不读取你数据框里的某一列，而是死磕 cell_data 的行索引 (index) 去和 Fragment 文件里的 Barcode 进行比对。 在单细胞多样本合并时，为了防重叠，我们的 index 通常会带有样本前/后缀（如 AAACGAACAAGCGCTG-1_F32）。虽然官方提供了 split_pattern 参数用来切割前缀，但这玩意儿的底层逻辑有很大缺陷： 当设置 split_pattern=\u0026quot;_\u0026quot; 时，底层 Rust 代码往往强制默认你的格式是 样本_Barcode，从而去提取下划线后面的部分。如果你的 index 是 Barcode_样本，它提取出来的其实是 F32 这个无用字符串，拿着 F32 去比对，自然匹配数为 0，最终导致生成空文件并报错。\n解决方案\n放弃让底层瞎猜，直接在 Python 层面用干净的 barcode 列替换掉 index，并彻底关闭 split_pattern 参数，实现 100% 精确匹配：\n# 1. 复制数据，用干净且不带样本前后缀的 barcode 列替换原始的 index cell_data_for_pb = cell_data.copy() cell_data_for_pb.index = cell_data_for_pb[\u0026#39;barcode\u0026#39;] # 2. 运行导出时关闭 split_pattern bw_paths, bed_paths = export_pseudobulk( input_data=cell_data_for_pb, # ... 其他常规参数 ... split_pattern=None # 核心修改：改为None，拒绝底层切分逻辑 ) 2. chromsizes 字典与染色体命名格式不一致 报错信息\n（同上，也是报 Fragment file does not exist）\n原因\n排除了 Barcode 匹配失败的情况后，最容易被忽视的元凶是染色体命名格式。 如果输入的 Fragment 文件中的染色体命名没有前缀（例如 1），而传入的 chromsizes 字典的键带有前缀（例如 chr1），底层的 Rust 解析器会直接静默丢弃所有在字典中找不到对应键的行。几千万行数据读取完被全部丢弃，未能生成任何有效文件，最终再次导致外层 Python 脚本抛出“文件不存在”。\n解决方案\n在将字典传入 export_pseudobulk 之前，通过 Python 字典推导式，将 chromsizes 的键统一去掉 chr 前缀，强制与 Fragment 文件对齐：\n# 将类似于 {\u0026#39;chr1\u0026#39;: 248956422} 转换为 {\u0026#39;1\u0026#39;: 248956422} chromsizes_fixed = {str(k).replace(\u0026#39;chr\u0026#39;, \u0026#39;\u0026#39;): v for k, v in chromsizes.items()} 3. 底层 Rust 崩溃：Invalid number of fields 报错信息\nthread \u0026#39;\u0026lt;unnamed\u0026gt;\u0026#39; panicked at src/aggregate_fragments.rs:80:18: Invalid number of fields in fragment file! pyo3_runtime.PanicException: Invalid number of fields in fragment file! 原因\n经历了前两步，tmp 文件夹下终于成功创建了对应细胞类型的文件，但程序刚开始运行就崩溃了。 原因是部分非标准 10x 流程输出的 Fragment 文件包含了第 6 列（通常是正负链信息，如 + 或 -）。而 SCENIC+ 的底层解析器强制写死了列数检查，仅允许严格的 5 列格式（染色体、起点、终点、Barcode、read count）。只要读取到第 6 列，立马触发 PanicException 强制退出。\n解决方案\n回到 Linux 命令行，使用文本处理工具强行截断文件保留前 5 列，并重新压缩、建立 tabix 索引：\n# 解压读取 -\u0026gt; 截取前 5 列 -\u0026gt; 重新用 bgzip 压缩成新文件 zcat /path/to/original/fragments.tsv.gz | cut -f 1-5 | bgzip \u0026gt; /path/to/fixed/fragments_5col.tsv.gz # 为处理后的新文件建立 tabix 索引 tabix -p bed /path/to/fixed/fragments_5col.tsv.gz 最后，在 Python 脚本中更新 path_to_fragments 字典指向新的 _5col.tsv.gz 文件，即可顺利跑通整个流程。\n三、排坑总结 重要 SCENIC+ 的 scatac_fragment_tools 模块为了追求极高的文本解析速度，大幅牺牲了容错率和报错的友好度。\n少用 split_pattern：不要依赖底层的切分逻辑。永远在 Python 层把 index 处理成和 Fragment 文件里一模一样的纯 Barcode，然后设为 None。 静默过滤陷阱：遇到匹配不上的条目（染色体名称对不上 chr1 vs 1），底层逻辑通通是直接丢弃该行而不抛出 Warning。排查 does not exist 报错时，优先核对两端数据的格式是否做到字面意义上的完全一致。 文件结构红线：输入给流程的 Fragment 文件必须严格为 5 列，多一列都会导致底层直接 Panic 崩溃。遇到底层报错，直接查原文件的列数。 ","permalink":"https://june6699.github.io/posts/scenic+%E6%8B%86fragments/","summary":"\u003ch3 id=\"一问题背景\"\u003e一、问题背景\u003c/h3\u003e\n\u003cp\u003e在使用 SCENIC+ (pycisTopic) 的 \u003ccode\u003eexport_pseudobulk()\u003c/code\u003e 函数，按细胞类型拆分 ATAC fragment 文件并准备进行 consensus peak calling 时，常常遭遇一系列难以排查的“幽灵”错误。\u003c/p\u003e\n\u003cp\u003e主要表现为：明明输入的数据没有任何问题，程序却频繁提示临时文件不存在，或者在刚创建好临时文件准备写入时直接崩溃闪退。根本原因是底层的 \u003ccode\u003escatac_fragment_tools\u003c/code\u003e 解析器对输入文件的格式、字典匹配以及 DataFrame 的索引有着极其严苛（且缺乏友好报错提示）的硬编码限制。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/分析"],"title":"SCENIC+中export_pseudobulk导出片段文件的神坑盘点"},{"content":"一、问题背景 在使用 SnapATAC 的 snapToSeurat() 函数将 ATAC snap 对象转换为 Seurat 对象时，遭遇一系列版本兼容性问题。根本原因是当前环境安装的是 Seurat v5，而 SnapATAC 依赖 Seurat v4 的接口。\n二、报错流程与解决方案 1. snapToSeurat 报错：DimReduc global slot 报错信息\nError in validObject(.Object) : 类别为\u0026#34;DimReduc\u0026#34;的对象不对: \u0026#39;global\u0026#39; must be a 1-length logical 原因\nSeurat v5 对 DimReduc 对象的 global slot 验证更严格，SnapATAC 内部创建方式与 v5 不兼容。\n解决方案\n降级 Seurat 至 v4，新建 conda 环境隔离：\nconda create -n seurat_v4 r-base=4.3 conda activate seurat_v4 2. 安装 Seurat v4 时：SeuratObject 不可用 报错信息\nERROR: dependency \u0026#39;SeuratObject\u0026#39; is not available for package \u0026#39;Seurat\u0026#39; 解决方案\n从 GitHub 按顺序分别安装，先装 SeuratObject：\nremotes::install_github(\u0026#34;mojaveazure/seurat-object@v4.1.4\u0026#34;) remotes::install_github(\u0026#34;satijalab/seurat@v4.4.0\u0026#34;) 3. 安装 SeuratObject 时：Matrix 版本不满足 报错信息\npackage \u0026#39;Matrix\u0026#39; is not available for this version of R 原因\nCRAN 最新 Matrix 要求 R \u0026gt;= 4.4，而当前 R 版本较低，需手动指定归档版本。\n解决方案\n从 CRAN 归档直接安装 Matrix 1.6.1：\nconda install -c conda-forge r-matrix=1.6.1 或在 R 内：\ninstall.packages( \u0026#34;https://cran.r-project.org/src/contrib/Archive/Matrix/Matrix_1.6-1.tar.gz\u0026#34;, repos = NULL, type = \u0026#34;source\u0026#34; ) 4. 安装 Seurat v4 时：sctransform 版本不满足 报错信息\nnamespace \u0026#39;sctransform\u0026#39; 0.3.4 is being loaded, but \u0026gt;= 0.4.0 is required ERROR: lazy loading failed for package \u0026#39;Seurat\u0026#39; 解决方案\n先升级 sctransform，再重装 Seurat：\nremotes::install_github(\u0026#34;ChristophH/sctransform@v0.4.1\u0026#34;) remotes::install_github(\u0026#34;satijalab/seurat@v4.4.0\u0026#34;) 5. snapToSeurat 仍报错：rownames 无法设置 报错信息\nError in `rownames\u0026lt;-`(x = `*tmp*`, value = paste0(obj@barcode, 1:ncell)) : attempt to set \u0026#39;rownames\u0026#39; on an object with no dimensions 原因\neigs.dims 参数写成了标量 18，应为向量 1:18。\n解决方案\npbmc.atac \u0026lt;- snapToSeurat( obj = x.sp, eigs.dims = 1:18, # ← 必须是向量 norm = TRUE, scale = TRUE ) 三、最终成功环境 软件 版本 R 4.3.x Seurat 4.4.0 SeuratObject 4.1.4 Matrix 1.6.5 SnapATAC 1.0.0 sctransform \u0026gt;= 0.4.0 核心教训：SnapATAC 1.x 与 Seurat v5 不兼容，必须在独立 conda 环境中使用 Seurat v4，且各依赖包版本需严格对应。\n","permalink":"https://june6699.github.io/posts/atac%E7%9A%84transferanchor%E4%B8%8Eseurat%E7%89%88%E6%9C%AC%E9%97%AE%E9%A2%98/","summary":"\u003ch3 id=\"一问题背景\"\u003e一、问题背景\u003c/h3\u003e\n\u003cp\u003e在使用 SnapATAC 的 \u003ccode\u003esnapToSeurat()\u003c/code\u003e 函数将 ATAC snap 对象转换为 Seurat 对象时，遭遇一系列版本兼容性问题。根本原因是当前环境安装的是 \u003cstrong\u003eSeurat v5\u003c/strong\u003e，而 SnapATAC 依赖 \u003cstrong\u003eSeurat v4\u003c/strong\u003e 的接口。\u003c/p\u003e\n\u003chr\u003e\n\u003ch3 id=\"二报错流程与解决方案\"\u003e二、报错流程与解决方案\u003c/h3\u003e\n\u003ch4 id=\"1-snaptoseurat-报错dimreduc-global-slot\"\u003e1. snapToSeurat 报错：DimReduc global slot\u003c/h4\u003e\n\u003cp\u003e\u003cstrong\u003e报错信息\u003c/strong\u003e\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/分析"],"title":"SnapATAC与Seurat版本兼容性问题"},{"content":"1. 为什么整数安全范围是 ±2⁵³，而不是 ±2⁶³？ 因为 JavaScript 里的 Number 不是整数类型，而是 64 位双精度浮点数（IEEE 754 double）。\n这两种\u0026quot;64 位\u0026quot;的本质区别是：\n64 位整数：64 位全部用来存整数值，每一位都直接贡献数值 64 位浮点数：64 位要被拆成三段（符号 + 指数 + 尾数），真正用来表示精度的位数远少于 64 位 JavaScript 用的是后者，所以它的安全整数范围做不到 ±2⁶³。\n2. IEEE 754 双精度浮点数的结构 2.1 三部分组成 一个 Number 占 64 位，按固定格式划分为三段：\n部分 位数 作用 符号位 1 位 表示正负 指数位 11 位 决定数的\u0026quot;量级\u0026quot;（数有多大或多小） 尾数位 52 位 决定数的\u0026quot;精细程度\u0026quot; 一句话概括：指数位负责移动小数点，尾数位负责记录具体数值。\n2.2 二进制科学计数法 十进制有科学计数法：\n1234000 = 1.234 × 10^6 二进制也有类似写法：\n101.101₂ = 1.01101 × 2^2 IEEE 754 存的正是这种形式：\n(-1)^符号位 × 1.尾数 × 2^指数 注意最前面的 1. 是隐含的，默认存在、不占位，这也是为什么尾数只有 52 位，但有效精度却是 53 位。\n2.2.1 指数决定\u0026quot;范围\u0026quot; 指数越大，整个数就越大：\n1.0 × 2^0 = 1 1.0 × 2^10 = 1024 1.0 × 2^53 = 非常大的数 2.2.2 尾数决定\u0026quot;精度\u0026quot; 尾数位越多，越能分辨出两个相邻的数。尾数位有限，能精确区分的数就有上限。\n3. 指数位的作用 3.1 同样的尾数，指数不同 → 数值完全不同 尾数 1.0101 在不同指数下的结果：\n1.0101 × 2^1 = 2.625 1.0101 × 2^5 = 42 1.0101 × 2^20 = 很大的数 所以指数位不是精度位，它是放大倍数。\n3.2 为什么浮点数能同时表示极大和极小的数？ 因为指数可正可负：\n指数大 → 表示很大的数（如 1e308） 指数小（负数）→ 表示很小的数（如 1e-308） 这就是\u0026quot;浮点\u0026quot;的含义：小数点的位置不是固定的，而是随指数浮动的。\n3.3 11 位指数的能力 11 位指数理论上有 2¹¹ = 2048 种组合，但 IEEE 754 会保留一部分给特殊值（0、Infinity、NaN），真正可用的范围覆盖了足够宽的数值区间。\n重点提醒：范围大，≠ 每个整数都能精确表示。\n4. 为什么超过 2⁵³ 之后就不精确了？ 核心规律：\n浮点数的有效位数固定。数越大，这些位数越多地被整数部分\u0026quot;占用\u0026quot;，留给细微变化的空间就越少，导致相邻可表示数之间的间隔越来越大。\n4.1 \u0026ldquo;53 位有效精度\u0026quot;从哪来？ 尾数栏位有 52 位，但由于最高位那个 1 是隐含的（不需要实际存储），所以总有效精度是：\n52 + 1（隐含位）= 53 位有效二进制位 这 53 位，决定了 Number 能精确区分多少个连续整数。\n4.2 用\u0026quot;3 位精度\u0026quot;的简化模型来理解 为了不被 53 这个数字绕晕，先假设一个缩小版：这个世界的浮点数只有 3 位有效位。\n4.2.1 小范围内：每个整数都有位置 1 = 1.00 × 2^0 2 = 1.00 × 2^1 3 = 1.10 × 2^1 4 = 1.00 × 2^2 5 = 1.01 × 2^2 6 = 1.10 × 2^2 7 = 1.11 × 2^2 每个整数都能精确表示，相邻间隔 = 1。\n4.2.2 到了 8：刻度开始变粗 8 = 1000₂ = 1.000 × 2^3 ✅ 能表示 9 = 1001₂ = 1.001 × 2^3 ❌ 需要 4 位尾数，存不下 9 只能被近似成最近的可表示数：8 或 10。\n结果：可表示的数变成 8, 10, 12, 14 …，间隔从 1 变成了 2。\n4.2.3 再往大走：间隔不断翻倍 数越大，指数越大，尾数能表达的细节越粗：\n数值范围 可表示数 间隔 4 ~ 8 4, 5, 6, 7, 8 1 8 ~ 16 8, 10, 12, 14, 16 2 16 ~ 32 16, 20, 24, 28, 32 4 4.3 映射回 JavaScript 的真实情况（53 位） 把刚才的\u0026quot;3 位\u0026quot;换成真实的 53 位：\n数值范围 相邻间隔 0 ~ 2⁵³ 1（每个整数都可精确表示） 2⁵³ ~ 2⁵⁴ 2 2⁵⁴ ~ 2⁵⁵ 4 以此类推… 每上一个量级，间隔翻倍 验证：\n2**53 // 9007199254740992 ✅ 2**53 + 1 // 9007199254740992 ❌（被舍入，和上面一样） 2**53 + 2 // 9007199254740994 ✅ 5. \u0026ldquo;被舍入\u0026quot;是什么意思？ 5.1 生活中的舍入 保留两位小数：\n3.14159 → 3.14 3.146 → 3.15 精确值存不下，就改成\u0026quot;最近的能表示的值\u0026rdquo;，这就是舍入。\n5.2 浮点数里的舍入 浮点数保留的不是两位小数，而是固定的二进制位数。\n当你写 2**53 + 1，JS 会发现这个精确值存不下，于是找最近的可表示数——恰好是 9007199254740992，也就是 2**53 本身。\n2**53 + 1 === 2**53 // true 这不是\u0026quot;算错了\u0026rdquo;，而是精确值无处安放，被近似成了旁边能表示的值。\n5.3 为什么不舍入成 2⁵³ + 2？ 2**53 + 1 正好在 2**53 和 2**53 + 2 的正中间，按照 IEEE 754 的\u0026quot;就近舍入\u0026quot;规则（ties to even），这种居中情况会落向偶数那一侧，结果是 2**53。\n6. 用\u0026quot;刻度尺\u0026quot;直观理解浮点数精度 把浮点数想象成一把刻度尺：\n6.1 小数值区域：刻度很密 ..., 1, 2, 3, 4, 5, ... （每格 = 1，每个整数都有刻度线） 6.2 大数值区域：刻度变稀 ..., 9007199254740992, 9007199254740994, 9007199254740996, ... （每格 = 2，奇数的刻度线消失了） 不是\u0026quot;整数不能表示\u0026quot;，而是：太大的整数，刻度不够密，没法逐个安置。\n7. 为什么安全整数上限是 2⁵³ − 1，而不是 2⁵³？ 7.1 \u0026ldquo;安全整数\u0026quot;的含义 \u0026ldquo;安全\u0026quot;不是说超过就完全不能算，而是两个条件都满足：\n这个数本身能被精确表示 这个数前后相邻的整数也能被精确区分（不会出现 n === n + 1） 7.2 安全整数的范围 Number.MIN_SAFE_INTEGER // -9007199254740991，即 -(2⁵³ - 1) Number.MAX_SAFE_INTEGER // 9007199254740991，即 (2⁵³ - 1) 2⁵³ 本身虽然还能被表示，但它已经站在\u0026quot;刻度变粗\u0026quot;的边界上——再往后加 1 就不安全了，所以上限取 2⁵³ - 1。\n8. 64 位整数 vs. 64 位浮点数 8.1 64 位整数 64 位全部用来存整数，1 位做符号，剩下 63 位直接表示数值，所以能精确覆盖 ±2⁶³ 的范围，每个整数都有位置。\n8.2 64 位浮点数 64 位要按 1 + 11 + 52 拆分，是在\u0026quot;范围\u0026quot;和\u0026quot;精度\u0026quot;之间做了折中：\n范围极大（能到 ±1.8 × 10³⁰⁸） 但不是每个整数都能逐一精确表示 9. 需要更大的整数精度怎么办？用 BigInt 9.1 BigInt 的特点 BigInt 是 JavaScript 专门用来处理大整数的类型，没有精度丢失问题：\n2n ** 63n // 精确，没有任何近似 数字后面加 n 就是 BigInt 字面量。\n9.2 BigInt 的限制 BigInt 不能和普通 Number 直接混合运算：\n1n + 1 // ❌ TypeError 1n + 1n // ✅ 2n 10. 完整对比示例 10.1 在 2⁵³ 以内：完全正常 9007199254740990 + 1 // 9007199254740991 ✅ 9007199254740991 + 1 // 9007199254740992 ✅ 10.2 超过 2⁵³：开始出现跳格 9007199254740992 + 1 // 9007199254740992 ❌（+1 消失了） 9007199254740992 + 2 // 9007199254740994 ✅（间隔已变为 2） 11. 一句话总结 JavaScript 的 Number 是 64 位浮点数，不是 64 位整数。 浮点数只有 53 位有效精度，超过 2⁵³ − 1 之后，整数之间的间隔会逐渐扩大（2、4、8……），像 2**53 + 1 这样的数因为没有对应的精确存储位置，会被自动舍入到最近的可表示值。 如果需要处理超大整数，请使用 BigInt。 ","permalink":"https://june6699.github.io/posts/%E5%BB%96%E9%9B%AA%E5%B3%B0-javascript-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-0.1--%E6%95%B0%E5%AD%97%E7%B2%BE%E5%BA%A6/","summary":"\u003ch2 id=\"1-为什么整数安全范围是-2而不是-2\"\u003e1. 为什么整数安全范围是 ±2⁵³，而不是 ±2⁶³？\u003c/h2\u003e\n\u003cp\u003e因为 JavaScript 里的 \u003ccode\u003eNumber\u003c/code\u003e \u003cstrong\u003e不是整数类型\u003c/strong\u003e，而是 \u003cstrong\u003e64 位双精度浮点数\u003c/strong\u003e（IEEE 754 double）。\u003c/p\u003e\n\u003cp\u003e这两种\u0026quot;64 位\u0026quot;的本质区别是：\u003c/p\u003e","tags":["技术","技术/前端","技术/前端/JavaScript"],"title":"廖雪峰 JavaScript 学习笔记 —— 数字精度"},{"content":" 豫章故郡，洪都新府。星分翼轸，地接衡庐。\n襟三江而带五湖，控蛮荆而引瓯越。\n物华天宝，龙光射牛斗之墟；人杰地灵，徐孺下陈蕃之榻。\n雄州雾列，俊采星驰。台隍枕夷夏之交，宾主尽东南之美。\n都督阎公之雅望，棨戟遥临；宇文新州之懿范，襜帷暂驻。\n十旬休假，胜友如云；千里逢迎，高朋满座。\n腾蛟起凤，孟学士之词宗；紫电青霜，王将军之武库。\n家君作宰，路出名区；童子何知，躬逢胜饯。\n时维九月，序属三秋。潦水尽而寒潭清，烟光凝而暮山紫。\n俨骖騑于上路，访风景于崇阿；临帝子之长洲，得天人之旧馆。\n层峦耸翠，上出重霄；飞阁流丹，下临无地。\n鹤汀凫渚，穷岛屿之萦回；桂殿兰宫，即冈峦之体势。\n披绣闼，俯雕甍；山原旷其盈视，川泽纡其骇瞩。\n闾阎扑地，钟鸣鼎食之家；舸舰弥津，青雀黄龙之舳。\n云销雨霁，彩彻区明。落霞与孤鹜齐飞，秋水共长天一色。\n渔舟唱晚，响穷彭蠡之滨；雁阵惊寒，声断衡阳之浦。\n遥襟甫畅，逸兴遄飞。爽籁发而清风生，纤歌凝而白云遏。\n睢园绿竹，气凌彭泽之樽；邺水朱华，光照临川之笔。\n四美具，二难并。穷睇眄于中天，极娱游于暇日。\n天高地迥，觉宇宙之无穷；兴尽悲来，识盈虚之有数。\n望长安于日下，目吴会于云间。\n地势极而南溟深，天柱高而北辰远。\n关山难越，谁悲失路之人；萍水相逢，尽是他乡之客。\n怀帝阍而不见，奉宣室以何年？\n呜呼！时运不齐，命途多舛。冯唐易老，李广难封。\n屈贾谊于长沙，非无圣主；窜梁鸿于海曲，岂乏明时？\n所赖君子见机，达人知命。老当益壮，宁移白首之心？\n穷且益坚，不坠青云之志。\n酌贪泉而觉爽，处涸辙以犹欢。\n北海虽赊，扶摇可接；东隅已逝，桑榆非晚。\n孟尝高洁，空余报国之情；阮籍猖狂，岂效穷途之哭！\n勃，三尺微命，一介书生。\n无路请缨，等终军之弱冠；有怀投笔，慕宗悫之长风。\n舍簪笏于百龄，奉晨昏于万里。非谢家之宝树，接孟氏之芳邻。\n他日趋庭，叨陪鲤对；今兹捧袂，喜托龙门。\n杨意不逢，抚凌云而自惜；钟期既遇，奏流水以何惭？\n呜乎！胜地不常，盛筵难再；兰亭已矣，梓泽丘墟。\n临别赠言，幸承恩于伟饯；登高作赋，是所望于群公。\n敢竭鄙怀，恭疏短引；一言均赋，四韵俱成。\n请洒潘江，各倾陆海云尔。\n滕王高阁临江渚，佩玉鸣鸾罢歌舞。\n画栋朝飞南浦云，珠帘暮卷西山雨。\n闲云潭影日悠悠，物换星移几度秋。\n阁中帝子今何在？槛外长江空自流。\n唐·王勃\n这里是过去的豫章郡，如今的洪都府。此地的星空分属翼、轸二星的区域，地域连接着衡山和庐山。以三江为衣襟，以五湖为衣带，控制着楚地，接引着瓯越。这里有珍贵的物产和天然的宝藏，龙泉剑的光芒直射到牛、斗二星之间的区域；人才杰出，山川灵秀，徐孺子曾使陈蕃专为他设下坐榻。雄伟的州郡像云雾一样罗列，杰出的人才如流星般飞驰。城池坐落在夷夏交界的地方，宾客和主人都是东南一带的俊杰。都督阎公有着崇高的声望，仪仗从远方到来；宇文新州有着美好的风范，车马暂时停留。正逢十日休假的日子，优秀的友人云集；迎接千里而来的宾客，高贵的朋友坐满宴席。文章的辞采如蛟龙腾空、凤凰飞起，那是文坛宗主孟学士；兵器如紫电青霜般锋利，那是王将军的武库。我的父亲在交趾做县令，我路过这个有名的地区；我年幼无知，却有幸亲身参加这场盛大的宴会。时间是九月，季节属于深秋。雨后的积水消尽，寒凉的水潭清澈见底，烟雾凝聚，傍晚的山峦呈现出紫色。在高高的道路上整治车马，到高大的山岭中寻访风景；来到帝子曾居住的长洲，登上仙人昔日的馆阁。层层叠叠的山峦耸立着青翠的颜色，向上直插云霄；凌空的楼阁涂有鲜艳的丹漆，向下临视仿佛没有地面。鹤栖息的汀洲、野鸭聚居的小洲，极尽岛屿曲折回环的景致；桂木、兰木建造的宫殿，顺着冈峦的地势而建。推开精美的阁门，俯视雕饰的屋脊；辽阔的山野平原尽收眼底，纡回的江河湖泽令人看了惊叹。房屋遍地，都是鸣钟列鼎而食的富贵人家；船只停满渡口，都是青雀黄龙形状的船身。云消雨停，阳光普照，天空明朗。晚霞与孤单的野鸭一同飞翔，秋天的江水和辽阔的天空连成一片。渔舟在傍晚唱起歌，歌声传遍彭蠡湖畔；雁群因寒意而惊起，叫声到衡阳的水边便中断了。胸襟刚感到舒畅，超逸的兴致随即兴起。清脆的排箫声响起，清风随之而生；柔美的歌声缭绕不散，白云也为之停住。像睢园的绿竹宴一样，饮酒的豪气超过了陶渊明；像邺水咏荷花那样，文采比得上谢灵运。良辰、美景、赏心、乐事四美俱全，贤主、嘉宾二难齐备。向天空放眼远望，在闲暇的日子里尽情游乐。天高地远，感到宇宙的无边无际；兴致已尽，悲愁随之而来，认识到事物的兴衰成败皆有定数。望向夕阳下的长安，遥看云雾间的吴会。地势偏远，南海深邃；天柱高耸，北极星遥远。关山难以逾越，有谁同情不得志的人；偶然相逢，全是他乡的过客。怀念君王却不得召见，什么时候才能像贾谊那样在宣室被召见？唉！时机不好，命运多舛。冯唐容易老去，李广难以封侯。使贾谊遭受委屈，贬到长沙，并非没有圣明的君主；使梁鸿逃到海边，难道不是在政治昌明的时代？所依靠的是君子能察觉事物的先兆，通达的人知道自己的命运。年纪虽老但志气更壮，怎能在白头时改变心意？处境虽穷但意志更坚定，不放弃远大崇高的志向。喝了贪泉的水，反而觉得清爽；处在干涸的车辙中，还能保持欢乐。北海虽然遥远，乘着旋风仍能到达；早年的时光虽然逝去，珍惜晚年也不算晚。孟尝品行高洁，却空有一腔报国的热情；阮籍狂放不羁，难道要效仿他在无路可走时便恸哭吗！我王勃，地位卑微，只是一个书生。没有门路请缨报国，如同终军一样年纪轻轻；有投笔从戎的志向，羡慕宗悫那种“乘长风破万里浪”的抱负。舍弃一生的功名富贵，到万里之外去侍奉父母。我不是谢玄那样的优秀人才，却能结识各位贤才。不久将要到父亲身边接受教诲，今天有幸登上龙门。没有遇到杨得意那样引荐的人，只能抚惜自己的文章独自叹惜；既然遇到钟子期那样的知音，演奏高山流水的乐曲又有什么惭愧的呢？唉！名胜之地不能常存，盛大的宴会难以再遇；兰亭集会的盛况已成过往，金谷园也已成废墟。临别时写下这篇赠言，有幸蒙受这次盛宴的恩泽；登高作赋，这是期望在座的诸位贵宾。斗胆竭尽我浅薄的情怀，恭敬地写下这篇小序；每人都赋诗一首，我的四韵诗也已写成。请诸位展露潘岳、陆机那样的文才，各自抒发华美的文采吧。滕王阁高高地靠着江边，佩玉、鸾铃的声音停息，歌舞已经结束。早晨，画栋飞上了南浦的云；傍晚，珠帘卷入了西山的雨。悠闲的云朵在潭水中的影子，一天天悠然自在，事物变换，星辰移动，度过了多少个春秋。阁中的滕王如今在哪里？栏杆外的长江，空自滚滚东流。\n","permalink":"https://june6699.github.io/posts/%E6%BB%95%E7%8E%8B%E9%98%81%E5%BA%8F/","summary":"\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e豫章故郡，洪都新府。星分翼轸，地接衡庐。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e襟三江而带五湖，控蛮荆而引瓯越。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e物华天宝，龙光射牛斗之墟；人杰地灵，徐孺下陈蕃之榻。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e雄州雾列，俊采星驰。台隍枕夷夏之交，宾主尽东南之美。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e都督阎公之雅望，棨戟遥临；宇文新州之懿范，襜帷暂驻。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e十旬休假，胜友如云；千里逢迎，高朋满座。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e腾蛟起凤，孟学士之词宗；紫电青霜，王将军之武库。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e家君作宰，路出名区；童子何知，躬逢胜饯。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e时维九月，序属三秋。潦水尽而寒潭清，烟光凝而暮山紫。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e俨骖騑于上路，访风景于崇阿；临帝子之长洲，得天人之旧馆。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e层峦耸翠，上出重霄；飞阁流丹，下临无地。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e鹤汀凫渚，穷岛屿之萦回；桂殿兰宫，即冈峦之体势。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e披绣闼，俯雕甍；山原旷其盈视，川泽纡其骇瞩。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e闾阎扑地，钟鸣鼎食之家；舸舰弥津，青雀黄龙之舳。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e云销雨霁，彩彻区明。落霞与孤鹜齐飞，秋水共长天一色。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e渔舟唱晚，响穷彭蠡之滨；雁阵惊寒，声断衡阳之浦。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e遥襟甫畅，逸兴遄飞。爽籁发而清风生，纤歌凝而白云遏。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e睢园绿竹，气凌彭泽之樽；邺水朱华，光照临川之笔。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e四美具，二难并。穷睇眄于中天，极娱游于暇日。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e天高地迥，觉宇宙之无穷；兴尽悲来，识盈虚之有数。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e望长安于日下，目吴会于云间。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e地势极而南溟深，天柱高而北辰远。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e关山难越，谁悲失路之人；萍水相逢，尽是他乡之客。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e怀帝阍而不见，奉宣室以何年？\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e呜呼！时运不齐，命途多舛。冯唐易老，李广难封。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e屈贾谊于长沙，非无圣主；窜梁鸿于海曲，岂乏明时？\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e所赖君子见机，达人知命。老当益壮，宁移白首之心？\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e穷且益坚，不坠青云之志。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e酌贪泉而觉爽，处涸辙以犹欢。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e北海虽赊，扶摇可接；东隅已逝，桑榆非晚。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e孟尝高洁，空余报国之情；阮籍猖狂，岂效穷途之哭！\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e勃，三尺微命，一介书生。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e无路请缨，等终军之弱冠；有怀投笔，慕宗悫之长风。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e舍簪笏于百龄，奉晨昏于万里。非谢家之宝树，接孟氏之芳邻。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e他日趋庭，叨陪鲤对；今兹捧袂，喜托龙门。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e杨意不逢，抚凌云而自惜；钟期既遇，奏流水以何惭？\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e呜乎！胜地不常，盛筵难再；兰亭已矣，梓泽丘墟。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e临别赠言，幸承恩于伟饯；登高作赋，是所望于群公。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e敢竭鄙怀，恭疏短引；一言均赋，四韵俱成。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e请洒潘江，各倾陆海云尔。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e滕王高阁临江渚，佩玉鸣鸾罢歌舞。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e画栋朝飞南浦云，珠帘暮卷西山雨。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e闲云潭影日悠悠，物换星移几度秋。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e阁中帝子今何在？槛外长江空自流。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e唐·王勃\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e这里是过去的豫章郡，如今的洪都府。此地的星空分属翼、轸二星的区域，地域连接着衡山和庐山。以三江为衣襟，以五湖为衣带，控制着楚地，接引着瓯越。这里有珍贵的物产和天然的宝藏，龙泉剑的光芒直射到牛、斗二星之间的区域；人才杰出，山川灵秀，徐孺子曾使陈蕃专为他设下坐榻。雄伟的州郡像云雾一样罗列，杰出的人才如流星般飞驰。城池坐落在夷夏交界的地方，宾客和主人都是东南一带的俊杰。都督阎公有着崇高的声望，仪仗从远方到来；宇文新州有着美好的风范，车马暂时停留。正逢十日休假的日子，优秀的友人云集；迎接千里而来的宾客，高贵的朋友坐满宴席。文章的辞采如蛟龙腾空、凤凰飞起，那是文坛宗主孟学士；兵器如紫电青霜般锋利，那是王将军的武库。我的父亲在交趾做县令，我路过这个有名的地区；我年幼无知，却有幸亲身参加这场盛大的宴会。时间是九月，季节属于深秋。雨后的积水消尽，寒凉的水潭清澈见底，烟雾凝聚，傍晚的山峦呈现出紫色。在高高的道路上整治车马，到高大的山岭中寻访风景；来到帝子曾居住的长洲，登上仙人昔日的馆阁。层层叠叠的山峦耸立着青翠的颜色，向上直插云霄；凌空的楼阁涂有鲜艳的丹漆，向下临视仿佛没有地面。鹤栖息的汀洲、野鸭聚居的小洲，极尽岛屿曲折回环的景致；桂木、兰木建造的宫殿，顺着冈峦的地势而建。推开精美的阁门，俯视雕饰的屋脊；辽阔的山野平原尽收眼底，纡回的江河湖泽令人看了惊叹。房屋遍地，都是鸣钟列鼎而食的富贵人家；船只停满渡口，都是青雀黄龙形状的船身。云消雨停，阳光普照，天空明朗。晚霞与孤单的野鸭一同飞翔，秋天的江水和辽阔的天空连成一片。渔舟在傍晚唱起歌，歌声传遍彭蠡湖畔；雁群因寒意而惊起，叫声到衡阳的水边便中断了。胸襟刚感到舒畅，超逸的兴致随即兴起。清脆的排箫声响起，清风随之而生；柔美的歌声缭绕不散，白云也为之停住。像睢园的绿竹宴一样，饮酒的豪气超过了陶渊明；像邺水咏荷花那样，文采比得上谢灵运。良辰、美景、赏心、乐事四美俱全，贤主、嘉宾二难齐备。向天空放眼远望，在闲暇的日子里尽情游乐。天高地远，感到宇宙的无边无际；兴致已尽，悲愁随之而来，认识到事物的兴衰成败皆有定数。望向夕阳下的长安，遥看云雾间的吴会。地势偏远，南海深邃；天柱高耸，北极星遥远。关山难以逾越，有谁同情不得志的人；偶然相逢，全是他乡的过客。怀念君王却不得召见，什么时候才能像贾谊那样在宣室被召见？唉！时机不好，命运多舛。冯唐容易老去，李广难以封侯。使贾谊遭受委屈，贬到长沙，并非没有圣明的君主；使梁鸿逃到海边，难道不是在政治昌明的时代？所依靠的是君子能察觉事物的先兆，通达的人知道自己的命运。年纪虽老但志气更壮，怎能在白头时改变心意？处境虽穷但意志更坚定，不放弃远大崇高的志向。喝了贪泉的水，反而觉得清爽；处在干涸的车辙中，还能保持欢乐。北海虽然遥远，乘着旋风仍能到达；早年的时光虽然逝去，珍惜晚年也不算晚。孟尝品行高洁，却空有一腔报国的热情；阮籍狂放不羁，难道要效仿他在无路可走时便恸哭吗！我王勃，地位卑微，只是一个书生。没有门路请缨报国，如同终军一样年纪轻轻；有投笔从戎的志向，羡慕宗悫那种“乘长风破万里浪”的抱负。舍弃一生的功名富贵，到万里之外去侍奉父母。我不是谢玄那样的优秀人才，却能结识各位贤才。不久将要到父亲身边接受教诲，今天有幸登上龙门。没有遇到杨得意那样引荐的人，只能抚惜自己的文章独自叹惜；既然遇到钟子期那样的知音，演奏高山流水的乐曲又有什么惭愧的呢？唉！名胜之地不能常存，盛大的宴会难以再遇；兰亭集会的盛况已成过往，金谷园也已成废墟。临别时写下这篇赠言，有幸蒙受这次盛宴的恩泽；登高作赋，这是期望在座的诸位贵宾。斗胆竭尽我浅薄的情怀，恭敬地写下这篇小序；每人都赋诗一首，我的四韵诗也已写成。请诸位展露潘岳、陆机那样的文才，各自抒发华美的文采吧。滕王阁高高地靠着江边，佩玉、鸾铃的声音停息，歌舞已经结束。早晨，画栋飞上了南浦的云；傍晚，珠帘卷入了西山的雨。悠闲的云朵在潭水中的影子，一天天悠然自在，事物变换，星辰移动，度过了多少个春秋。阁中的滕王如今在哪里？栏杆外的长江，空自滚滚东流。\u003c/p\u003e\n\u003c/div\u003e","tags":["诗","诗/名篇"],"title":"滕王阁序"},{"content":"2026.3.2 —— 2026.3.8 2026.3.2 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 5 5 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 15 2026.3.4 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 5 5 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 15 2026.3.7 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 5 5 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 25 2026.3.9 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 5 5 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 15 Group6 0 0 20 2026.3.11 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 7 3 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 15 Group6 0 0 20 2026.3.15 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 1 10 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 25 2026.3.18 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 8 10 15 Group3 0 10 15 Group4 0 10 15 Group5 1 10 20 2026.3.20 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 1 10 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 15 2026.3.23 引体向上 引体卷腹 俯卧撑 Group1 15 0 15 Group2 10 0 15 Group3 6 8 15 Group4 0 10 15 Group5 2 10 15 2026.4.3 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 10 0 15 Group3 0 10 0 Group4 Group5 2026.4.5 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 10 0 15 Group3 10 0 15 Group4 0 10 15 Group5 5 5 30 2026.4.12 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 10 0 15 Group3 0 10 15 Group4 0 10 15 Group5 0 10 15 2026.4.15 引体向上 引体卷腹 俯卧撑 Group1 10 15 Group2 10 15 Group3 10 15 Group4 6 5 15 Group5 4 6 30 2026.4.23 今天状态好\n引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 10 0 15 Group3 10 0 15 Group4 10 0 15 Group5 8 0 25 2026.4.25 今天状态不好，手酸\n引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 10 0 15 Group3 8 2 15 Group4 6 4 20 Group5 2026.4.30 引体向上 引体卷腹 俯卧撑 Group1 10 0 15 Group2 10 0 15 Group3 10 0 15 Group4 6 4 15 Group5 0 10 15 引体向上 引体卷腹 俯卧撑 Group1 Group2 Group3 Group4 Group5 ","permalink":"https://june6699.github.io/posts/%E9%94%BB%E7%82%BC%E8%AE%B0%E5%BD%95/","summary":"\u003ch3 id=\"202632--202638\"\u003e2026.3.2 —— 2026.3.8\u003c/h3\u003e\n\u003ch4 id=\"202632\"\u003e2026.3.2\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"202634\"\u003e2026.3.4\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"202637\"\u003e2026.3.7\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e25\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"202639\"\u003e2026.3.9\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup6\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e20\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026311\"\u003e2026.3.11\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e7\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup6\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e20\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026315\"\u003e2026.3.15\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e25\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026318\"\u003e2026.3.18\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e8\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e20\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026320\"\u003e2026.3.20\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026323\"\u003e2026.3.23\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e6\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e8\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"202643\"\u003e2026.4.3\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"202645\"\u003e2026.4.5\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e30\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026412\"\u003e2026.4.12\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e0\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026415\"\u003e2026.4.15\u003c/h4\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体向上\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e引体卷腹\u003c/th\u003e\n\t\t\t\t\t\u003cth style=\"text-align: center\"\u003e俯卧撑\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup1\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup2\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup3\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e10\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e6\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e15\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003eGroup5\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e4\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e6\u003c/td\u003e\n\t\t\t\t\t\u003ctd style=\"text-align: center\"\u003e30\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch4 id=\"2026423\"\u003e2026.4.23\u003c/h4\u003e\n\u003cp\u003e今天状态好\u003c/p\u003e","tags":["生活","生活/记录","生活/记录/锻炼"],"title":"锻炼记录"},{"content":"0、总言 这是想做做饭的第n天，这篇文章用来记录，自己回家想吃什么，以及通过网络或其他渠道学到的做饭技巧和步骤。\n一、想吃的 二、学习的 2.1 牛排 留子一条视频解决你所有煎牛排问题_哔哩哔哩_bilibili 关键词：干腌、表面干燥、油温临界点、晃锅测试、黄油香料淋油、配菜吸收锅底风味\n2.1.1 配料和食材 主菜：一块厚牛排（视频里约 3 cm 厚）\n配菜：芦笋、口蘑\n香料：大蒜、百里香、迷迭香\n油脂：菜籽油、黄油\n调味：盐、黑胡椒；也可以用鸡精或味精替代一部分盐来增加鲜味\n工具：厨房纸、锡纸、夹子或筷子、勺子、盘子或木板\n2.1.2 步骤 提前一天干腌：用厨房纸擦干牛排表面水分，两面均匀撒盐。严格一点可以按牛排重量的 3% 放盐；不称重就薄薄撒一层。 撒完盐之后把牛排揉匀，再用至少四层厨房纸包住，放冰箱冷藏一晚。目的不是“入味玄学”，而是让盐把表面水分拔出来，让第二天下锅时更容易形成焦壳。 如果想要更明显的鲜味，可以把一部分盐换成鸡精或味精。注意顺序还是先擦干，再调味，再包厨房纸冷藏。 处理芦笋：芦笋底部通常比较老，可以直接切掉下方 1/3；不舍得切的话，用刮皮刀把中段以下的外皮刮掉。 准备香料：大蒜不用剥皮，直接拍一下或压开即可；迷迭香和百里香不用太多，香味很强，够给黄油增香就行。 热锅热油：锅不挑，平底锅、圆底锅都可以。油可以任何时候下，但量要比平时炒菜略多一点，方便牛排表面接触热油。 判断油温：核心是找到“接近烟点但还没冒烟”的状态。看到油开始冒烟，就说明火太大了，要调小。 第一面下锅：牛排下锅后先等约 1 分钟，不要急着扒拉。表面足够干的牛排不会疯狂溅油，也更容易离锅。 晃锅测试：轻轻晃锅，如果牛排能自己离开原来的位置，说明美拉德反应至少已经开始。这时可以抬起来看焦壳。 补焦壳：如果某一块地方颜色不够，就翻回去继续煎那一块。只要下面有热油，温度够，就能继续补美拉德反应。 封边：厚牛排需要把侧边也煎到变色、形成外壳。这样可以减少汁水从边缘渗出。 加黄油和香料：两面和侧边都有焦壳之后，把火调小，加入黄油、大蒜、迷迭香和百里香。黄油容易糊，宁可火低一点，也不要猛火烧焦。 黄油香料淋油：等黄油融化并把香料味炸出来，用勺子反复把热黄油浇到牛排上。锅可以倾斜，让油集中到一侧，牛排放另一侧。 控制淋油时间：视频里的 3 cm 厚牛排大约淋 1 分半。如果想吃更熟，就多淋一会儿，因为这一步是在温和地给牛排内部补温度。 香料上肉：想要香味更明显，可以把香料直接放到牛排表面，再用黄油浇香料，让香味留在牛排上。 锡纸焖熟：牛排煎到目标状态前后，用锡纸轻轻盖住，不要压死，留一点小气孔排水蒸气。 回锅复脆：焖过之后表面会变湿。切之前可以把香料拿掉，大火短时间回锅，让表壳重新变脆，时间大约十几秒到二十秒。 切牛排：不要在最终摆盘的盘子里切，汁水会流得到处都是。先在砧板或临时盘上切好，再转移到正式盘子。 2.1.3 配菜 芦笋：牛排出锅后，锅里有黄油、牛油和香料味，直接下芦笋。先开大火让油升温，看到快冒烟就调小。 让芦笋尽量铺开，每一根都接触到锅底的油。火可以略大一点，但不要把黄油烧糊。 不必死记时间，频繁观察表面。看到芦笋出现焦化斑、颜色变深，就是比较好的状态。 芦笋出锅后先放在垫了厨房纸的盘子上控油，最后再调味。 口蘑：先让开口的那一面朝下煎，把表面煎熟；再翻过来，等蘑菇自己的汁水慢慢填满。 口蘑不需要很大火，先把蘑菇煎熟、煎出汁水即可。锅里的油如果一直清亮，说明火力控制得不错，没有超过黄油的糊点。 2.1.4 摆盘和调味 盘子可以用大白瓷盘，也可以用木板。有烤箱、蒸箱或热盘炉的话，可以提前温一下盘子，避免牛排很快变凉。 切好的牛排转移到盘子上，用刀背轻轻推开，让切面露出来。 想拍照的话，可以放一根新鲜迷迭香，再把刚才炸过的大蒜放旁边。 配菜放在旁边，不要让汁水把白盘弄得太乱。 因为干腌时已经加盐，最后先尝牛肉本味。如果觉得不够，再补黑胡椒和盐。 2.1.5 我理解的关键点 牛排煎得好不好，第一关键不是锅多贵，而是表面够不够干。 油温要卡在接近冒烟但还没有明显冒烟的临界点，太低没有焦壳，太高容易糊。 不要靠玄学时间表判断美拉德反应，要靠 晃锅测试 和焦壳颜色判断。 黄油不是一开始就下，它负责后段增香。先用耐高温油煎焦壳，再用黄油和香料补风味。 配菜不是另起炉灶，而是利用牛排锅里的油脂和香料味，顺手完成。 摆盘也很重要：不要在正式盘子里切牛排，切完再摆，视觉上会干净很多。 ","permalink":"https://june6699.github.io/posts/%E5%AD%A6%E4%B9%A0%E5%81%9A%E9%A5%AD/","summary":"\u003ch2 id=\"0总言\"\u003e0、总言\u003c/h2\u003e\n\u003cp\u003e这是想做做饭的第n天，这篇文章用来记录，自己回家想吃什么，以及通过网络或其他渠道学到的做饭技巧和步骤。\u003c/p\u003e\n\u003ch2 id=\"一想吃的\"\u003e一、想吃的\u003c/h2\u003e\n\u003ch2 id=\"二学习的\"\u003e二、学习的\u003c/h2\u003e\n\u003ch3 id=\"21-牛排\"\u003e2.1 牛排\u003c/h3\u003e\n\u003cp\u003e\u003ca href=\"https://www.bilibili.com/video/BV1nBdvBzEmb/?spm_id_from=333.1391.0.0\u0026amp;vd_source=76a6f89f0900bd443ef08648e4c92f12\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e留子一条视频解决你所有煎牛排问题_哔哩哔哩_bilibili\u003c/a\u003e\n\u003c/p\u003e","tags":["生活","生活/记录","生活/记录/做饭"],"title":"学习做饭"},{"content":"📌 ② LiMCA — Nature Methods, 2024 Wu H, Zhang J, Jian F, et al. “Simultaneous single-cell three-dimensional genome and gene expression profiling uncovers dynamic enhancer connectivity underlying olfactory receptor choice.” Nat Methods 21, 974–982 (2024)\nhttps://www.nature.com/articles/s41592-024-02239-0 亮点： LiMCA（Linking mRNA to Chromatin Architecture）通过物理分离同一细胞的细胞质（mRNA）和细胞核（染色质），实现了对 3D 基因组结构和转录组的高灵敏度联合检测。研究者将 LiMCA 与他们开发的高分辨率 scATAC-seq 方法（METATAC）结合，成功解析了单个嗅觉感觉神经元发育过程中的染色质可及性、3D 基因组结构和基因表达信息，扩展了已知的嗅觉受体增强子库，揭示了“一个神经元—一个受体”选择过程背后动态的空间调控规律。\n组学组合：scHi-C + scRNA-seq + scATAC-seq（三组学联合） 创新性：灵敏度极高；三组学同细胞联合揭示增强子调控新规则 期刊：Nature Methods（方法学顶刊） ","permalink":"https://june6699.github.io/posts/article2_limca_hic+rna_atac/","summary":"\u003ch3 id=\"--limca--nature-methods-2024\"\u003e📌 ② LiMCA — \u003cem\u003eNature Methods\u003c/em\u003e, 2024\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003eWu H, Zhang J, Jian F, et al. “Simultaneous single-cell three-dimensional genome and gene expression profiling uncovers dynamic enhancer connectivity underlying olfactory receptor choice.” \u003cem\u003eNat Methods\u003c/em\u003e 21, 974–982 (2024)\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.nature.com/articles/s41592-024-02239-0\" target=\"_blank\" rel=\"noopener noreferrer\"\u003ehttps://www.nature.com/articles/s41592-024-02239-0\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e亮点：\u003c/strong\u003e LiMCA（Linking mRNA to Chromatin Architecture）通过物理分离同一细胞的细胞质（mRNA）和细胞核（染色质），实现了对 3D 基因组结构和转录组的高灵敏度联合检测。研究者将 LiMCA 与他们开发的高分辨率 scATAC-seq 方法（METATAC）结合，成功解析了单个嗅觉感觉神经元发育过程中的染色质可及性、3D 基因组结构和基因表达信息，扩展了已知的嗅觉受体增强子库，揭示了“一个神经元—一个受体”选择过程背后动态的空间调控规律。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/论文"],"title":"同步单细胞三维基因组与基因表达谱分析揭示了嗅觉受体选择背后动态增强子连接机制"},{"content":"📌 ① HiRES — Science, 2023 https://www.science.org/doi/10.1126/science.adg3797 Liu Z, Chen Y, Xia Q, et al. \u0026ldquo;Linking genome structures to functions by simultaneous single-cell Hi-C and RNA-seq.\u0026rdquo; *Science* 380, 1070–1076 (2023)\n亮点： 1这是首篇真正实现单细胞水平同时测量染色质三维构象和基因表达的方法论文。作者开发了 HiRES（Hi-C and RNA-seq Employed Simultaneously）技术，并应用于数千个小鼠发育胚胎单细胞。研究发现，三维基因组结构在高度受细胞周期影响的同时，会随发育进程以细胞类型特异性方式逐渐分化。通过比较染色质互作与转录的拟时序动态，他们发现了广泛的\u0026quot;染色质重塑先于转录激活\u0026quot;现象，证明特异性染色质互作与谱系分化过程中的转录调控密切相关。\n组学组合：scHi-C + scRNA-seq（同一细胞） 创新性：首次实现两者同步，揭示\u0026quot;结构先于功能\u0026quot;的普遍规律 期刊：Science（顶刊） 结合我们的课题 如其标题所说，他通过对单细胞同时测HIC和RNA-seq，来分析bin之间的互作与基因表达，是否有相关性（HiRES技术）。有研究分别做HIC和RNA-seq，然后把两个数据里面的细胞类型进行匹配，联合分析。但是因为他们不是来自于同一个细胞，所以这种整合可能会错误的把3D基因组状态与转录路组状态关联起来（而且发育中，3D结构变化不一定和转录组变化是同步的），这对于我们的课题有一定警示意义，我们就不是来自同一个细胞的。如把还没变化的 3D 结构配给了已经变化的表达，或者反过来。因此，在我们肾脏课题中，需要谨慎解释结果。\n1、原理 图1\n第一步：原位逆转录（In situ Reverse Transcription） 细胞不裂解，直接在细胞内部进行逆转录 RNA → cDNA（互补DNA） 关键技巧：逆转录引物上带有mRNA特异性标签，这个标签后来用于计算机区分 RNA 和 DNA 的读段 细胞内同时存在：原始基因组 DNA + 新合成的 cDNA 第二步：原位 Hi-C（In situ Hi-C） 原理：空间上靠近的 DNA 片段会被交联、酶切、末端补平、生物素标记，再连接在一起 连接产物反映了细胞核内哪些基因组区域在空间上是\u0026quot;邻居\u0026quot; 第三步：流式分选（Flow Sorting） 将处理好的细胞一个一个分选到多孔板的每个孔里，保证每孔只有一个细胞，实现真正的单细胞分辨率 第四步：准线性扩增（Quasi-linear Amplification / MALBAC-DT 类策略） 这是 HiRES 的核心创新，单个细胞的 DNA/RNA 量极少，必须扩增才能测序\n包含多轮退火和环状化扩增循环，相比纯指数扩增（PCR），线性扩增的偏差更小，覆盖更均匀（图 1B）\n在同一管反应中同时扩增 DNA 和 cDNA，无需分管\n第五步：计算机辅助区分 RNA vs DNA 读段 测序后，根据第一步引入的 mRNA 特异性标签，用生物信息学方法区分： 带标签 → RNA 来源的读段（RNA-seq） 不带标签 → 基因组 DNA 来源的读段（Hi-C） 无需物理分离 RNA 和 DNA！这避免了样本损失 可靠的结果 图 1D可见聚类分析，下图揭示了RNA聚类注释与HIC聚类注释结果高度一致（图 S1-I）。\n使用 HiRES 的 Hi-C 数据，对每个细胞重建结构，代表性的如S2 A-C，其中染色体区域（A）、AB区室（B，CpG频率高的代表转录活跃，属于A compartment，为绿色）、径向偏好（C，细胞核里不同的DNA区域有各自固定的\u0026quot;位置偏好\u0026quot;——活跃基因倾向待在核中心，沉默基因倾向待在核边缘）。\n图 1F左右图分别展示了单细胞3D基因组结构和基因表达的关系（黄球越大表达越高），说明转录基因总喜欢在更活跃的染色质环境中。\n2、HIC数据分析 2.1 注释 图 2A中是RNA数据的注释结果（ExE，胚外细胞；EPI，上胚层和原条；NMP，神经中胚层祖细胞；OPC，少突胶质细胞前体细胞）。 有四个主要细胞群，包括胚胎组织、胚外内胚层、胚外外胚层和血液，还有一个处于有丝分裂期的细胞群（Mitotic Cell）。 原文 中文翻译 胚层 Neural ectoderm 神经外胚层 外胚层 NMP 神经中胚层祖细胞 — Neural tube 神经管 外胚层 Radial glia 放射状胶质细胞 外胚层 OPC 少突胶质前体细胞 外胚层 Early neuron 早期神经元 外胚层 Early mesoderm 早期中胚层 中胚层 ExE mesoderm 胚外中胚层 中胚层 Early mesenchyme 早期间充质 中胚层 Intermediate mesoderm 中间中胚层 中胚层 Myocyte 肌细胞 中胚层 Mix late mesenchyme 混合晚期间充质 中胚层 图 2B是HIC包含四个细胞群的注释，且图 3C可见外胚层（蓝色）和中胚层（红色）在一开始比较混合，之后彼此分离（E7.5-E11.5），证明染色质构象作为基因表达支架的作用在早期发育中是保守的。 2.2 马鞍图展示分化中3D构象的变化 B区室是基因组中转录沉默、染色质压缩的区域（异染色质）。\n随着胚胎发育，细胞命运逐渐确定，那些需要被永久关闭的基因所在区域会被\u0026quot;贴上\u0026quot;异染色质标记，归入B区室；这些B区室区域在细胞核内倾向于物理上聚集在一起（尤其是锚定在核膜内表面），就像油滴在水中会自发汇聚一样——这一过程由相分离驱动。 因此随着发育时间推进，越来越多的区域变成B区室，且这些B区室彼此靠近聚集，在Hi-C数据中就表现为B-B之间的接触频率持续升高。 本质上，B-B互作增多反映的是细胞在分化过程中对\u0026quot;不需要的基因\u0026quot;进行集中封存的过程。 2.3 细胞周期对三维基因组结构的影响远大于对转录的影响 在图2 D中的放射状胶质细胞簇可见，上面RNA的聚类很密集，而下面HIC的聚类很分散，把下面HIC簇的细胞RNA表达数据提取并进行差异表达分析，GO显示富集到很多细胞周期通路。\nQ1：那么为什么处在不同细胞周期的放射状胶质细胞，其HIC接触矩阵差异很大呢？ A1：因为不同细胞周期的染色体构象差异显著。 比如G0/G1期需要大量转录基因、合成蛋白质等准备工作，所以染色质需要展开以便转录因子、RNA聚合酶等接触到DNA； 而S期要局部开放，以便DNA能够有序推进，而又不至于全开导致乱成一团； M期需极度压缩，如果不压缩，46条染色体（以人为例）互相缠绕，纺锤丝根本抓不住每条染色体整齐拉向两极。 Q2：那么为什么RNA又那么整齐？ A2：因为RNA聚类靠的是基因表达，标记的是细胞类型（细胞身份本身），而非细胞的状态，他们的RNA表达足够相似。 重要 综上，研究细胞周期背景下三维基因组动态的变化非常重要。\n3、HiRES捕获的细胞周期动态 3.1 HIC接触数据定义细胞周期阶段 作者团队开发了一种基于DNA和RNA数据将单细胞分配到七个细胞周期阶段的策略，每个阶段都具有独特的细胞周期基因表达、DNA复制和接触分布特征（图S6 A、B）。\n图2 E显示，细胞周期呈连续转换，图2 F显示接触定义的簇与细胞周期阶段更一致，说明由细胞周期协调的染色质构象变化是整体三维基因组结构的主要贡献者。\n此外，每种细胞群特有的染色质组织必然在区分它们彼此之间以及与胚胎细胞群方面发挥了主导作用。因此，细胞类型特异性和细胞周期特异性的染色质相互作用在早期发育过程中共存，并共同塑造了单细胞三维基因组。\nF：热图显示三维基因组簇中与细胞周期或RNA定义的簇重叠的细胞比例。RNA细胞类型的编号与（A）相同。\n3.2 发育后期的细胞G1期长 发育后期的细胞不再需要快速增殖，G1期自然延长（图S6E显示G1期比例随发育增加）；G1期延长使染色质在有丝分裂结束后有更充足的时间重建三维结构（如TAD、长程互作），因此观察到发育后期细胞的平均长程接触更多（图S6D）。\n3.3 伪细胞周期 前面我们已经划分了七个细胞周期阶段，接下来，在每个细胞类型里面，我们先按这个细胞周期阶段排序分组（G0/G1/Early-S/Mid-S/Late-S/G2/M）。\n在每个阶段组内继续排序，因为每个细胞有一条contact decay曲线，计算每两个细胞之间的曲线形状差异（最小距离），然后找到一种排列顺序使得相邻细胞之间的差异最小。\n关于contact decay曲线：Hi-C测的是基因组上任意两个位点之间的互作频率，而两个位点在基因组上距离越远，互作越少。 在G1期（舒展），远距离位点处于分开状态，所以互作频率低，也就是该曲线下降很陡； 相反的，在M期（极度压缩），远近都被压缩，所以下降曲线会较平且缓慢。 因此通过这种曲线的对比，可以定义该细胞所处的详细细胞周期阶段。 互作频率 ↑ |█ | █ | █ | █ | █ | █ └─────────────────→ 两位点间的基因组距离 最后7组首尾相连，就得到了一个丝滑的染色质动态时间序列。\n3.4 错位对齐 对齐之后发现了一个错位现象：\n如神经外胚层的早期S期细胞与放射状胶质细胞的晚期G1期细胞对齐，而不是与早期S期细胞对齐。\n早期发育细胞的周期阶段X ↔ 晚期发育细胞的周期阶段X-1（滞后） 反过来也成立：晚期发育细胞超前于早期发育细胞 原因：因为早期发育细胞G1期短，上次的M期刚刚结束，染色质刚刚舒展一点就进入了S期，而晚期发育细胞有充足的G1期时间。\n且这种错位在早期S期最显著，之后减弱：\n过程 驱动力 作用 ① 有丝分裂后自发解折叠 染色质自身物理弹性 M期结束后染色体自然舒展，建立长程互作 ② DNA复制 复制机器推进 复制叉推进过程中积累大量短程互作 G1期只有过程①，染色质缓慢舒展； S期开始后，过程②开始，其产生的短程互作开始主导染色质结构。 而且该过程跨细胞类型保守，所以不同细胞类型的结构差异逐渐减小，错位逐渐消失。 重要 综上，对于G1期较短的细胞周期，这两个过程在时间上相互重叠，共同决定了三维基因组的细胞周期动态。\n4、将差异性染色质相互作用与基因表达联系起来 4.1 细胞类型特异性差异相互作用（DI） HiRES将每个细胞看做一个独立的样本，较 bulk-Hi-C 提高更高的统计功效，作者团队开发SimpleDiff流程解决scHi-C数据在千碱基分辨率下极其稀疏的问题。\n补充：普通做法是，计算ab位点在A和B-celltype中各自的互作次数，并比较。 SimpleDiff基本原理： 先重建三维结构：我们有很多个那些点对接触的信息，相当于a-b、c-d、b-d这种信息，这样就能根据相对位置推算出一个三维结构，得到每个基因组bin在细胞核的三维坐标。 有了坐标，使用欧几里得距离公式就能得到每个细胞里这两个bin的距离，这样每个细胞就都能给出一个值了，最后用Wilcoxon检验比较。 常规做法 A细胞类型：100个细胞里，5个检测到互作 → 频率 5% B细胞类型：100个细胞里，3个检测到互作 → 频率 3% SimpleDiff A细胞类型：100个细胞的距离值 → 0.3, 0.4, 0.35, 0.28...（100个数） B细胞类型：100个细胞的距离值 → 0.8, 0.9, 0.75, 0.85...（100个数） 4.2 DI富集特异标记基因 4.2.1 测试 用成年小鼠脑内两簇兴奋性和抑制性神经元之间的差异来测试SimpleDiff的性能和可靠性。\nSimpleDiff从4,849,385对20 kb基因组区间中识别出123,728个差异表达（DI），错误发现率（FDR）\u0026lt;5%。DI显著富集细胞类型特异性标记基因（卡方检验，P \u0026lt; 2.2 × 10⁻¹⁶），尤其是在排名靠前的DI中（图S8 C）。\nC：DI锚点与顶级标记基因重叠的比值。DI组按FDR排序。误差条表示95%置信区间。\n与标记基因重叠的DI在相应的细胞类型中往往表现出较弱的相互作用，这可能部分归因于近期在小鼠脑中发现的“结构域熔解”现象。\n结构域熔解（Domain Melting）\n正常情况下，基因组被组织成 TAD——一个区域内部互作多，边界外互作少，像一个个\u0026quot;隔间\u0026quot;。\n结构域熔解是指：当某个基因被高度激活转录时，它所在的TAD结构会局部瓦解——边界变模糊，内部互作减弱，就像固体\u0026quot;熔化\u0026quot;成液体一样失去原有结构。\n转录时RNA聚合酶沿DNA高速移动，会产生拓扑张力，破坏原有的染色质折叠结构，导致局部TAD解体。\n4.2.2 一对多分析细胞类型DI 图 3A：小鼠胚胎细胞类型的代表性DI，其中数字表示细胞类型（与前面一样），仅取各细胞类型中前5%互作强度最高的DI；列是各细胞类型。\n图 3B：从早期神经元中识别出的DI示例。白色箭头指示3D邻近图（上图）上包含DI的主要区域。圆圈表示3D差异图（下图）上的主要DI。\n4.3 DI上基因的功能富集 GREAT = Genomic Regions Enrichment of Annotations Tool\n使用细胞类型特异的DI做GREAT得到基因列表，上调最显著的DI富集了与特定细胞类型相关的基因本体论（GO）术语，例如神经外胚层中的“神经元分化”和早期中胚层中的“心脏发育”。\n重要 该结果表明，尽管早期发育过程中不同组织的染色质结构总体上相似，但染色质相互作用的局部重连具有高度的细胞类型特异性，并且与细胞功能密切相关。\n4.2 DI谱聚类 有了各个细胞的DI的位置后，我们可以得到这样一个矩阵，每行是一个细胞，行内是该细胞所有DI的三维距离值。\n使用这个矩阵，我们可以做一个UMAP聚类图，并用细胞类型（CD左）和细胞周期（CD右）分别着色。\nD图是C图仅保留G1期、G0期细胞的版本。\n我们发现，使用最佳DI谱进行聚类仍然无法区分早期发育谱系中的细胞类型（图S9C）。作者给出了两个可能的原因：\n三维基因组的动态特性（scHi-C是随机采样的）使得单细胞中的染色质相互作用具有极强的随机性； 与细胞周期相关的显著染色质重组主导了细胞类型特异性的染色质特征，即使是G1期和G0期细胞也是如此，而大多数G1期和G0期细胞在有丝分裂后仍在经历持续的染色质构象变化（图S9D）。 解决办法：\n前面我们知道，RNA表达聚类注释结果比HI-C聚类注释更加可靠更加紧凑，所以这里作者将具有相似表达谱的单细胞合并成元细胞 MetaCell可以解决这些问题，因为细胞周期与标记基因表达变化的相关性要小得多。\n图 3C：基于聚合DI谱的元细胞UMAP聚类。虚线圆圈分别表示神经外胚层（蓝色）和中胚层（橙色）谱系。\n重要 表明可以利用单细胞RNA测序的联合分析来克服单细胞Hi-C数据的固有噪声。\n4.3 Hi-C + RNA 4.3.1 GADI与基因的关联性 GADI：基因关联DI\n使用相关性分析，即每个DI在每个metacell里面的距离值与每个基因在每个metacell里面的表达（metacell由RNA表达决定）。\n图 S10A：GADI比随机的gene-DI有更显著的结果，证明GADI的可靠性。\n图 S10B：GADI富集细胞类型特异性标记基因，OR表overlap ratio。\n图 S10C：平均每个基因与117个GADI有关联，大多GADI（61%）仅与一个基因有关联，2.6%与5个基因以上有关，其中许多来自 Hox 和原钙黏蛋白基因簇（图 S10D）。\n这两个基因簇都是基因组上密集排列的基因家族，在三维结构上具有特殊性： 几十个基因串联排列在一小段基因组上 受同一个三维调控域（TAD）统一管控 一个增强子或染色质互作可以同时影响多个相邻Hox基因的表达，一个关键的增强子（HS5-1）通过形成染色质环轮流激活不同的原钙黏蛋白基因 4.3.2 GADI富集在TSS附近 与 DI 相比，GADI 在转录起始位点 (TSS) 周围高度富集（图 3E），而且大多数（69.5%）锚定点与 TSS 重叠的 GADI 显示出相互作用强度与基因活性之间的正相关性（图 S10E）。\n这些相互作用通常将启动子与远端调控元件（包括超级增强子）连接起来（图 3F）。\n图 3F：与Dcc（左）或Dlc1（右）相连的GADI。顶部显示3D邻近图。每个GADI用连接其两个锚点的弧线表示，颜色表示其与基因表达的相关性。\n作者为了验证其结果，将结果与最近在两个不同的基因位点Zic1/Zic4和Mir9-2上的报道进行了比较，这两个位点的功能性增强子-启动子连接已在体内实验中得到验证（39 ）。在这两个位点上，我们都鉴定出了包含增强子-启动子相互作用的GADI，这与其他报道一致（图 S10F）。\n图 S10F：类似上图。\n重要 因此，GADI不仅代表与转录变化相关的染色质重连，也指示了潜在的增强子-启动子相互作用，这些相互作用是细胞类型特异性基因表达调控的基础。\n5、广泛的染色质相互作用在转录激活前发生重塑 5.1 用残差探究GADI与RNA表达的同步变化 通过GADI将染色质相互作用与特定基因关联起来后，现在能够以高分辨率比较染色质构象的伪时间动态与转录过程。\n作者首先恢复了两条胚胎分化轨迹：早期神经元轨迹和混合的晚期间充质轨迹（图S11，A和B）( 43 )。\n每个GADI-基因对的“残差”：同一元细胞中GADI相互作用强度与表达水平之差，类似于“染色质潜能”方法( 44 )\n正残差：染色质互作已经建立，但基因还没开始表达 → 染色质变化超前于转录\n负残差：基因已经在表达，但染色质互作还没建立 → 转录超前于染色质变化\n残差≈0：染色质变化和转录同步发生\n并使用轨迹上的所有元细胞进行单样本t检验，以确定残差是否显著偏离零（图 S11C）。\n结果：虽然大多数染色质相互作用与基因表达同步变化，但仍有40,990个（21.6%）GADI-基因对（涵盖315个基因）的残差显著大于零，表明在转录改变之前染色质相互作用就已经发生了重连（图 4A）。\nGADI的变化落后于RNA表达的例子\n5.2 机制探究 图 4C：包含H3K27ac信号（上图）或BB区室相互作用（下图）的GADI百分比。\n与混合晚期间充质或早期神经元标记基因表达呈正相关或负相关的GADI分别按残差从大到小排序，分成100组： 左边（0）= 残差最大 = 染色质变化远超前于基因表达（Prior，红色） 中间 = 残差接近0 = 同步变化（Not significant，灰色） 右边（100）= 残差最小 = 基因表达超前于染色质（Subsequent，蓝色） 每组中prior GADI（比RNA表达先变化的GADI）的数量显示在顶部。 上图：每组GADI中，有多少比例落在H3K27ac富集区域（活性增强子标记）\n下图：每组GADI中，有多少比例属于B-B区室互作\n在混合的晚期间充质谱系中（左边四图），无论GADI相互作用强度与基因活性之间的相关性如何，基因表达前发生变化的相互作用都显著富集了活性增强子的染色质特征（上图H3K27ac强度高，这个明显；下图BB互作强度弱，即不在异染色质区）。\n在早期神经元谱系中（右边四图），我们观察到了正相关和负相关的相反结果。\n只有与转录呈正相关的GADI在基因表达前发生变化的相互作用中表现出增强子标记的类似富集。\n相反，与转录呈负相关的GADI则富集异染色质标记和BB区室相互作用\n解释 2 相反的结果\n与prior GADI存在负相关的基因，的在转录起始位点（TSS）处减少，而在基因体及其侧翼区域富集（图 S13B）。\n此外，我们发现相应的神经元基因（定义为具有\u0026gt;20个负相关的GADI的基因）通常位于更沉默的染色体环境中（图S13C和D），即PC1值更低一些。\n图 S13C：各组都是负相关GADI-RNA的基因列表，即负相关Prior GADI在基因表达下降之前就先建立互作。\n6、结论 基因表达前三维基因组的变化背后存在不同的染色质动力学机制（图 4D）。\n首先，在大多数基因位点，基因表达前的染色质重连主要发生在活性染色质之间，这可能是由增强子的激活驱动的。\n其次，对于位于抑制性染色质环境中的基因，转录激活前发生的是浓缩的异染色质的松弛。这两个过程并非互斥，可能同时发生在同一基因上。\n","permalink":"https://june6699.github.io/posts/article1-hires-hic-rna-seq-linking-genome-structures/","summary":"\u003ch2 id=\"--hires--science-2023\"\u003e📌 ① HiRES — \u003cem\u003eScience\u003c/em\u003e, 2023\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://www.science.org/doi/10.1126/science.adg3797\" target=\"_blank\" rel=\"noopener noreferrer\"\u003ehttps://www.science.org/doi/10.1126/science.adg3797\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eLiu Z, Chen Y, Xia Q, et al. \u0026ldquo;Linking genome structures to functions by simultaneous single-cell Hi-C and RNA-seq.\u0026rdquo; *Science* 380, 1070–1076 (2023)\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e亮点：\u003c/strong\u003e 1这是首篇真正实现单细胞水平同时测量染色质三维构象和基因表达的方法论文。作者开发了 HiRES（Hi-C and RNA-seq Employed Simultaneously）技术，并应用于数千个小鼠发育胚胎单细胞。研究发现，\u003cstrong\u003e三维基因组结构在高度受细胞周期影响的同时，会随发育进程以细胞类型特异性方式逐渐分化\u003c/strong\u003e。通过比较染色质互作与转录的拟时序动态，他们发现了\u003ccode\u003e广泛的\u0026quot;染色质重塑先于转录激活\u0026quot;现象\u003c/code\u003e，证明特异性染色质互作与谱系分化过程中的转录调控密切相关。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/论文"],"title":"HiRES单细胞三维基因组与转录组同步解析"},{"content":"一、scHi-C 核心原理概述 scHi-C（single-cell High-throughput Chromosome Conformation Capture）是单细胞水平的染色质三维空间互作捕获技术，核心目标是解析单个细胞内染色质的多位点同时互作（Chromatin Hub）。 其实验核心原理：通过甲醛交联固定染色质天然空间构象，限制性内切酶切割基因组DNA，对空间邻近的不同染色质区段进行生物素标记与连接，形成跨多个基因组位点的嵌合DNA片段；利用高通量双端测序读取嵌合片段序列，通过生物信息学比对定位片段对应的基因组坐标，最终还原染色质的真实空间接触关系。 区别于群体细胞Hi-C，scHi-C 高度依赖嵌合read（chimeric read）的捕获与分析，这是识别单细胞多位点互作的核心数据特征。\n二、测序数据格式 SAM 格式（比对结果存储） SAM 是存储序列比对信息的标准文本格式，每行代表一条 read 的比对记录，scHi-C 数据中同一 read name 的 R1/R2 记录连续相邻，示例如下：\nA01045:956:HMNFYDMXY:2:1101:19307:1016\t97\tchr10\t111308001\t60\t150M\t=\t111308051\t200\tGTATGTGATGGGTCAACGTGCCACAGACTCAGGAGTAACGAGGCCTCCTGACCTCAGACAAAACCTCCAACACTATGAGCACAATGAACGTTCCCTGCTTTTAAAGCTGATGATCTCAGGTATTCTGGTACACTAACAGAAAGCTGATGT\tFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFF,FFF:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFF:FFFFFF:FF\tNM:i:1 MD:Z:81A68\tMC:Z:150M\tAS:i:145\tXS:i:0 A01045:956:HMNFYDMXY:2:1101:19307:1016\t145\tchr10\t111308051\t60\t150M\t=\t111308001\t-200\tACCTCAGACAAAACCTCCAACACTATGAGCAAAATGAACGTTCCCTGCTTTTAAAGCTGATGATCTCAGGTATTCTGGTACACTAACAGAAAGCTGATGTGATGGTTTTAAATGTTAACTCAGAATCATGTGGGAAGAGAGTCTCCATAG\tFFF:FFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFF\tNM:i:0 MD:Z:150\tMC:Z:150M\tAS:i:150\tXS:i:0 A01045:956:HMNFYDMXY:2:1101:23683:1047\t81\tchrX\t25068476\t0\t150M\t=\t32598360\t7529736\tTAGATTCCCTCTTTTCTTCCAGATTCCAAGATGCCTTCCAGGCTCGAACCCGGACATGTGAGCCACTGGCCAGCCTCAACAATTTGGCGAACCAATGCAGGACCTGAGAAAGGCAGAGGACATTTGGAAGAAACACTGCTGATTTGTAGC\tFFFFF,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:FFFFFFF,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\tNM:i:0 MD:Z:150\tMC:Z:150M\tAS:i:150\tXS:i:150 关键字段原理（scHi-C 核心） readName：测序原始 read 唯一标识，R1 和 R2 共享完全相同的 read name，是 pairtools 配对的核心依据； flag：二进制状态码（scHi-C 关键），97/145 为双端 read 正确配对的反向比对标记，81 为单端反向比对标记，直接标识 read 类型与比对方向； chr/pos：read 比对的染色体与基因组坐标，是染色质互作的定位基础； mapQ：比对质量值（60为最高可信度，0为无有效比对），parse2 步骤会过滤 min-mapq 40 以下的低质量记录； CIGAR（150M）：表示 150bp 序列完全匹配，无插入缺失，是 scHi-C 有效比对的标准格式； RNEXT/PNEXT：配对 read（R1/R2）的比对染色体/坐标，= 表示配对 read 比对在同一条染色体； SA:Z（嵌合read专属tag）：scHi-C 核心特征，记录一条 read 的多个比对位置，对应染色质多位点空间互作； NM/MD/AS：比对错配、匹配区域、比对得分等质控标签，用于评估比对可靠性。 原理补充 双端测序的必要性：Hi-C 实验产生的有效片段均为空间邻近的不同染色质区段连接形成的嵌合片段，R1、R2 分别读取片段两端，可直接定位两个互作位点； 单细胞数据特征：每个细胞独立生成 R1.fastq.gz 和 R2.fastq.gz 两个文件，保证单细胞分辨率的数据独立性； 嵌合read价值：scHi-C 中一条 read 可能比对到多个基因组位置，直接对应染色质多位点空间互作。 三、比对流程 BWA 比对（核心比对步骤） bwa mem -SP5M -T0 -t16 ref.fa R1.fastq.gz R2.fastq.gz \u0026gt; output.int.sam 1. scHi-C 专用参数原理（关键） -SP5M 是 Hi-C/scHi-C 数据的专用参数组合，专为嵌合read设计，缺一不可：\n-S：跳过SAM头部校验，适配Hi-C嵌合read的输出格式； -P：严格保留双端read的配对关系，保证R1/R2绑定； -5：仅保留read 5\u0026rsquo;端比对位置（Hi-C互作仅依赖片段末端坐标，排除内部序列干扰）； -M：将多位置比对的read标记为次级比对，通过SAtag记录所有嵌合位点； -T0：最低比对得分设为0，保留弱比对信号，避免丢失嵌合read； -t16：16线程加速比对。 2. 输出核心规则 BWA 直接输出的 SAM 文件严格按照 read name 排序，同一 read 的 R1、R2 及所有嵌合比对记录连续相邻，这是后续 pairtools 配对的必要前提。\nSAM 格式（比对结果存储） readName flag chr7 144581129 60 150M = 125449562 ... SA:Z:... readName flag chr7 125449562 60 150M = 144581129 ... 关键字段原理 flag：二进制标记，标识read类型（R1/R2）、比对方向、是否唯一比对； SA:Z:***：嵌合read标记，scHi-C核心特征，记录一条read的所有补充比对位置，对应多位点互作； 坐标信息：记录染色质互作的基因组位置，是三维构象分析的基础。 四、pairtools 处理流程 pairtools 是 Hi-C/scHi-C 数据标准化工具，核心功能是完成read配对、过滤、去重，输出标准化互作对（pairs）。\nparse2：SAM → pairs 格式转换（最核心步骤） pairtools parse2 -c mm10.chrom.sizes --assembly mm10 --add-pair-index --expand --drop-sam --min-mapq 40 input.sam -o output.pairs 工作原理 算法：采用滑动缓冲窗口扫描SAM，将同名read存入缓冲区，等待R1/R2及嵌合记录全部集齐后完成配对； 硬性依赖：必须基于read name连续的SAM文件，记录分散则直接判定为无效； 输出规则：生成pairs格式，存储一对read对应的两个互作位点坐标； pair_type=UU：两端均唯一比对，是scHi-C有效互作的金标准。 sort：pairs 基因组坐标排序 pairtools sort -o output_sorted.pairs input.pairs 原理 原始pairs按read name排序，相同坐标的重复互作分散存储；按基因组坐标排序后，技术重复会连续排列，为去重做准备。\ndedup：PCR 重复去除 pairtools dedup --mark-dups --output-stats output.dedup.stats -o output_dedup.pairs input_sorted.pairs 原理 重复来源：PCR扩增会导致同一原始嵌合片段被多次测序，产生完全相同的坐标互作（技术噪音）； 去重逻辑：识别坐标完全一致的pairs，仅保留1条，保证数据的生物学真实性； --mark-dups：标记重复而非直接删除，便于质控。 select：过滤自连接，保留 UU 有效对 pairtools select \u0026#39;(pair_type==\u0026#34;UU\u0026#34;) and ((chrom1!=chrom2) or (abs(pos1-pos2)\u0026gt;10000))\u0026#39; input_dedup.pairs \u0026gt; output.Noselfligation.UU.pairs 原理 自连接（self-ligation）：Hi-C实验技术噪音，指同一染色质片段自身连接，非真实空间互作； 过滤规则：同一染色体距离＜10kb的互作判定为自连接，直接剔除； 保留规则：仅保留UU类型（两端唯一比对）的高可信度互作。 五、自定义过滤流程（R语言，scHi-C特有） 去 blacklist 区域 # 去除两端落入 mm10 blacklist 区域的 pairs y \u0026lt;- a[a$ID1 == 0 \u0026amp; a$ID2 == 0, ] 原理 黑名单区域是基因组中串联重复、着丝粒、比对异常区的集合，序列重复性极高，互作信号无生物学意义，需彻底剔除。\n筛选多位点接触（≥3个10kb bin） # 只保留一条 PE read 覆盖 ≥3 个唯一 10kb bin 的接触 out \u0026lt;- rec[rec$Num.10Kb.Bin \u0026gt;= 3, ] 原理 scHi-C核心：专注多位点同时互作（Chromatin Hub），区别于普通Hi-C的两位点互作； 10kb bin：染色质互作的基本分析单元； 筛选逻辑：≥3个不同bin代表真实多位点互作，＜3个判定为普通Hi-C噪音。 六、典型问题排查：M24样本处理失效分析 6.1 异常症状 M24 样本走完完整流程后，.Noselfligation.UU.pairs 文件几乎为空（仅1行）； 对照 D0 样本同一步骤有十万级有效互作； SAM 文件大小（十几GB）、raw pairs 行数均正常，数据未丢失，但全部失效； 无效pairs特征：全为! 0 ! 0（无基因组坐标）+XX（无效配对类型）。 6.2 根本原因（原理级） M24 的 BWA 流程错误加入了 samtools 坐标排序：\n# 错误流程：排序破坏read name顺序 bwa mem ... | samtools sort -o output.bam - \u0026amp;\u0026amp; samtools view -h -o output.sam output.bam samtools sort 的破坏性：将文件按染色体物理坐标重排，彻底摧毁 BWA 输出的 read name 有序性； 记录分散：同一read的R1、R2、嵌合比对被随机分散（间隔数百万行）； pairtools 失效：滑动缓冲窗口无法集齐配对read，全部判定为无效数据； 输出特征：无效配对统一输出! 0 ! 0 XX，文件大小正常但无有效信息。 6.3 修复方案（仅改一步） # 正确流程：BWA直接输出SAM，保留read name顺序 bwa mem -SP5M -T0 -t16 ref.fa R1.fastq.gz R2.fastq.gz 2\u0026gt;log \u0026gt; output.int.sam 修复原理 去掉samtools sort/index，BWA直接输出SAM，严格保留原始read name顺序； 同一read的R1/R2/嵌合记录连续相邻，满足pairtools parse2的核心要求； 兼容性：仅修改比对步骤，后续pairtools、R脚本完全无需改动，即可恢复正常输出。 七、流程核心总结 黄金原则：scHi-C 比对后绝对不能做坐标排序（指的是sam文件不能sort，parse后的pairs文件仍然需要pairtools的sort），必须保留 read name 顺序； 核心依赖：BWA -SP5M 参数 + 有序SAM + pairtools 滑动窗口配对； 数据逻辑：嵌合read → 多位点互作 → Chromatin Hub（scHi-C核心生物学信号）； 失效根源：坐标排序破坏read配对，是scHi-C数据处理最常见的致命错误。 ","permalink":"https://june6699.github.io/posts/pairtools%E5%A4%84%E7%90%86hic%E6%95%B0%E6%8D%AEbug%E8%A7%A3%E5%86%B3%E6%97%A5%E5%BF%97/","summary":"\u003ch2 id=\"一schi-c-核心原理概述\"\u003e一、scHi-C 核心原理概述\u003c/h2\u003e\n\u003cp\u003escHi-C（single-cell High-throughput Chromosome Conformation Capture）是\u003cstrong\u003e单细胞水平\u003c/strong\u003e的染色质三维空间互作捕获技术，核心目标是解析单个细胞内染色质的\u003cstrong\u003e多位点同时互作（Chromatin Hub）\u003c/strong\u003e。\n其实验核心原理：通过甲醛交联固定染色质天然空间构象，限制性内切酶切割基因组DNA，对\u003cstrong\u003e空间邻近的不同染色质区段\u003c/strong\u003e进行生物素标记与连接，形成跨多个基因组位点的\u003cstrong\u003e嵌合DNA片段\u003c/strong\u003e；利用高通量双端测序读取嵌合片段序列，通过生物信息学比对定位片段对应的基因组坐标，最终还原染色质的真实空间接触关系。\n区别于群体细胞Hi-C，scHi-C 高度依赖\u003cstrong\u003e嵌合read（chimeric read）\u003c/strong\u003e的捕获与分析，这是识别单细胞多位点互作的核心数据特征。\u003c/p\u003e","tags":["技术","技术/生信","技术/生信/分析"],"title":"pairtools处理HIC测序数据"},{"content":"研究生学习 2025-2026年贯穿了我研一下半学期与研二上半学期，这一年在科研与学习上稳步推进，也迎来了不少新的挑战与突破。\n在猪心脏相关课题上，我对原有内容做了进一步完善，重点修正了 SnapATAC 分析流程。流程的核心问题出在细胞类型命名上：若 Seurat 对象中的细胞类型名称包含 / 符号（如 Macrophage/Myeloid），系统会将其识别为路径层级，导致保存异常。修正后，对最终DAR结果的提升虽不显著，但分析逻辑更严谨、结果更可靠。\n同时，我将差异表达分析、BETA、AME等核心流程重新完整跑通一遍。其中 AME 分析采用了2026版 JASPAR 数据库，与此前王晨的结果对比后发现：差异表达结果完全一致，BETA 存在小幅差异，AME 仅在部分 q 值上有极细微差别。统一重跑、统一目录管理，也为后续结果查阅与复现提供了极大便利。\n这一年我还接手了一个难度与体量都极具挑战的课题——王晨留下的小鼠肾脏衰老与发育研究。项目数据十分丰富：涵盖小鼠 D0、D56、W92 三个时间点，共12个 scATAC 样本、25个单细胞转录组样本、4个空间转录组样本、17个 scHi-C 样本，同时整合6月龄猪、成年人的公共数据与部分自测数据，后续还需衔接实验验证。我以此课题作为开题方向，从对空间转录组、Hi-C 完全陌生开始，在唐老师一小时的细致讲解后，仅用6天便完成开题报告。尽管内容仍有不足，但已是当时能力范围内的最大努力。感谢唐老师的指导，也感谢知乎、Claude、ChatGPT 等工具在这段时间里给予的助力。开题后，经过近一年的摸索与分析，我对空间转录组有了更深入的理解，而 Hi-C 数据分析仍需继续深耕。\n此外，我利用课余时间学习了前端相关知识，包括 JavaScript、CSS、Django 等，在实践中越发体会到 Cursor 的高效便捷，也深刻意识到：审美是页面设计的前提，没有见过足够简洁、大气、优雅的界面，就很难做出真正好用又好看的页面。在此基础上，我搭建了自己的第一个个人博客 ，参考教程来自 https://github.com/qiubaiying/qiubaiying.github.io 。\n（忽略调皮豆包）\n机器学习与深度学习方面，我也有所涉猎，对 MLP 多层感知机、SVM 支持向量机、神经网络结构及多种学习率优化策略有了基础认知，并实战了pytorch，做了几个简单的项目，但是HIC的域适应课题仍为做出来，唉，菜！由于长时间未实战应用，相关知识已逐渐生疏，此前学过的域适应、对抗模型等内容更是遗忘大半。\nAI 领域发展日新月异，需要学习的内容层出不穷。在海量知识面前，找到真正热爱的方向并坚持深耕，既重要又可贵，也绝非易事。\n","permalink":"https://june6699.github.io/posts/2025-2026%E5%B9%B4%E6%80%BB/","summary":"\u003ch3 id=\"研究生学习\"\u003e研究生学习\u003c/h3\u003e\n\u003cp\u003e2025-2026年贯穿了我研一下半学期与研二上半学期，这一年在科研与学习上稳步推进，也迎来了不少新的挑战与突破。\u003c/p\u003e\n\u003cp\u003e在猪心脏相关课题上，我对原有内容做了进一步完善，重点修正了 \u003ccode\u003eSnapATAC\u003c/code\u003e 分析流程。流程的核心问题出在\u003cstrong\u003e细胞类型命名\u003c/strong\u003e上：若 \u003ccode\u003eSeurat\u003c/code\u003e 对象中的细胞类型名称包含 \u003ccode\u003e/\u003c/code\u003e 符号（如 \u003ccode\u003eMacrophage/Myeloid\u003c/code\u003e），系统会将其识别为路径层级，导致保存异常。修正后，对最终DAR结果的提升虽不显著，但分析逻辑更严谨、结果更可靠。\u003c/p\u003e","tags":["生活","生活/记录"],"title":"2025-2026初 年终总结"},{"content":"今日元宵，在此祝各位元宵快乐、阖家团圆！\n月上柳梢头，人约黄昏后 思越人·紫府东风放夜时 紫府东风放夜时，步莲秾李伴人归。\n五更钟动笙歌散，十里月明灯火稀。\n香苒苒，梦依依。天涯寒尽减春衣。\n凤凰城阙知何处，寥落星河一雁飞。\n宋·贺铸\n东风吹起，京城元宵夜禁解除，步态轻盈、艳若桃李的游人相伴而归。五更钟声响起，笙歌散尽，十里长街明月高悬，灯火渐稀。香气袅袅，梦魂依依，天涯寒意褪尽，褪去冬衣换春衫。不知京城宫阙今在何处，只见寥落星河间，一只孤雁高飞。\n鹧鸪天·建康上元作 客路那知岁序移，忽惊春到小桃枝。\n天涯海角悲凉地，记得当年全盛时。\n花弄影，月流辉。水精宫殿五云飞。\n分明一觉华胥梦，回首东风泪满衣。\n宋·赵鼎\n漂泊在外，浑然不觉节序更迭，猛然惊觉春意已攀上桃枝。身处天涯海角这悲凉之地，犹记当年汴京全盛时的元宵盛景。花枝弄影，月光流辉，水晶宫殿上彩云飞舞。恍然一场繁华幻梦，回首东风，泪满衣襟。\n踏莎行·元夕 拨雪寻春，烧灯续昼。暗香院落梅开后。\n无端夜色欲遮春，天教月上官桥柳。\n花市无尘，朱门如绣。娇云瑞雾笼星斗。\n沈香火冷小妆残，半衾轻梦浓如酒。\n宋·毛滂\n拨开积雪寻觅春意，点灯续接白昼，梅花开后院落暗香浮动。夜色无端欲掩春色，天公却教明月照上官桥垂柳。花市纤尘不染，朱门华美如绣，柔云瑞雾笼罩星斗。沉香燃尽，妆容浅淡，半床薄被中的浅梦，浓烈如醇酒。\n鹧鸪天·元夕有所梦 肥水东流无尽期。当初不合种相思。\n梦中未比丹青见，暗里忽惊山鸟啼。\n春未绿，鬓先丝。人间别久不成悲。\n谁教岁岁红莲夜，两处沉吟各自知。\n宋·姜夔\n肥水东流永无歇止，当初真不该种下这相思情意。梦中相见犹不如画像真切，暗夜里忽被山鸟啼声惊醒。春色尚未染绿大地，双鬓已先斑白，人间别离日久，反不觉悲切。年年元宵灯夜，两地之人各自沉吟思念，唯有心知。\n元宵 有灯无月不娱人，有月无灯不算春。\n春到人间人似玉，灯烧月下月如银。\n满街珠翠游村女，沸地笙歌赛社神。\n不展芳尊开口笑，如何消得此良辰。\n明·唐寅\n有灯无月难成欢，有月无灯不成春。春到人间，人儿温润如玉；花灯映月，月华皎洁如银。满街珠翠是游赏的村女，笙歌沸地赛过社神祭典。若不举杯畅饮、开怀一笑，怎对得住这良辰美景。\n正月十五夜 火树银花合，星桥铁锁开。\n暗尘随马去，明月逐人来。\n游伎皆秾李，行歌尽落梅。\n金吾不禁夜，玉漏莫相催。\n唐·苏味道\n元宵灯火璀璨如火树银花交相辉映，宵禁解除，星桥城门洞开。马蹄过处轻尘飞扬，明月好似追着游人而来。歌女们艳若桃李，边走边唱《落梅》古曲。京城解除夜禁，计时的玉漏啊，莫要匆匆催走这良夜。\n蝶恋花·密州上元 灯火钱塘三五夜，明月如霜，照见人如画。\n帐底吹笙香吐麝，更无一点尘随马。\n寂寞山城人老也！击鼓吹箫，却入农桑社。\n火冷灯稀霜露下，昏昏雪意云垂野。\n宋·苏轼\n杭州元宵三五之夜灯火辉煌，明月如霜，映得游人美如图画。帐下吹笙，香气如麝般清雅，路上洁净无一丝尘土。而今身处寂寞山城，人也渐老，元宵唯有击鼓吹箫，走入农家桑社。灯火清冷稀疏，霜露降下，云层低垂，一片沉沉雪意笼罩原野。\n永遇乐·落日熔金 落日熔金，暮云合璧，人在何处。\n染柳烟浓，吹梅笛怨，春意知几许。\n元宵佳节，融和天气，次第岂无风雨。\n来相召、香车宝马，谢他酒朋诗侣。\n中州盛日，闺门多暇，记得偏重三五。\n铺翠冠儿，捻金雪柳，簇带争济楚。\n如今憔悴，风鬟霜鬓，怕见夜间出去。\n不如向、帘儿底下，听人笑语。\n宋·李清照\n落日如熔金，暮云如合璧，我却不知身在何处。浓烟染绿柳枝，笛声吹出梅花哀怨，春意几何？元宵佳节，天气融和，谁料不会转眼风雨。友人香车宝马相邀，我推却了酒朋诗侣。记得汴京繁盛时，闺中多暇，最重元宵三五。人人翠冠雪柳，打扮得齐整俏丽。如今憔悴不堪，鬓发斑白，怕在夜间出门，不如躲在帘儿底下，听旁人欢声笑语。\n生查子·元夕 去年元夜时，花市灯如昼。\n月上柳梢头，人约黄昏后。\n今年元夜时，月与灯依旧。\n不见去年人，泪湿春衫袖。\n宋·欧阳修\n去年元宵夜，花市灯火亮如白昼。月上柳梢，与心上人相约黄昏之后。今年元宵，月与灯依旧璀璨，却不见去年那人，泪沾春衫袖。\n青玉案·元夕 东风夜放花千树。更吹落、星如雨。\n宝马雕车香满路。凤箫声动，玉壶光转，一夜鱼龙舞。\n蛾儿雪柳黄金缕。笑语盈盈暗香去。\n众里寻他千百度。蓦然回首，那人却在，灯火阑珊处。\n宋·辛弃疾\n东风吹开元宵夜的花灯，如千树花开，又似繁星如雨飘落。宝马雕车香气满路，凤箫悠扬，玉壶流光，整夜鱼龙灯舞不息。游女们头戴蛾儿、雪柳、黄金缕，笑语盈盈，暗香远去。我在人群中千百次寻觅那人，蓦然回首，却见她立在灯火阑珊、清冷僻静之处。\n〇 札记\n元宵佳节，研二下学期的开端，感觉自己今天才刚刚进入状态，换句话说，刚刚从放假的状态回归，坚持学习，坚持锻炼，争取改掉许许多多的坏习惯！保持健康的身体为先，在做自己喜欢的事中学习为次。\n→ 年终总结 · 2026 ","permalink":"https://june6699.github.io/posts/%E5%85%83%E5%AE%B5%E4%BD%B3%E8%8A%82/","summary":"\u003cdiv class=\"poem-festival-wish\"\u003e今日元宵，在此祝各位\u003cstrong\u003e元宵快乐、阖家团圆\u003c/strong\u003e！\u003cbr\u003e月上柳梢头，人约黄昏后\u003c/div\u003e\n\u003cp\u003e\u003cimg src=\"/images/%e5%85%83%e5%ae%b5%e4%bd%b3%e8%8a%82/%e5%85%83%e5%ae%b5-%e5%ad%94%e6%98%8e%e7%81%af.jpg\" alt=\"元宵孔明灯\" width=\"4160\" height=\"6240\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch3 id=\"思越人紫府东风放夜时\"\u003e思越人·紫府东风放夜时\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e紫府东风放夜时，步莲秾李伴人归。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e五更钟动笙歌散，十里月明灯火稀。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e香苒苒，梦依依。天涯寒尽减春衣。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e凤凰城阙知何处，寥落星河一雁飞。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·贺铸\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e东风吹起，京城元宵夜禁解除，步态轻盈、艳若桃李的游人相伴而归。五更钟声响起，笙歌散尽，十里长街明月高悬，灯火渐稀。香气袅袅，梦魂依依，天涯寒意褪尽，褪去冬衣换春衫。不知京城宫阙今在何处，只见寥落星河间，一只孤雁高飞。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"鹧鸪天建康上元作\"\u003e鹧鸪天·建康上元作\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e客路那知岁序移，忽惊春到小桃枝。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e天涯海角悲凉地，记得当年全盛时。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e花弄影，月流辉。水精宫殿五云飞。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e分明一觉华胥梦，回首东风泪满衣。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·赵鼎\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e漂泊在外，浑然不觉节序更迭，猛然惊觉春意已攀上桃枝。身处天涯海角这悲凉之地，犹记当年汴京全盛时的元宵盛景。花枝弄影，月光流辉，水晶宫殿上彩云飞舞。恍然一场繁华幻梦，回首东风，泪满衣襟。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"踏莎行元夕\"\u003e踏莎行·元夕\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e拨雪寻春，烧灯续昼。暗香院落梅开后。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e无端夜色欲遮春，天教月上官桥柳。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e花市无尘，朱门如绣。娇云瑞雾笼星斗。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e沈香火冷小妆残，半衾轻梦浓如酒。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·毛滂\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e拨开积雪寻觅春意，点灯续接白昼，梅花开后院落暗香浮动。夜色无端欲掩春色，天公却教明月照上官桥垂柳。花市纤尘不染，朱门华美如绣，柔云瑞雾笼罩星斗。沉香燃尽，妆容浅淡，半床薄被中的浅梦，浓烈如醇酒。\u003c/p\u003e\n\u003c/div\u003e\n\u003cp\u003e\u003cimg src=\"/images/%e5%85%83%e5%ae%b5%e4%bd%b3%e8%8a%82/%e5%85%83%e5%ae%b5-%e8%83%8c%e6%99%af1.jpg\" alt=\"元宵背景\" width=\"5472\" height=\"3648\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch3 id=\"鹧鸪天元夕有所梦\"\u003e鹧鸪天·元夕有所梦\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e肥水东流无尽期。当初不合种相思。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e梦中未比丹青见，暗里忽惊山鸟啼。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e春未绿，鬓先丝。人间别久不成悲。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e谁教岁岁红莲夜，两处沉吟各自知。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·姜夔\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e肥水东流永无歇止，当初真不该种下这相思情意。梦中相见犹不如画像真切，暗夜里忽被山鸟啼声惊醒。春色尚未染绿大地，双鬓已先斑白，人间别离日久，反不觉悲切。年年元宵灯夜，两地之人各自沉吟思念，唯有心知。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"元宵\"\u003e元宵\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e有灯无月不娱人，有月无灯不算春。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e春到人间人似玉，灯烧月下月如银。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e满街珠翠游村女，沸地笙歌赛社神。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e不展芳尊开口笑，如何消得此良辰。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e明·唐寅\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e有灯无月难成欢，有月无灯不成春。春到人间，人儿温润如玉；花灯映月，月华皎洁如银。满街珠翠是游赏的村女，笙歌沸地赛过社神祭典。若不举杯畅饮、开怀一笑，怎对得住这良辰美景。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"正月十五夜\"\u003e正月十五夜\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e火树银花合，星桥铁锁开。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e暗尘随马去，明月逐人来。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e游伎皆秾李，行歌尽落梅。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e金吾不禁夜，玉漏莫相催。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e唐·苏味道\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e元宵灯火璀璨如火树银花交相辉映，宵禁解除，星桥城门洞开。马蹄过处轻尘飞扬，明月好似追着游人而来。歌女们艳若桃李，边走边唱《落梅》古曲。京城解除夜禁，计时的玉漏啊，莫要匆匆催走这良夜。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"蝶恋花密州上元\"\u003e蝶恋花·密州上元\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e灯火钱塘三五夜，明月如霜，照见人如画。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e帐底吹笙香吐麝，更无一点尘随马。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e寂寞山城人老也！击鼓吹箫，却入农桑社。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e火冷灯稀霜露下，昏昏雪意云垂野。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·苏轼\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e杭州元宵三五之夜灯火辉煌，明月如霜，映得游人美如图画。帐下吹笙，香气如麝般清雅，路上洁净无一丝尘土。而今身处寂寞山城，人也渐老，元宵唯有击鼓吹箫，走入农家桑社。灯火清冷稀疏，霜露降下，云层低垂，一片沉沉雪意笼罩原野。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"永遇乐落日熔金\"\u003e永遇乐·落日熔金\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e落日熔金，暮云合璧，人在何处。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e染柳烟浓，吹梅笛怨，春意知几许。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e元宵佳节，融和天气，次第岂无风雨。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e来相召、香车宝马，谢他酒朋诗侣。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e中州盛日，闺门多暇，记得偏重三五。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e铺翠冠儿，捻金雪柳，簇带争济楚。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e如今憔悴，风鬟霜鬓，怕见夜间出去。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e不如向、帘儿底下，听人笑语。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·李清照\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e落日如熔金，暮云如合璧，我却不知身在何处。浓烟染绿柳枝，笛声吹出梅花哀怨，春意几何？元宵佳节，天气融和，谁料不会转眼风雨。友人香车宝马相邀，我推却了酒朋诗侣。记得汴京繁盛时，闺中多暇，最重元宵三五。人人翠冠雪柳，打扮得齐整俏丽。如今憔悴不堪，鬓发斑白，怕在夜间出门，不如躲在帘儿底下，听旁人欢声笑语。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"生查子元夕\"\u003e生查子·元夕\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e去年元夜时，花市灯如昼。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e月上柳梢头，人约黄昏后。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e今年元夜时，月与灯依旧。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e不见去年人，泪湿春衫袖。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·欧阳修\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e去年元宵夜，花市灯火亮如白昼。月上柳梢，与心上人相约黄昏之后。今年元宵，月与灯依旧璀璨，却不见去年那人，泪沾春衫袖。\u003c/p\u003e\n\u003c/div\u003e\n\u003cp\u003e\u003cimg src=\"/images/%e5%85%83%e5%ae%b5%e4%bd%b3%e8%8a%82/%e5%85%83%e5%ae%b5-%e7%81%af%e7%ac%bc.jpg\" alt=\"元宵灯笼\" width=\"4160\" height=\"6240\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch3 id=\"青玉案元夕\"\u003e青玉案·元夕\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e东风夜放花千树。更吹落、星如雨。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e宝马雕车香满路。凤箫声动，玉壶光转，一夜鱼龙舞。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e蛾儿雪柳黄金缕。笑语盈盈暗香去。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e众里寻他千百度。蓦然回首，那人却在，灯火阑珊处。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·辛弃疾\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e东风吹开元宵夜的花灯，如千树花开，又似繁星如雨飘落。宝马雕车香气满路，凤箫悠扬，玉壶流光，整夜鱼龙灯舞不息。游女们头戴蛾儿、雪柳、黄金缕，笑语盈盈，暗香远去。我在人群中千百次寻觅那人，蓦然回首，却见她立在灯火阑珊、清冷僻静之处。\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"poem-year-end\"\u003e\n\u003cp class=\"year-end-title\"\u003e〇 札记\u003c/p\u003e\n\u003cp class=\"year-end-placeholder\"\u003e元宵佳节，研二下学期的开端，感觉自己今天才刚刚进入状态，换句话说，刚刚从放假的状态回归，坚持学习，坚持锻炼，争取改掉许许多多的坏习惯！保持健康的身体为先，在做自己喜欢的事中学习为次。\u003c/p\u003e\n\u003ca href=\"/posts/2026-%E5%B9%B4%E6%80%BB/\" class=\"year-end-link\"\u003e→ 年终总结 · 2026\u003c/a\u003e\n\u003c/div\u003e","tags":["诗","诗/节日"],"title":"元宵佳节"},{"content":" 不远不近\n作者：刘玄德的作文墙\n近了会倦，远了会陌生。不要走近我，也不要离我远去。\n这句话，我用了三十年才读懂。\n我到现在都记得1998年的冬天，雪漫过了土坯房的门槛。妈揣着卖32个鸡蛋的钱，走了六里雪路去镇上，给我买3块5的新华字典。她回来时裤腿冻得硬邦邦，鞋上的泥结了冰，可怀里的字典用蓝布手帕包着，连个折角都没有，暖乎乎的。那时候，我离她很近。她劈柴，我蹲在门口看；她做饭，我趴在灶台边闻；夜里风吹塑料布窗哗啦响，她把我揣进棉袄怀里。肥皂味混着柴火味。那是我这辈子认定的，最安全、最暖的味道。\n后来我上了初中，开始要面子了。嫌她穿打补丁的衣服，嫌她说话带口音，嫌她来学校给我送馍丢人。有次她拎着一布包白面馍和腌萝卜来，我当着全班的面把馍推回去，冲她喊：「谁让你来的？赶紧走！」她没说话，蹲下来捡我碰掉的馍，拍了拍土又塞给我，声音小小的：「娃，饿了吃。」我没有回头。那是我第一次，主动拉开距离。\n再后来，我去上大学了，一年回一次家。打电话总是匆匆挂断，她说家里白菜长了、鸡下蛋了，我总说「知道了，我忙着呢」。我们离得越来越远，远到除了「吃了吗」「穿暖点」，再也找不到多余的话。原来远了，真的会陌生。\n等我在城里买了房，第一时间把她接来，想给她过好日子。可住在一起才发现，我们之间隔了太多东西。她去小区捡纸壳堆阳台，我嫌丢人跟她吵；她把剩菜热了一遍又一遍舍不得倒，我冲她喊吃了会拉肚子；她五点起来做早饭，我嫌吵摔了房门，她就安安静静坐在客厅等我，饭凉了就再热一遍。我们离得太近了，近到我把所有坏脾气都撒在了她身上。原来近了，真的会倦。\n那晚，我发了高烧迷迷糊糊，她用温水一遍遍擦我的额头。我睁眼看见她坐在床边，头发白了大半，像当年雪落在土坯房门口。我摸她的手，全是老茧，还有当年给人剥玉米磨出的疤，硬得硌人。我抱着她哇的一声哭出来，一遍遍地说对不起，她拍着我的背，像哄小时候的我一样：「傻娃，妈不怪你，妈啥都知道。」\n可开春她还是回了老家，说城里住不惯，还是土坯房踏实。我知道，她是怕给我添麻烦，怕我再因为她生气烦心。从那以后，我就陷在了无尽的拧巴里。想把她接来，怕我的刺再扎伤她，近了会倦；想让她在老家安稳度日，又怕离得太远，她有个头疼脑热我都赶不回去，远了会陌生。原来那句话，是我这辈子，最不敢对她说出口的心里话：不要走近我，我怕我的尖刺扎伤你；也不要离我远去，我怕一回头，就再也找不到你。\n昨天，我接到邻居电话。她说，妈走得很快。我回到老家时，土坯房门口的雪还没化，屋里很整齐。炕头压着一只旧纸箱。里面是萝卜干、红薯干、鞋垫。最底下，是那块蓝布手帕。包着零钱。一块、五块、十块。还有一张纸条。没封口。没贴邮票。没有寄出。字歪歪扭扭——「娃，别太累。妈有钱。」日期，是三个月前。原来，她什么都准备好了。只是不敢走近。也舍不得离远。于是那封信，就停在那里。停在「不远不近」的地方。\n雪慢慢落。蓝布手帕叠得整齐。我第一次，主动把它揣进怀里。它是冷的。这一次，再也捂不热了。\n刘玄德的作文墙，文学作者，擅长以质朴笔触书写亲情与人生况味，作品多发表于抖音等平台。\n作者链接：刘玄德的作文墙的抖音 - 抖音 ","permalink":"https://june6699.github.io/posts/%E4%B8%8D%E8%BF%9C%E4%B8%8D%E8%BF%91/","summary":"\u003cdiv class=\"prose-essay\"\u003e\n\u003cp class=\"prose-title\"\u003e不远不近\u003c/p\u003e\n\u003cp class=\"prose-author\"\u003e作者：刘玄德的作文墙\u003c/p\u003e\n\u003cdiv class=\"prose-body\"\u003e\n\u003cp\u003e近了会倦，远了会陌生。不要走近我，也不要离我远去。\u003c/p\u003e\n\u003cp\u003e这句话，我用了三十年才读懂。\u003c/p\u003e\n\u003cp\u003e我到现在都记得1998年的冬天，雪漫过了土坯房的门槛。妈揣着卖32个鸡蛋的钱，走了六里雪路去镇上，给我买3块5的新华字典。她回来时裤腿冻得硬邦邦，鞋上的泥结了冰，可怀里的字典用蓝布手帕包着，连个折角都没有，暖乎乎的。那时候，我离她很近。她劈柴，我蹲在门口看；她做饭，我趴在灶台边闻；夜里风吹塑料布窗哗啦响，她把我揣进棉袄怀里。肥皂味混着柴火味。那是我这辈子认定的，最安全、最暖的味道。\u003c/p\u003e","tags":["生活","生活/文章"],"title":"不远不近"},{"content":" 我的高考·安永全\n安永全\n晚来有闲，到康杰中学高三的文科班看了看就要面对高考的同学们，或者说是备受磨难的孩子们。三十八年前靠自修两次高考之事涌上心头，多少年来我羞于谈这些事，真的发生过吗？不提也罢，但几天下来却又恍恍惚惚神不守舍，终于还是按捺不住把它写了出来。如果这篇并不优秀，当时的心理也不健全，但确是真实的东西，能为一些同学们增加一点勇气，我将是非常高兴的。\n我愿把我经历了失败的成功献给你——希望你能用避免了失败的成功回赠我。\n没上高中，我也要考大学 我没有上过高中。\n我至今都为此感到遗憾。\n我于一九六零年在霍县初中毕业，学习成绩属于前五名，那一年开学并不考试，而是分配，我自然是要被分配上高中的，但我知道不行——家里的情况不行。\n当时我家住在县城，八口人，弟兄六人我为长，父亲是售货员工资三十四元，母亲早就对我说，上完初中就别上啦，不然弟妹们连小学也上不成，能认得钱就行啦……\n我总是说不出来话来。\n毕业离校的那一天，我把脸贴在霍县中学的匾牌上，泪流满面。\n以后，我当过小商贩，小工区装卸工，什么样赚钱就干什么。那时的工作很好找，但学徒工赚钱又很少，我的年龄也不到。后来，我终于找到一份固定的工作，就是拉人力车，主要是从离城十里路的副食品加工厂给霍县四个副食品店送酱油、醋，活少时就从大沟煤矿拉煤上街卖，一天大概能赚四元。\n那年，我十五岁。\n当时，霍县的东大街是一条长坡，用砖石和碎石铺的，坑坑洼洼，而第四副食品店又在坡顶上。拉车时，我狠低着头，伸长脖子，腰弓得几乎贴住地面，两手紧抓着辕杆，拼力向前，汗水常把眼睛打湿，前路一片迷茫。到最陡的地段，我简直怀疑自己是否长着腿，不然，怎么麻木得一点感觉都会没有呢？\n不管寒暑，不管风雨，我每天都要在这条长坡似的大街头上，展览一两回自己的狼狈。一九六一年的端午节，我多拉了一百斤，在东大街的最陡的地方，由于用力过猛，挣断了肩上的拉绳，脸撞向了地面，开了红花，失控的平车向后骤滑，穿过路边的行人和小摊。遇阻而翻过来，车上拉的酱油和醋满街乱流，惊叫声和责骂声混为一片。\n当我终于糊里糊涂地弄清发生了什么事的时候，承受着被撞伤的行人无情的责骂和拳打脚踢，面对着围观的人群中冷淡的目光，看着从脸上抹下的双手鲜血，特别是发现围观的人群里竟然有我初中时的同学，我脆弱的自尊心终于被撕破了，竟横躺在地上号啕大哭！\n古云：男儿有泪不轻弹，我从小就不是一个好男儿。\n但我终于明白了，生活不相信眼泪。\n穷，真是太可怕了，太残酷了。\n因为穷，你就要忍受痛苦和屈辱；因为穷，一样的胳膊一样的腿，人家能上高中，你就要天天拉平板车。人家能上大学，高中，而你的青春就只能这样被消磨。\n大学，那时我根本就不知道它是什么样。在想象里大学里的一切都放光芒，大学里的人都伟大高尚，前途无量，出来就能当教授、科学家、作家、将军、首长……更别说让全家吃饱穿暖！大学啊，那是我从小如痴如迷、如饥如渴的想往，为什么就和我无缘呢？\n什么上帝，什么神仙，什么沉沉大地，什么朗朗苍天，苍天啊！你究竟有没有长眼？\n苍天有眼 一九六一年秋天，我给澡堂送煤时，认识了高中学生谢俊杰（现任临纷市文联主席），闲淡中，他说：高考招生简章中有一句话，招生对象是高中毕业和具有同等学力的社会青年，后一类对象大概就是指你这号没有上过高中的人，你可以考文科，文科只考语文、政治、历史、地理和俄语，不考数理化。\n天啊！真是这样吗？我问。\n我到教育局再给你问问，他说。\n第三天，他拿给我一份去年招生简章，并告诉我教育局肯定的回答，但又告诉我，教育局的人说，没上高中考大学，在霍县可是没有先例。\n我惊喜异常，暗暗下决心，我决不能这样活，我要自修考大学，什么先例不先例，我就为什么不能成为先例呢？\n阴暗的心灵的天空透出了一丝亮光。\n我很快就找齐了文科的全部课目，堆起来像座小山，又把家里放杂物的小房开辟成学习间。我订了学习计划和时间表，早上六点起床学到八点，吃饭后去干活，下午六点再学习到十二点，除了拉车就是学习，什么都有不干，什么都不说，什么都不想，一本书一本书地啃，一段一段地念，一道题一道题地攻，一个词一个词地过，雷打不动，军令如山，三年课程两年半学完。\n但是，没多久，我就发现，当初实在是意气用事，可谓不以其事，不知其难呀！\n最难学的是俄语，我以前就根本没有接触过任何外语，翻开一看，哎呀！世界上怎么还有这样古怪的字呢？我越看越犯愁，越看越沮丧，好几夜，我就对着天书般的俄语课本在发愣，听着院里的鸡叫声，看着窗外越来越亮，一筹莫展，心情坏到极点，就拿起根棍子，又敲桌子，又打干墙，胡喊乱骂。\n中国人为什么要学习外国语言呢？人家苏联高考又不考咱汉语，咱们为什么要考俄语呢？真他娘的！\n可是顶什么用呢？我越骂越感到绝望，后来只好到霍中去找我曾经的化学老师，那时他也教俄语。\n张老师非常同情我，但又说，外语不是其他课，在家自修根本不可能，可他还是答应利用晚自习后在他家教我，然而去了几次后，我就觉得不行。张老师家四口人，房子很小，母亲卧病在床，爱人上班，孩子上学，第三次去时，他爱人的脸色很不好看，学习中间，他爱人还和他吵起来，使我非常难堪。\n我已记不清，我是怎样走出张老师家的，只是觉得怎么也不能来了，谁想张老师又半路上追上我来赔情道歉，弄得我更加尴尬。他又告诉我不如让我上初中的弟弟双全在家教我（那时的霍县中学也开了俄语课），学起来方便一点。根据前几年高考俄语试题的情况，初中俄语知识要占60%的量，如果把初中课程学懂了，能考40分左右，其他四门考得特别好，补上俄语的失分，也许会有机会达到分数线，但要有充分的思想准备，这是很难很难，不是一般的难。\n亲爱的张老师啊！我将永远永远记住你的恩情，在那时，只有你把我当人看，当你的学生看。\n以后，我就以我弟弟为俄语之师了，他现学现卖，虽然他水平有限，他的进度也完全制约着我的进度，但比此前有较大的改观。每天早上，我外出拉车前，我在两个胳膊上写五个单词，一边拉车一边念，念一遍俄语再念一遍俄译文，到第二天早晨再复习一遍，对了，擦掉再换十个单词写上，好几次，念着、念着，把车撞到了人身上，好几次过往汽车几乎撞在我身上。我已经顾不了这些了，一定要搬动俄语这座大山，全搬不动，也要搬它一少半。\n其他几门课，我除了地理课辅之以画图的方法外，基本上都用中国最传统的学习方法——背课文。背呀背……背呀背……\n在家学习的时候背，拉车时边拉边背，平时走路背，吃饭时心里背。有时集中一门背，有时五门课文叉着背，没人时大声背，有人时小声背，能背下去就继续往下背，背不下去就查随身带，再背。新学的要十遍八遍地背，已经背过的也要反复地背，背得人晕头转向，背得人心烦意乱，背得人脑袋好像要爆炸，嘴也快要说不出来话，古今中外，政、史、文、理内容那么多，跨度那么大，一个人的脑袋无非那样点，但要在很有限的时间，装进那么多东西。还要不间断地一门一门、一层一层、一句一句理清楚，背出来那种感觉不亲自经历，绝难想象；而一旦经历，便终身难忘。\n一天又一天，一月又一月。花开花落，暑来寒往背书声给我换来一个又一个太阳，又把我带入一个又一个梦乡。\n一九六三年夏天。\n我虽然觉得我自学的时间不短，按计划还要学一年，学得很不扎实，很不条理，明显存在着很多的空当，但又觉得还不是一塌糊涂，还是掌握了许多东西，特别是觉得应该体验一下高考的滋味，摸一摸各科试题的深浅。当然又想——也许啊，也许、也许一侥幸会有奇迹出现。\n报名遇上大麻烦 那一天，带上居委会的介绍信和招生简章我战战兢兢地到了霍县招生办，我知道本县高三应届的毕业生和复习班的往届学生都是学校统一报名的，而我这种情况，只有我一个，总担心不会很顺当。\n进门后，招办的人在打扑克，我恭恭敬敬地每人叫了声老师，把居委会的证明双手交给一个看上去像领导的人，说：「我想报个名」；谁想他看了我一眼，笑了笑，就一下子扔到地上，他问，小伙子你知道什么叫癞蛤蟆想吃天鹅肉吗？我说：你说我是蛤蟆我承认，但我不是癞蛤蟆，我说我是好蛤蟆，谁想他一下子就发了火，大声责问我，好蛤蟆就能吃上天鹅肉吗？蛤蟆就是蛤蟆！他们又去打扑克去了，我站着等呀等，真不知道该怎么办。等他们打完了，我又低声下气地说了不知多少好话，还是没人搭理我，我实在忍不住了，就说，老师，我给你磕个头，求你行行好，给我报上名，让我试一试吧……\n在霍县报名、体检领上准考证后，我就去了临汾。当时霍县的考场设在临汾一中，高考前一天我就坐火车到了临汾，我是第一次到临汾，又无亲无故，四处打听才找到考场，我不敢在外面住宿，怕睡过头了误了考试的时间，只好就睡在临汾一中的操场边上。\n两天考完，又生气，又悲伤。\n有些问题就没学过，只能看着试卷干瞪眼，有些是学得不扎实，影影糊糊知道，却答不上，有些题是时间没有掌握好，本来能答上，但还没有答完就被撤了卷，特别是心理素质不强，有的问题过去明明记得很牢，在考场却怎么也想不起，越想不起就越着急，越着急就越想不起来。最糟糕的是在考我自认为最强项的语文时，竟把作文题目「当我唱起国际歌的时候」看成「当我唱起国歌的时候」，一字之差，四十五分就全丢啦，至于我费了千辛万苦的俄语，下来和别人一对答案，最多只能得到五分。\n唉，第一次高考就这样收场了。\n虽然我本来就是把它当作一次试验，但还是使我想起了阿Q。\n又想起了蛤蟆。\n我终于站在了一个新的水平线上 第一次失败使我成为了别人的笑料。\n第一次高考，引发了我对高考的思考。\n高考究竟考什么？\n好像通过答卷考文化知识，其实高考在考决心考你对高考的认识，考你是否知道高考是人生的第一个转折点，假如你能闯过高考的炼狱对大多数人来讲，才算具备了走向理想的起码条件；考你有没有信心做个有用的人，做个你所羡慕的那种人；考你有没有决心回报爱着你的人，关心着你的人，期盼着你的人，有没有决心为中华民族乃至人类做点事情；贫家的子女有没有决心改变命运，条件优越家的子女有没有决心开辟更美好的人生，决心是成功的母亲。\n高考是考能力，考吃苦精神，考自信心，是啊！美好世界，花季少年，却没有了消闲，没有了浪漫，没有了欢唱，看到的就是那些冰冷的公式，单词、试题、还有哪些也许除了应试而毫无用处的东西，它充斥着你，压抑着你，戏弄着你，折磨着你。而且不是一天、一月、不是一年、二年，如果你能一刻也不减弱自己的努力，如果你能不间断，是把苦吃下，把苦嚼烂，把苦消化，能感到这是一种幸福，如果你能冲满自信去面对难关，成功也许并不太难。有人说高考是科举制度的翻版，但过去科举，每年全国只录取几百名举人、二、三十名进士，其中一名状元，一名榜眼，一名探花。而如今，虽然有人说高考是独木桥，但这个独木桥上每年通过的队伍毕竟是几十万、几百万，浩浩荡荡……\n高考也是考学习的方法，虽然前人已归纳出不少基本方法，但理性的原则对个体来讲，都不可能完全适用，世界上没有两粒完全相同的沙子，每个人都必须摸索具有个人特色的方法，高考即是战场，战场上就是讲究战术，只有冠军，绝不允许有亚军，亚军那就意味着死亡，正确的战术可以死而后生，正确的方法可以事半功倍。\n高考啊，高考，你可以诅骂它是残酷的，可怕的，沉重的，不公道的，充满弊病的，但在更完美的制度取代它之前，你还是要面对现实，战胜自己，战胜自己的懒惰、脆弱、得过且过；战胜自己的迟钝、死板，粗枝大叶，以战胜高考来武装自己，武装到每一个细胞，武装到每一分每一秒。\n我为自己重新制订了学习计划，调整了外语和其他课的投入比例，只学初中外语，放弃高中外语，以达到45分为目标，以90分的时间和精力使其他四门课均达到85分以上，以强补弱，强项让它更强。\n不就是三十几本书？\n不就是两千多道题吗？\n为了加深记忆，不仅要把记住、背会，而且要能基本写出来，历史课要做到，把课本书放在一边，拿两本稿纸把一个世纪一个世纪、一个朝代一个朝代的重大事情，重大人物，重要时间，统统写出，要做到一个标点符号都不差地写出来，写不下去就查书，再写时就容易记住了。\n为了锻炼思维敏捷和临场应变能力，我将各门课的试题，分别写在纸条上，卷成纸捻子，大题是长捻子，小题是短捻子，放在五个小盒子里，每次先摆好闹钟，抽出五道大题，二十道小题，在两个小时做完，而后对照课本阅卷打分。\n为了把作文的时间合理化，就自己出了各种体裁和类别的五十道作文题，随时抽出一道练习在50分钟内完成，各种试题都如此反复练习。\n我觉得我尽了最大的努力，想尽了能想出的办法，做到了扎扎实实，步步为营，我实在不敢拿我的未来去赌博，去侥幸。\n然而，人还是无法预料命运。\n一九六四年六月，居民小组通知我上山下乡到西张村，这将意味着我将丧失自修的条件，使考大学成为泡影。我只能改变再学一年，明年再去高考的计划，准备第二次仓促上阵。这时距离高考只有十七天。\n我又一次来到县城招办楼，碰见了又是去年那个人，他说县上的报名体检已经结束，地区也只有明天一天时间，看着办吧。\n我已经没有了选择。\n我赶回家拿了钱，背上书，换了证明，跑到火车站，想坐三点半的车，到临汾报名，到售票口一看，只见贴着一张公告，因介休至灵石区间被洪水冲断，列车暂停，预计两天。\n我也被命运激怒了，没有火车还有两条腿，干脆破罐子破摔了，我沿着铁路线一直朝前走，一百五十华里路走了十二个小时，第二天凌晨到达临汾，报名体验结束后，又由临汾沿铁路回霍县，回到家倒头便睡，睡了一天，醒来后，两腿肿得水桶一般，脚底像撕烂的红布片。\n我一切都无从顾及了，除了不敢停止拉车，怕大学考不上又丢了饭碗，学得已近乎于疯狂，除了试题，除了答案，像是一切都不存在，没有了自己，也没有了世界，没有了月亮，也没有了太阳。\n我实施了「头悬梁锥刺股」的实践。\n我不知道战国时的苏秦和东汉的孙敬当年是如何运用这种办法战胜疲劳的，而我却难以奏效。\n当我把头发扎紧，用绳子吊在屋顶上，不一会儿又沉沉入睡，那种程度的疼痛根本就无法战胜昏迷似的疲倦。\n锥刺股吧，锥了，刺不出血，不疼就等于不刺，刺得厉害了，倒是有效，三四个小时再也不会睡着，一边压着出血的地方，一边学习，但刺不上几次，伤口便发生了感染，溃烂。\n我想了一个办法。\n我想起了我妈。\n我妈是个严厉的人，就属于电视连续剧「大宅门」中二奶奶那种类型的人，记得小时候逃学时被发现，父亲把我吊到树上，拿一根木棍，训斥声和动作虽很大，但棍子落在身上并不疼，于是我们继续逃学，第二次父亲又打我时，我妈在一边看着，并不说话，拿一把钳子在腿上狠一拧，转身就走，我大声一呼，腿上虽没有出血却再也不敢逃学，我最爱我妈，也最怕我妈，一见我妈手里拿着钳子腿就发抖。\n我需要我妈的钳子，就把这想法告诉我妈。\n我妈问我，不考就不行吗？\n我说，不考不行，让我再试一回。\n我妈点了点头。\n那一夜，我又瞌睡了。当然我猛然被大腿的剧疼唤醒时，看见我妈手里拿着钳子却满脸泪水就再也睡不着了……\n在以后的十几天里，我妈就守着我学习，虽然她再也没有用过手里的钳子，但我也没有在学习时再瞌睡过，坚持每天学到凌晨三点。\n那一段，是我生命里的极限。\n那一段，是我妈对我的再生。\n高考终于来到了，考试终于结束了，政、史、文、理我感觉很好，一想到俄语又十分烦恼。我在忐忑不安的等待中度日如年，渐渐地听说，霍县中学生的录取通知书下来了，又听说文科三十七个人只有一个人考上了「山西大学」，就觉得这一次又完了。\n一九六四年，八月二十五号，这是我毕生难忘的一天，中午，我正在给家门口附近的商店卸货，忽见邮递员拿着一封信，打听我的名字。那以前，我和外界从没有信件联系，突发的预感使我飞跑过去，接过信，我手颤抖了，好久都不敢去拆，我简直没有勇气去聆听命运对我控制，当我终于咬着牙打开它时，一张高等院校录取通知书出现在我的眼前：安永全同学，你被录取为山西师范学院中文系学生，请于九月十日前来报到，师院就师院嘛，高兴得简直要疯狂，竟像范进中举一样，在大街上高喊：我考上了，我考上了，我考上了！\n我终于站在一个新的地平线上。\n虽然，我不知道以后将要走向什么地方。\n安永全（1945年8月—），山西霍州人，高级记者，中国作家协会会员。1970年开始发表作品，曾任山西省电台驻临汾记者站记者、站长，乡宁县委副书记、县长，临汾地委副秘书长，浮山县委书记，晋城市副市长，临汾行署副专员，运城地委、市委副书记，运城市政协党组书记、主席。 著有小说《明天》，散文《游云邱山》《悠悠长街》《夜宿独家村》《琢磨日本》《我看美国》《我的高考》，散文集《我的高考》。《游云邱山》1985年获全国优秀游记散文奖，《夜宿独家村》1992年获山西省模范散文奖。\n创作背景：2001年高考前夕，时任运城市委副书记的安永全去康杰中学看望复习的学子们，触景生情写下《我的高考》，后在教育界广为传播。\n","permalink":"https://june6699.github.io/posts/%E6%88%91%E7%9A%84%E9%AB%98%E8%80%83/","summary":"\u003cdiv class=\"prose-essay\"\u003e\n\u003cp class=\"prose-title\"\u003e我的高考·安永全\u003c/p\u003e\n\u003cp class=\"prose-author\"\u003e安永全\u003c/p\u003e\n\u003cdiv class=\"prose-body\"\u003e\n\u003cp\u003e晚来有闲，到康杰中学高三的文科班看了看就要面对高考的同学们，或者说是备受磨难的孩子们。三十八年前靠自修两次高考之事涌上心头，多少年来我羞于谈这些事，真的发生过吗？不提也罢，但几天下来却又恍恍惚惚神不守舍，终于还是按捺不住把它写了出来。如果这篇并不优秀，当时的心理也不健全，但确是真实的东西，能为一些同学们增加一点勇气，我将是非常高兴的。\u003c/p\u003e","tags":["生活","生活/文章"],"title":"我的高考·安永全"},{"content":"卜算子·自嘲 丁元英《卜算子·自嘲》\n本是后山人，偶做前堂客。醉舞经阁半卷书，坐井说天阔。大志戏功名，海斗量福祸。论到囊中羞涩时，怒指乾坤错。\n本是山野闲人，偶到前堂充充门面。仗着读过半卷书就高谈阔论，实不过井底之蛙坐井说天。空有大志、戏看功名，想把福祸得失都量个明白，可一到囊中羞涩时，便只会怒指乾坤有错。\n乾坤本无错，皆为世人过。贵贱缘尽终有时，皆为地下客。客乃地下坐，奈何福和祸。福祸相依皆有时，休问对与错。\n天地本无错，皆因世人自误。富贵贫贱总有尽头，终究都是黄土过客。归于尘土，又何必计较福祸？福祸相依，各有其时，不必追问对错。\n未曾清贫难成人，不经挫折永天真。人情似纸张张薄，世事如棋局局新。穷在闹市无人问，富在深山有远亲。不信你看宴中酒，杯杯先敬有钱人。\n未历清贫难成人，不经挫折永天真。人情薄如纸，世事新如棋。穷居闹市无人问，富隐深山有远亲。不信且看席间酒，杯杯先敬有钱人。\n杯中倒满无情酒，心中再无意中人。看尽人生红尘梦，尝尽人间疾苦情。\n杯中满是无情酒，心中已无意中人。看尽红尘繁华梦，尝尽人间疾苦情。\n","permalink":"https://june6699.github.io/posts/%E5%8D%9C%E7%AE%97%E5%AD%90%E8%87%AA%E5%98%B2/","summary":"\u003ch2 id=\"卜算子自嘲\"\u003e卜算子·自嘲\u003c/h2\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-meta\"\u003e丁元英《卜算子·自嘲》\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e本是后山人，偶做前堂客。醉舞经阁半卷书，坐井说天阔。大志戏功名，海斗量福祸。论到囊中羞涩时，怒指乾坤错。\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e本是山野闲人，偶到前堂充充门面。仗着读过半卷书就高谈阔论，实不过井底之蛙坐井说天。空有大志、戏看功名，想把福祸得失都量个明白，可一到囊中羞涩时，便只会怒指乾坤有错。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e乾坤本无错，皆为世人过。贵贱缘尽终有时，皆为地下客。客乃地下坐，奈何福和祸。福祸相依皆有时，休问对与错。\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e天地本无错，皆因世人自误。富贵贫贱总有尽头，终究都是黄土过客。归于尘土，又何必计较福祸？福祸相依，各有其时，不必追问对错。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e未曾清贫难成人，不经挫折永天真。人情似纸张张薄，世事如棋局局新。穷在闹市无人问，富在深山有远亲。不信你看宴中酒，杯杯先敬有钱人。\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e未历清贫难成人，不经挫折永天真。人情薄如纸，世事新如棋。穷居闹市无人问，富隐深山有远亲。不信且看席间酒，杯杯先敬有钱人。\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e杯中倒满无情酒，心中再无意中人。看尽人生红尘梦，尝尽人间疾苦情。\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e杯中满是无情酒，心中已无意中人。看尽红尘繁华梦，尝尽人间疾苦情。\u003c/p\u003e\n\u003c/div\u003e","tags":["诗","诗/杂感"],"title":"卜算子·自嘲"},{"content":"今日除夕，在此祝各位马年大吉！\n旧岁至此而除，新年自明旦而始 点绛唇·何处君家 今年见。明年重见。春色如人面。\n宋·毛滂\n今年相见，明年还要再相会，春光如故人面容般明媚动人。\n满江红 年年约，常相见。但无事，身强健。\n金·蔡松年\n年年相约，常常聚首，只盼平安无事、身康体健。\n岁日 一日今年始，一年前事空。\n唐·元稹\n今日是新年之首，往岁的烦忧皆已翻篇成空。\n诉衷情·友人生日 朱颜长似，头上花枝，岁岁年年。\n宋·葛胜仲\n愿容颜如头上花枝般常驻，岁岁年年，青春不减。\n元旦试笔 老去又逢新岁月，春来更有好花枝。\n明·陈献章\n年华渐老却迎来崭新岁月，春回大地，更有繁花满枝相迎。\n别高子勉兄弟 南北奔波岁月催，足间浑未洗尘埃。\n休将旧事从头说，且喜新年入手来。\n宋·王铚\n南北奔波，岁月催人，脚上风尘未净。莫再提往日辛酸，且喜新年已在眼前。\n喜迁莺·守岁 待到了，道一声稳睡，明年相见。\n宋·史浩\n守岁至天明，互道一声安寝，相约来年再会。\n木兰花 欢声喜气逐时新，青鬓玉颜长似旧。\n宋·晏殊\n欢声笑语与喜气时时焕新，青丝朱颜却依然如故、岁月静好。\n卜算子 唯愿花心似我心，岁岁长相守。\n佚名\n唯愿你我心意相通，岁岁年年长相厮守。\n少年游·谢家庭槛晓无尘 岁岁年年，共欢同乐，嘉庆与时新。\n宋·晏殊\n岁岁年年，同欢共乐，吉庆随节令常新。\n元日述怀 愿得长如此，年年物候新。\n唐·卢照邻\n但愿年年如此安好，四时物候岁岁常新。\n巳酉元旦 不改山河旧，同瞻日月新。\n明·贝琼\n山河依旧不改，共同瞻望日月新篇。\n诉衷情·海棠 如花似叶，岁岁年年，共占春风。\n宋·苏轼\n如花与叶般相依，岁岁年年，共沐春风。\n去岁千般皆如愿，今年万事定称心 去岁千般皆如愿，今年万事定称心。\n宋·释道原\n去岁事事遂心如愿，今岁万事定当称心如意。\n转调蹋莎行·元旦 从今诸事愿、胜如旧。人生强健，喜一年入手。\n元·王寂\n愿从今往后诸事更胜往昔，身体强健，喜迎新岁入手。\n〇 札记\n（此处待填写，详见年终总结）\n{% assign year_post = site.posts | where: \"title\", \"2026 年终总结\" | first %}→ 年终总结 · 2026 ","permalink":"https://june6699.github.io/posts/%E6%96%B0%E5%B9%B4%E5%88%B0/","summary":"\u003cdiv class=\"poem-festival-wish\"\u003e今日除夕，在此祝各位\u003cstrong\u003e马年大吉\u003c/strong\u003e！\u003cbr\u003e旧岁至此而除，新年自明旦而始\u003c/div\u003e\n\u003ch3 id=\"点绛唇何处君家\"\u003e点绛唇·何处君家\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e今年见。明年重见。春色如人面。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·毛滂\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e今年相见，明年还要再相会，春光如故人面容般明媚动人。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"满江红\"\u003e满江红\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e年年约，常相见。但无事，身强健。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e金·蔡松年\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e年年相约，常常聚首，只盼平安无事、身康体健。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"岁日\"\u003e岁日\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e一日今年始，一年前事空。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e唐·元稹\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e今日是新年之首，往岁的烦忧皆已翻篇成空。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"诉衷情友人生日\"\u003e诉衷情·友人生日\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e朱颜长似，头上花枝，岁岁年年。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·葛胜仲\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e愿容颜如头上花枝般常驻，岁岁年年，青春不减。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"元旦试笔\"\u003e元旦试笔\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e老去又逢新岁月，春来更有好花枝。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e明·陈献章\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e年华渐老却迎来崭新岁月，春回大地，更有繁花满枝相迎。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"别高子勉兄弟\"\u003e别高子勉兄弟\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e南北奔波岁月催，足间浑未洗尘埃。\u003cbr\u003e休将旧事从头说，且喜新年入手来。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·王铚\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e南北奔波，岁月催人，脚上风尘未净。莫再提往日辛酸，且喜新年已在眼前。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"喜迁莺守岁\"\u003e喜迁莺·守岁\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e待到了，道一声稳睡，明年相见。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·史浩\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e守岁至天明，互道一声安寝，相约来年再会。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"木兰花\"\u003e木兰花\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e欢声喜气逐时新，青鬓玉颜长似旧。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·晏殊\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e欢声笑语与喜气时时焕新，青丝朱颜却依然如故、岁月静好。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"卜算子\"\u003e卜算子\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e唯愿花心似我心，岁岁长相守。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e佚名\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e唯愿你我心意相通，岁岁年年长相厮守。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"少年游谢家庭槛晓无尘\"\u003e少年游·谢家庭槛晓无尘\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e岁岁年年，共欢同乐，嘉庆与时新。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·晏殊\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e岁岁年年，同欢共乐，吉庆随节令常新。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"元日述怀\"\u003e元日述怀\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e愿得长如此，年年物候新。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e唐·卢照邻\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e但愿年年如此安好，四时物候岁岁常新。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"巳酉元旦\"\u003e巳酉元旦\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e不改山河旧，同瞻日月新。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e明·贝琼\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e山河依旧不改，共同瞻望日月新篇。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"诉衷情海棠\"\u003e诉衷情·海棠\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e如花似叶，岁岁年年，共占春风。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·苏轼\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e如花与叶般相依，岁岁年年，共沐春风。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"去岁千般皆如愿今年万事定称心\"\u003e去岁千般皆如愿，今年万事定称心\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e去岁千般皆如愿，今年万事定称心。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e宋·释道原\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e去岁事事遂心如愿，今岁万事定当称心如意。\u003c/p\u003e\n\u003c/div\u003e\n\u003ch3 id=\"转调蹋莎行元旦\"\u003e转调蹋莎行·元旦\u003c/h3\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-lines\"\u003e从今诸事愿、胜如旧。人生强健，喜一年入手。\u003c/p\u003e\n\u003cp class=\"poem-meta\"\u003e元·王寂\u003c/p\u003e\n\u003cp class=\"poem-interp\"\u003e愿从今往后诸事更胜往昔，身体强健，喜迎新岁入手。\u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv class=\"poem-year-end\"\u003e\n\u003cp class=\"year-end-title\"\u003e〇 札记\u003c/p\u003e\n\u003cp class=\"year-end-placeholder\"\u003e（此处待填写，详见年终总结）\u003c/p\u003e\n{% assign year_post = site.posts | where: \"title\", \"2026 年终总结\" | first %}\u003ca href=\"{{ site.baseurl }}{{ year_post.url }}\" class=\"year-end-link\"\u003e→ 年终总结 · 2026\u003c/a\u003e\n\u003c/div\u003e","tags":["诗","诗/节日"],"title":"马年到"},{"content":"清平乐·六盘山 毛主席\n天tiān高gāo云yún淡dàn，望wàng断duàn南nán飞fēi雁yàn。 不bú到dào长cháng城chéng非fēi好hǎo汉hàn，屈qū指zhǐ行xíng程chéng二èr万wàn。 六liù盘pán山shān上shàng高gāo峰fēng，红hóng旗qí漫màn卷juǎn西xī风fēng。 今jīn日rì长cháng缨yīng在zài手shǒu，何hé时shí缚fù住zhù苍cāng龙lóng？\n译文 长空高阔，白云清朗，南飞的大雁已望至天边。不登临长城关口算不得英雄，屈指一算征程已有二万。六盘山上雄峰再拔，烈烈西风漫卷红旗。今日长缨在手，何时缚住苍龙？\n作者介绍 毛泽东（1893—1976），字润之，笔名子任。生于湖南湘潭韶山一个农民家庭。中国人民的领袖，马克思主义者、无产阶级革命家、战略家、理论家、诗人、书法家。被《时代》杂志评为“20世纪最具影响100人”之一，被视为现代世界历史中最重要的人物之一。代表作品有《矛盾论》《实践论》《论持久战》《沁园春·雪》等，有《毛泽东选集》。\n感悟 抖音最近很火的爬长城后，来上这么一段，真是惬意啊，相信长城也是许多大学生的目标旅游地之一吧！\n","permalink":"https://june6699.github.io/posts/%E6%B8%85%E5%B9%B3%E4%B9%90%E5%85%AD%E7%9B%98%E6%B0%B4/","summary":"\u003ch2 id=\"清平乐六盘山\"\u003e清平乐·六盘山\u003c/h2\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-meta\"\u003e毛主席\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e\n\u003cruby\u003e天\u003crt\u003etiān\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e高\u003crt\u003egāo\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e云\u003crt\u003eyún\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e淡\u003crt\u003edàn\u003c/rt\u003e\u003c/ruby\u003e，\u003cruby\u003e望\u003crt\u003ewàng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e断\u003crt\u003eduàn\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e南\u003crt\u003enán\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e飞\u003crt\u003efēi\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e雁\u003crt\u003eyàn\u003c/rt\u003e\u003c/ruby\u003e。\n\u003cruby\u003e不\u003crt\u003ebú\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e到\u003crt\u003edào\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e长\u003crt\u003echáng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e城\u003crt\u003echéng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e非\u003crt\u003efēi\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e好\u003crt\u003ehǎo\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e汉\u003crt\u003ehàn\u003c/rt\u003e\u003c/ruby\u003e，\u003cruby\u003e屈\u003crt\u003eqū\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e指\u003crt\u003ezhǐ\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e行\u003crt\u003exíng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e程\u003crt\u003echéng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e二\u003crt\u003eèr\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e万\u003crt\u003ewàn\u003c/rt\u003e\u003c/ruby\u003e。\n\u003cruby\u003e六\u003crt\u003eliù\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e盘\u003crt\u003epán\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e山\u003crt\u003eshān\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e上\u003crt\u003eshàng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e高\u003crt\u003egāo\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e峰\u003crt\u003efēng\u003c/rt\u003e\u003c/ruby\u003e，\u003cruby\u003e红\u003crt\u003ehóng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e旗\u003crt\u003eqí\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e漫\u003crt\u003emàn\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e卷\u003crt\u003ejuǎn\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e西\u003crt\u003exī\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e风\u003crt\u003efēng\u003c/rt\u003e\u003c/ruby\u003e。\n\u003cruby\u003e今\u003crt\u003ejīn\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e日\u003crt\u003erì\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e长\u003crt\u003echáng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e缨\u003crt\u003eyīng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e在\u003crt\u003ezài\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e手\u003crt\u003eshǒu\u003c/rt\u003e\u003c/ruby\u003e，\u003cruby\u003e何\u003crt\u003ehé\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e时\u003crt\u003eshí\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e缚\u003crt\u003efù\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e住\u003crt\u003ezhù\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e苍\u003crt\u003ecāng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e龙\u003crt\u003elóng\u003c/rt\u003e\u003c/ruby\u003e？\u003c/p\u003e","tags":["诗","诗/名篇","诗/名篇/近现代"],"title":"清平乐·六盘山"},{"content":"鹧鸪天·西都作 宋·朱敦儒\n上阕\n我wǒ是shì清qīng都dū山shān水shuǐ郎láng，天tiān教jiào分fēn付fù与yǔ疏shū狂kuáng。\n曾céng批pī给jǐ雨yǔ支zhī风fēng券quàn，累lěi上shàng留liú云yún借jiè月yuè章zhāng。 下阕\n诗shī万wàn首shǒu，酒jiǔ千qiān觞shāng。几jǐ曾céng着zhuó眼yǎn看kàn侯hóu王wáng？\n玉yù楼lóu金jīn阙què慵yōng归guī去qù，且qiě插chā梅méi花huā醉zuì洛luò阳yáng。 译文 我本是天上司掌山水的郎官，天性疏狂不羁。天帝曾批给我掌管风露的诏书，我也屡次上呈留云借月的奏章。诗一写便是万首，酒一饮便是千杯，何曾正眼瞧过王侯将相。天上玉楼金阙懒得归去，只愿插枝梅花醉卧洛阳。\n作者介绍 朱敦儒（1081年—1159年），字希真，号岩壑，又称伊水老人、洛川先生，祖籍河南洛阳。少有文名，绍兴五年（1135年）经举荐获进士出身，担任秘书省正字。本是主战派，后阿附秦桧，受任鸿胪寺少卿，时人非之。朱敦儒诗词皆长，尤工词。多写隐逸生活，词风旷达洒脱。南渡后也写过一些关注国事的作品，境界苍凉。\n感悟 一个字，狂！\n","permalink":"https://june6699.github.io/posts/%E9%B9%A7%E9%B8%AA%E5%A4%A9-%E8%A5%BF%E9%83%BD%E4%BD%9C/","summary":"\u003ch2 id=\"鹧鸪天西都作\"\u003e鹧鸪天·西都作\u003c/h2\u003e\n\u003cdiv class=\"poem-content\"\u003e\n\u003cp class=\"poem-meta\"\u003e宋·朱敦儒\u003c/p\u003e\n\u003cp class=\"poem-stanza\"\u003e上阕\u003c/p\u003e\n\u003cp class=\"poem-lines\"\u003e\n\u003cruby\u003e我\u003crt\u003ewǒ\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e是\u003crt\u003eshì\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e清\u003crt\u003eqīng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e都\u003crt\u003edū\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e山\u003crt\u003eshān\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e水\u003crt\u003eshuǐ\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e郎\u003crt\u003eláng\u003c/rt\u003e\u003c/ruby\u003e，\u003cruby\u003e天\u003crt\u003etiān\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e教\u003crt\u003ejiào\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e分\u003crt\u003efēn\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e付\u003crt\u003efù\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e与\u003crt\u003eyǔ\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e疏\u003crt\u003eshū\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e狂\u003crt\u003ekuáng\u003c/rt\u003e\u003c/ruby\u003e。\u003cbr\u003e\n\u003cruby\u003e曾\u003crt\u003ecéng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e批\u003crt\u003epī\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e给\u003crt\u003ejǐ\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e雨\u003crt\u003eyǔ\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e支\u003crt\u003ezhī\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e风\u003crt\u003efēng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e券\u003crt\u003equàn\u003c/rt\u003e\u003c/ruby\u003e，\u003cruby\u003e累\u003crt\u003elěi\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e上\u003crt\u003eshàng\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e留\u003crt\u003eliú\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e云\u003crt\u003eyún\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e借\u003crt\u003ejiè\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e月\u003crt\u003eyuè\u003c/rt\u003e\u003c/ruby\u003e\u003cruby\u003e章\u003crt\u003ezhāng\u003c/rt\u003e\u003c/ruby\u003e。\n\u003c/p\u003e","tags":["诗","诗/名篇"],"title":"鹧鸪天·西都作"},{"content":"问题描述 当我们下载了某些软件后，右键菜单常常变得冗余，从而看起来很不舒服，如下图所示：\n原因分析 Win11 的新版右键菜单采用了二级菜单设计（\u0026ldquo;显示更多选项\u0026rdquo;），当系统中安装了过多第三方软件时，这些软件会在右键菜单中注册大量菜单项。由于 Win11 的新菜单需要动态加载这些第三方菜单项，当菜单项过多或某些软件响应较慢时，就会出现\u0026quot;正在加载中\u0026quot;的提示，导致右键菜单响应迟缓，影响使用体验。\n解决方案 方案一：切换为 Win10 传统右键菜单（推荐） 将 Win11 的新版右键菜单切换为 Win10 的传统样式，可以彻底解决\u0026quot;正在加载中\u0026quot;的问题，同时菜单响应速度更快。\n文件下载 GitHub 源码地址：点击访问 本地文件下载：点击下载 （下载后请将文件后缀改为 .bat） 脚本内容 以下为脚本完整内容，您可以选择下载文件或复制代码：\n@echo off \u0026gt;nul 2\u0026gt;\u0026amp;1 \u0026#34;%SYSTEMROOT%\\system32\\cacls.exe\u0026#34; \u0026#34;%SYSTEMROOT%\\system32\\config\\system\u0026#34; if \u0026#39;%errorlevel%\u0026#39; NEQ \u0026#39;0\u0026#39; ( goto UACPrompt ) else ( goto gotAdmin ) :UACPrompt echo Set UAC = CreateObject^(\u0026#34;Shell.Application\u0026#34;^) \u0026gt; \u0026#34;%temp%\\getadmin.vbs\u0026#34; echo UAC.ShellExecute \u0026#34;%~s0\u0026#34;, \u0026#34;\u0026#34;, \u0026#34;\u0026#34;, \u0026#34;runas\u0026#34;, 1 \u0026gt;\u0026gt; \u0026#34;%temp%\\getadmin.vbs\u0026#34; \u0026#34;%temp%\\getadmin.vbs\u0026#34; exit /B :gotAdmin if exist \u0026#34;%temp%\\getadmin.vbs\u0026#34; ( del \u0026#34;%temp%\\getadmin.vbs\u0026#34; ) @echo off echo. echo ============================================= echo 右键菜单类型 echo 1 (Win10旧版右键菜单) echo 2 (Win11新版右键菜单) echo ============================================= :select set /p opt=请选择操作： if %opt%==1 ( echo 正在开启Win10旧版右键菜单········· reg add \u0026#34;HKCU\\Software\\Classes\\CLSID\\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\\InprocServer32\u0026#34; /f /ve ) if %opt%==2 ( echo 正在恢复Win11新版右键菜单········· reg delete \u0026#34;HKCU\\Software\\Classes\\CLSID\\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\u0026#34; /f ) @echo off echo ************************************* echo * * echo * 重启任务管理器... * echo * * echo ************************************* taskkill /f /im explorer.exe \u0026amp; start explorer.exe pause 使用说明：\n下载文件后，将文件后缀从 .txt 改为 .bat 右键以管理员身份运行 选择 1 切换到 Win10 传统右键菜单 如需恢复 Win11 新版菜单，再次运行脚本选择 2 方案二：火绒安全专用版本 如果您使用的是火绒安全软件，可以使用以下专用版本。\n0、用户须知 ⚠️ 重要提示：电脑操作期间，因需重启资源管理器，所以会短暂黑屏/闪屏，属于正常现象。\n1、版本一 放到火绒安全的 bin 文件夹下点击执行即可：\n@echo off cd /d \u0026#34;%~dp0\u0026#34; regsvr32 /s HrShredShell.dll regsvr32 /s HRShell.dll taskkill /f /im explorer.exe start explorer.exe echo Done. pause 说明：因为转换后，火绒的菜单可能会消失，使用此脚本可以重新加载火绒的右键菜单项。\n补充：添加常用工具到右键菜单 添加 CMD 命令窗口 在文件夹右键菜单中添加\u0026quot;在此处打开命令窗口\u0026quot;选项：\nWindows Registry Editor Version 5.00 # 在文件夹背景空白处右键 [HKEY_CLASSES_ROOT\\Directory\\Background\\shell\\OpenCMDHere] @=\u0026#34;在此处打开命令窗口(\u0026amp;W)\u0026#34; \u0026#34;Icon\u0026#34;=\u0026#34;cmd.exe\u0026#34; [HKEY_CLASSES_ROOT\\Directory\\Background\\shell\\OpenCMDHere\\command] @=\u0026#34;cmd.exe /s /k pushd \\\u0026#34;%V\\\u0026#34;\u0026#34; # 在文件夹图标上右键 [HKEY_CLASSES_ROOT\\Directory\\shell\\OpenCMDHere] @=\u0026#34;在此处打开命令窗口(\u0026amp;W)\u0026#34; \u0026#34;Icon\u0026#34;=\u0026#34;cmd.exe\u0026#34; [HKEY_CLASSES_ROOT\\Directory\\shell\\OpenCMDHere\\command] @=\u0026#34;cmd.exe /s /k pushd \\\u0026#34;%V\\\u0026#34;\u0026#34; 使用方法：\n将上述内容保存为 .reg 文件 双击运行导入注册表 重启资源管理器或注销后生效 添加 VSCode 到右键菜单 在文件、文件夹右键菜单中添加\u0026quot;Open with Code\u0026quot;选项：\n📝 使用前请先设置 VSCode 路径：将下面的 VSCODE_PATH 变量替换为您实际的 VSCode 安装路径（例如：C:\\\\Program Files\\\\Microsoft VS Code\\\\Code.exe）\nWindows Registry Editor Version 5.00 # 请将下面的 VSCODE_PATH 替换为您的 VSCode 实际安装路径 # 例如：C:\\\\Program Files\\\\Microsoft VS Code\\\\Code.exe # 注意：路径中的反斜杠需要使用双反斜杠 \\\\ 转义 # 文件右键 [HKEY_CLASSES_ROOT\\*\\shell\\VSCode] @=\u0026#34;Open with Code\u0026#34; \u0026#34;Icon\u0026#34;=\u0026#34;\\\u0026#34;VSCODE_PATH\\\u0026#34;\u0026#34; [HKEY_CLASSES_ROOT\\*\\shell\\VSCode\\command] @=\u0026#34;\\\u0026#34;VSCODE_PATH\\\u0026#34; \\\u0026#34;%1\\\u0026#34;\u0026#34; # 文件夹右键 [HKEY_CLASSES_ROOT\\Directory\\shell\\VSCode] @=\u0026#34;Open with Code\u0026#34; \u0026#34;Icon\u0026#34;=\u0026#34;\\\u0026#34;VSCODE_PATH\\\u0026#34;\u0026#34; [HKEY_CLASSES_ROOT\\Directory\\shell\\VSCode\\command] @=\u0026#34;\\\u0026#34;VSCODE_PATH\\\u0026#34; \\\u0026#34;%V\\\u0026#34;\u0026#34; # 文件夹背景右键 [HKEY_CLASSES_ROOT\\Directory\\Background\\shell\\VSCode] @=\u0026#34;Open with Code\u0026#34; \u0026#34;Icon\u0026#34;=\u0026#34;\\\u0026#34;VSCODE_PATH\\\u0026#34;\u0026#34; [HKEY_CLASSES_ROOT\\Directory\\Background\\shell\\VSCode\\command] @=\u0026#34;\\\u0026#34;VSCODE_PATH\\\u0026#34; \\\u0026#34;%V\\\u0026#34;\u0026#34; 使用方法：\n将上述代码中所有的 VSCODE_PATH 替换为您实际的 VSCode 安装路径（例如：C:\\\\Program Files\\\\Microsoft VS Code\\\\Code.exe） 路径中的反斜杠需要使用双反斜杠 \\\\ 转义 保存为 .reg 文件 双击运行导入注册表 重启资源管理器或注销后生效 💡 提示：只需替换一次 VSCODE_PATH，所有位置会自动使用相同的路径。如果您的 VSCode 安装在默认位置，路径通常是 C:\\\\Users\\\\您的用户名\\\\AppData\\\\Local\\\\Programs\\\\Microsoft VS Code\\\\Code.exe。\n总结 通过以上方法，您可以：\n✅ 解决 Win11 右键菜单\u0026quot;正在加载中\u0026quot;的问题 ✅ 获得更快的右键菜单响应速度 ✅ 根据需要添加常用工具到右键菜单 如果遇到问题，欢迎在评论区留言讨论！\n","permalink":"https://june6699.github.io/posts/win11-right-click/","summary":"\u003ch2 id=\"问题描述\"\u003e问题描述\u003c/h2\u003e\n\u003cp\u003e当我们下载了某些软件后，右键菜单常常变得冗余，从而看起来很不舒服，如下图所示：\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/images/win11-right-click/Win11%e5%8f%b3%e9%94%ae%e6%ad%a3%e5%9c%a8%e5%8a%a0%e8%bd%bd%e4%b8%ad.png\" alt=\"Win11右键菜单正在加载中\" width=\"720\" height=\"937\" loading=\"lazy\" /\u003e\n\u003c/p\u003e\n\u003ch3 id=\"原因分析\"\u003e原因分析\u003c/h3\u003e\n\u003cp\u003eWin11 的新版右键菜单采用了\u003cstrong\u003e二级菜单设计\u003c/strong\u003e（\u0026ldquo;显示更多选项\u0026rdquo;），当系统中安装了过多第三方软件时，这些软件会在右键菜单中注册大量菜单项。由于 Win11 的新菜单需要动态加载这些第三方菜单项，当菜单项过多或某些软件响应较慢时，就会出现\u0026quot;正在加载中\u0026quot;的提示，导致右键菜单响应迟缓，影响使用体验。\u003c/p\u003e","tags":["技术","技术/工具"],"title":"如何解决Win11右键菜单冗余的问题"}]