作者: chentushen

  • 独立游戏-MED!

    “忠诚!Loyalty!”

    欢迎来到这片被战火撕裂、被谎言缝合的大陆。这里没有绝对的正义,只有极权的绞肉机、资本的提款机,以及在体制夹缝中艰难求生的普通人。

    • 我是这款独立游戏《MED》的开发者。今天,我将为您解密这个架空世界的完整版图与历史,带您提前踏入这座冰冷刺骨的“卫生院”。

    🌍 第一部分:战争与残骸(地缘篇


    曾经,大陆的心脏由一头灰色巨兽盘踞——斯科特第一帝国。它拥有西部无尽的煤烟与南部金黄的麦浪。然而,在上一场名为“民主VS君主”的世界大战后,帝国崩塌了。

    如今的大陆,被划分为几股暗流涌动的势力:

    民主阵营(虚伪的胜利者):

    联合群岛:西北海域霸主。他们用海军封锁世界,用金融贷款吸干大陆,是躲在幕后的冷酷金库。

    戈特 / 科特兰:西部的老牌民主国。表面上满口自由,背地里却向极权帝国走私工业母机,大赚黑心钱。

    西施科特(西斯科特):被强行从旧帝国剥离的工业区。似傀儡而非傀儡,是西方用来抵挡东方怒火的“带血防波堤”。

    君主阵营(绝望的复仇者):

    东斯科特(游戏主舞台):旧帝国的残躯。新皇帝利用战败的屈辱煽动民族狂热,建立了极度恐怖的极权统治。

    格雷西亚:东方的庞大巨兽。靠着出卖盟友和战略纵深,在战后奇迹般地保住了大部分领土。

    明里赫:南方的农业王朝。为了保住王室,曾在战争中背叛同盟,割让了最优质的河口城市。

    投机与神权(发死人财的秃鹫):

    麦加斯:北方的君主立宪国。战后东西方唯一的“走私桥梁”,两头下注的白手套。

    最高议会:政教合一的神权国。靠“新月运动”伪装民主,借“人道主义重建”之名,趁火打劫吞并领土。

    🏥 第二部分:欢迎来到药治部(游戏舞台篇)


    在这个宏大的历史背景下,你并非指挥千军万马的将军,也不是高高在上的政客。

    你只是一个抽中“帝国劳动工签”的普通学生,被分配到了东斯科特·帝国第三卫生院·药治部。

    在这里,你将体验到极权体制下最真实的流水线日常:

    药品的谎言:随着帝国颁布《药品安全与净化条例》,高质量的特效药越来越少。权贵用“合理处方单”抽干了救命药,平民的处方上只剩下越来越多的止痛药与镇静剂。帝国的目的很简单——不怕你病死,就怕你疼得叫出声。

    立体的审查:你的工作是“收货-摆货-发货”。但你需要核对违禁药、应付特权阶级的插队、甚至要在后勤官老头的杂物间里,把走私药伪装成垃圾送出去。

    “忠诚”的价码:帝国信用点数决定了你的生死。努力工作、甚至举报同事,能让你换取带冰箱的两居室;一旦信用过低,坏师傅的眼睛就会死死焊在你的后背上。

    🎭 第三部分:这套系统下,没有人是无辜的

    在卫生院里,你会遇到三种前辈:

    好师傅:他耐心教你所有流程,但他的真实身份是地下抵抗组织成员。在第三天,他就会被秘密警察带走。

    坏师傅:冷酷的帝国鹰犬。他随时会抽查你的账本,把你当成潜在的间谍和耗材。

    麻木的职员:他不说话,不反抗,只是默默干活。他是体制彻底异化后的最终形态。

    更有极具张力的联机模式(开发中):
    在这里,合作是奢望,背叛才是常态。你可以和队友合伙走私,也可以在利益分配不均时,偷偷收集对方的违规证据,匿名举报。甚至,当你们面临秘密警察的审讯时,只有最快出卖队友的人,才能拿到晋升的通行证。

    ⚙️ 关于《MED》的开发计划

    这是一款致敬《请出示证件》(Papers, Please)与《监视者》(Beholder)的模拟经营(生成)与道德困境游戏。

    如果你喜欢:
    ✅ 冷峻的极权反乌托邦叙事
    ✅ 令人窒息的官僚模拟与多结局
    ✅ 能够深刻拷问人性的抉择

    那么,请赞助/关注我吧!

    在爱发电的后续更新中,您将获得:

    📁 独家开发日志:游戏美术资产(低多边形药物建模、国家设定集)抢先看。

    🎨 设定集与壁纸:高清的阵营海报与地图解析。

    🎮 内测Demo试玩资格:提前进入卫生院,体验你的第一天工签生活。

    “帝国不怕人病死,就怕人疼得叫出声。而你,是递出那盒药的人。”
    点击【关注/赞助】,让我们一起把这座冰冷窒息的世界构建完整!

  • 圣旗与枯骨

    ——摘自《坦纳伯斯伯爵手记·卷七》

    教皇的圣旨传至坎迪亚时,整个王国都沸腾了。十字军东征——这是通往天堂的阶梯,是获取土地与财富的捷径,更是摆脱一切世俗债务的神圣豁免。

    皇帝召集诸领主,允许各人自行选择加入哪个骑士团,按封地税收排定序位。坦纳伯斯伯爵在旁听席上,看见莱恩纳德的名字赫然列于前三。旁人窃窃私语:“边陲小镇竟能比侯爵领还富,此人若非善治,便是善于搜刮。”

    但坦纳伯斯知道真相。莱恩纳德从不中饱私囊,每一枚铜板都如实入账,甚至连城中粪便清运的费用,他都是自掏腰包垫付的。税收账册上那些数字,干净得像他书房里的地板。

    所有人以为莱恩纳德会选圣殿骑士团——那里有帝国的金库撑腰,有最肥美的战利品分配。或是条顿骑士团——那里有最广袤的北方封地可供圈占。

    他选了医院骑士团。

    原因简单得可笑:医院骑士团的招募官,是他学院时代关系不错的老师,一位教过《治术要义》的老学者。莱恩纳德念着这份师生之谊,又想着医院骑士团虽不如其他骑士团风光,但至少安稳,或许还能在军旅间隙,钻研一下异域治理之术。

    临行前,老师单独找他谈了话。

    “莱恩纳德,你听我一句。”老学者的声音很低,“医院骑士团在后方战线,无法将那些‘本属于自己’的异教徒财产纳为所有——我们没有掠夺权。而且,一切装备、马匹、药品,皆需自备。”

    莱恩纳德愣了一下。

    “还有,”老师叹了口气,“你来了也好。我老了,身边没几个熟人。你若来,咱们也好有个照应,我……我或许能让你轻松些。”

    莱恩纳德点头应允。他想着,有老师关照,总不至于太差。

    他错了。

    医院骑士团的处境,远比老师透露的更为难堪。老师本人不过是骑士团中一名籍籍无名的招募官,受团长之命四处奔走,却因性格耿直,不懂谄媚,根本说不上话。而正是因为老师的“劝退”——他那番真诚的警告——让许多领主望而却步,医院骑士团招募到的人数少得可怜。

    可他们要面对的,是成百上千的伤员。

    前线的伤员如潮水般涌来,帐篷不够,床位不够,绷带不够,连药剂都捉襟见肘。莱恩纳德从天亮忙到天黑,从轻伤包扎到截肢手术,从搬运伤员到清点药品。他带来的积蓄,那些原本准备用于领地建设的金币,一枚一枚地流向了伤兵营的采购。

    他原想空闲时钻研异域治理之术。可这里没有空闲。连安息日都没有。

    某个周日清晨,莱恩纳德拖着疲惫的身躯向团长请求:“大人,今日安息日,可否容我稍歇半日?”

    团长头也没抬:“主说,当爱人如己。这里躺着的都是你的兄弟。你休息,他们便死。”

    莱恩纳德攥紧拳头。他想起教堂里那些关于仁爱与怜悯的教诲,想起那些在阳光中朗诵经文的日子。他几乎想脱口而出:你拿主的教诲当枷锁,你才是异端。

    但他不敢。

    他只是默默转身,继续去换药。

    坦纳伯斯伯爵后来偶然得到莱恩纳德寄回家臣的一封信。信上字迹潦草,墨痕凌乱,边角有可疑的水渍:

    “……内子勿念。此间尚好,唯近日伤患甚多,昼夜不得歇。昨见某伯爵领骑士抢得异教商队,金银满载,归途高歌。其治术远不如我,其封地远不如我,唯其贪婪远胜于我。”

    “我累。我替人包扎、替人清运、替人处理一切无人愿做之事。我带来之金已尽数用于购置绷带药剂,甚至挪用了郡下本该上缴的贡金。我知道这是失职,可我不能眼睁睁看着他们流血而死。”

    “有时我想,我在郡下是领主,在这里是杂役。我治理一个郡下的能力,在这里只够换得替团长跑腿的差事。”

    “愿主宽恕我。我大概不该来的。”

    信到此戛然而止,没有落款日期。

    坦纳伯斯将信折好,放回那叠文件中。他没有告诉任何人。

    他只是在笔记末尾,用极小的字迹写了一句:

    (坦纳伯斯伯爵的结语)

    沼泽女巫在熬煮草药时说:最擅长救人的人,往往最先被榨干。因为他无法像那些掠夺财富的人一样,在别人的痛苦面前转过身去。医院骑士团的悲剧不在于缺人,而在于最能干的那个人恰恰无法拒绝。他的能力成了他的刑具,他的善良成了他的镣铐。那些满载而归的伯爵们,会在庆功宴上高谈主的恩典。而莱恩纳德,他连安息日都被剥夺了,却依然在帐篷里替主擦洗伤口。愿主真的知道——究竟是谁在替祂流血。

    坦纳伯斯搁笔于此。他望向窗外,秋雨绵绵。他不知莱恩纳德是否还活着,是否还在那个永远睡不够的伤兵营里,替人擦去污血,然后被遗忘。他只是默默地,将那份信件的抄本,归入了一个标注着“未竟之事”的匣子。

    愿他平安。

    To be without some of the things you want is an indispensable part of happiness.

    没有一些你想要的东西是幸福不可或缺的一部分。

    —— 罗素

  • 个人开发者如何获得小米上岛

    夺舍 媒体通知

    夺舍媒体通知:

    让生活规划 App 白嫖 HyperOS 锁屏通知 + 灵动岛 + 大视图

    场景:你在开发一个时间块规划 App,前台服务跑着进度通知。HyperOS(小米澎湃OS)上,通知要么被折叠成”更多通知”(用户看不到),要么缩成一行挤在状态栏(丑且没信息量),锁屏上更是干干净净什么也没有。开发者账户没有,灵动岛 API 不公开。怎么办?

    答案是:夺舍媒体通知。

    1. 问题全景

    • 锁屏通知不显示 — HyperOS 限制了普通通知出现在锁屏上的类型,除非用户在系统设置里手动开。
    • “更多通知”折叠 — 前台服务的进度通知被 HyperOS 自动归到 Aggregate Section,收成一个”更多通知”折叠项,用户必须点两下才能看到进度条。
    • 通知高度不够 — 标准通知只能显示标题 + 一行文字 + 小进度条,事件名称、已用时间、剩余时间、下一任务全挤不下。
    • 灵动岛需要开发者账户 — 小米的灵动岛(Capsule)API 需要开发者资质,没账户连文档都看不了。

    这四个问题,最终用一个 Android 标准 API 全解决了——Notification.MediaStyle。

    2. 为什么是 MediaStyle

    翻小米澎湃OS开发者文档时看到 MIUI10 媒体通知适配说明,里面有几句话亮了:

    正在播放的媒体通知默认置顶 + 默认展开为大视图。

    正在播放的媒体通知默认会出现在锁屏上(置顶+大视图)。

    调用系统的媒体通知,系统就能做针对性的优化……

    也就是说,只要 HyperOS 认为你的通知是一个”媒体通知”,它就自动给你:

    • ✅ 锁屏上置顶展开显示
    • ✅ 通知栏里大视图(够高、能放更多信息)
    • ✅ 灵动岛胶囊(HyperOS 对媒体通知自动展示)
    • ✅ 不会被折叠进”更多通知”

    关键是:不需要开发者账户,不需要小米私有 API。这是 Android 5.0 就有的标准 API —— Notification.MediaStyle。

    3. “夺舍”方案

    我们并不播放媒体。但我们可以创建一个假的 MediaSession,设为”播放中”状态,然后把事件进度伪装成播放进度。 HyperOS 看到播放中的媒体通知,就会自动展开、置顶、锁屏显示、弹出灵动岛。

    3.1 创建假 MediaSession

    object PlannerMediaSession {
        private var session: MediaSession? = null
    
        val token: MediaSession.Token? get() = session?.sessionToken
    
        fun start(ctx: Context) {
            val s = MediaSession(ctx, "ld_planner")
            s.setPlaybackState(
                PlaybackState.Builder()
                    .setState(PlaybackState.STATE_PLAYING, 0, 1.0f)
                    .build()
            )
            s.isActive = true
            session = s
        }
    
        // 核心:用播放进度模拟事件进度,seekbar 自然变成进度条
        fun updateProgress(currentSec: Int, totalSec: Int) {
            val s = session ?: return
            val curMs = (currentSec.coerceAtLeast(0) * 1000).toLong()
            val durMs = (totalSec.coerceAtLeast(1) * 1000).toLong()
            s.setPlaybackState(
                PlaybackState.Builder()
                    .setState(PlaybackState.STATE_PLAYING, curMs, 1.0f)
                    .setBufferedPosition(durMs) // 缓冲条 → 总时长
                    .build()
            )
            s.setMetadata(
                MediaMetadata.Builder()
                    .putLong(MediaMetadata.METADATA_KEY_DURATION, durMs)
                    .build()
            )
        }
    }
    Kotlin

    三个关键点:

    • STATE_PLAYING — 告诉 HyperOS”正在播放”,触发锁屏展开 + 灵动岛
    • setPosition(curMs) — 当前进度(毫秒),驱动 seekbar 位置
    • METADATA_KEY_DURATION — 总时长(毫秒),驱动 seekbar 最大值
    • setBufferedPosition(durMs) — 把”缓冲位置”设为总时长,seekbar 上的灰色缓冲区变成进度条的背景

    3.2 构建 MediaStyle 通知

    注意要用原生 Notification.Builder 而非 NotificationCompat.Builder——后者不接受 Notification.MediaStyle。

    val mediaStyle = Notification.MediaStyle()
        .setShowActionsInCompactView(0, 1, 2)     // 折叠时显示哪几个按钮
        .setMediaSession(PlannerMediaSession.token) // 绑定假媒体会话
    
    val notif = Notification.Builder(context, channelId)
        .setSmallIcon(R.drawable.ic_notification_progress)
        .setLargeIcon(largeIcon)                    // 媒体通知左侧大图
        .setContentTitle("测试事件")
        .setContentText("1h 23m / 2h  ·  52%  ·  Ends 10:00")
        .setStyle(mediaStyle)                        // 关键:MediaStyle
        .setColor(accent)                            // 没有开发者账户,setColor 在 MIUI 上也能生效
        .addAction(/* Open */)
        .addAction(/* Next task name */)
        .addAction(/* Done */)
        .setVisibility(Notification.VISIBILITY_PUBLIC)
        .setOngoing(true)
        .build()
    Kotlin

    3.3 在前台服务里更新进度

    // PlannerForegroundService 的 progress loop 里
    while (isActive) {
        delay(5_000)  // 5 秒刷新一次
        val content = activeBlock.toProgressContent()
        val notif = builder.build(content, ProgressSilentUpdate)
        NotificationManagerCompat.from(this).notify(PROGRESS_ID, notif)
        
        // 同步更新媒体通知 seekbar
        PlannerMediaSession.updateProgress(content.elapsedSeconds, content.progressMax)
    }
    Kotlin

    这样每次通知刷新时,MediaSession 的播放位置也跟着更新。HyperOS 看到播放位置在变,就持续保持锁屏展开 + 灵动岛显示。

    4. 实际效果

    场景效果
    锁屏通知自动出现在锁屏最上方,展开显示事件名称、已用/总时长、进度条、下一任务
    通知栏大视图(MediaStyle),不会被折叠成”更多通知”,底部有 3 个操作按钮
    灵动岛HyperOS 自动在状态栏/屏幕顶部弹出胶囊,显示事件名称和进度
    进度条媒体通知原生 seekbar 实时走事件进度,灰色缓冲条代表总时长

    5. 为什么这不算 hack

    1. 用的是 Android 标准 API — Notification.MediaStyle 从 API 21 就存在,所有 Android 手机都支持,只不过 HyperOS 做了更好的适配。
    2. MediaSession 本来就可以”静默”播放 — 没有规定说 STATE_PLAYING 必须对应真实音频流。倒计时、进度条、番茄钟……天生适合这种模式。
    3. 小米文档鼓励用媒体通知 — 澎湃OS开发文档专门有一章讲媒体通知适配,核心观点就是”用系统媒体通知,系统帮你优化”。

    6. 注意事项

    • 必须用原生 Notification.Builder 而不是 NotificationCompat.Builder,因为后者不接收 Notification.MediaStyle。
    • 目标设备 minSdk 至少 26(Android 8),因为需要通知渠道。API 21-25 需额外处理。
    • 锁屏通知需要渠道 importance 设为 IMPORTANCE_HIGH,但不设 sound(setSound(null))就不会打扰用户。
    • 如果没有真实媒体回话,用完记得 session.release() 避免泄漏。
    • 不要用自定义 RemoteViews 布局—— HyperOS 对自定义布局的通知可能折叠。

    7. 总结

    一行 .setStyle(Notification.MediaStyle()),加上一个假的播放中 MediaSession,换来了:锁屏通知、大视图、灵动岛胶囊、内嵌进度条——四个特性零 API 开销。

    这招的适用范围远不止生活规划类 App:

    • 🍅 番茄钟 — 进度 = 剩余时间,动作 = 暂停/跳过
    • 🏃 运动计时 — 进度 = 已跑距离/时间
    • 📦 文件下载 — 进度 = 已下载百分比
    • 🚗 导航类 — 进度 = 已行驶/剩余路程
    • ⏰ 倒计时器 — 进度 = 已过时间

    本质上,任何需要一个”持续可见的进度通知”的场景,都可以套这个模板。

    需求是锁屏通知 → 想到媒体通知 → 发现不需要开发者账户 → 创建假 MediaSession → 绑上进度。

    这叫”夺舍”。

    // 全文核心就三行
    val mediaStyle = Notification.MediaStyle().setMediaSession(fakeToken)
    val notif = Notification.Builder(ctx, channel).setStyle(mediaStyle)...
    PlannerMediaSession.updateProgress(elapsed, total)
    Kotlin

    缺点:

    会被其他音乐播放器顶掉…


    2026-06-27 · LifeDrive 开发笔记 · 基于 HyperOS 2.0 / REDMI K70 实测

  • ComfyUI-SEEDVR2

    ComfyUI-SEEDVR2

    功能:修复视频像素

    “一句有哲理的话”

    跑了一下午,40min才能修1s 修了跟没修差不多…
    可能是我的电脑显卡还是太垃圾了

    于千万人之中遇见你所要遇见的人,于千万年之中,时间的无涯的荒野里,没有早一步,也没有晚一步,刚巧赶上了。

    Among thousands of people, you meet those you’ve met. Through thousands of years, in the wilderness of time, you happen to meet them, neither earlier nor a bit too late.

    —— 《爱》张爱玲

  • 诺言与秽物

    ——摘自《坦纳伯斯伯爵手记·卷六》

    莱恩纳德伯爵有一桩旁人难以理解的苦处——他有洁癖。

    虽不严重,却也足以让他对城中日益堆积的粪便问题寝食难安。按帝国律法,封地内的污物清理由领主责成下属官吏分管。莱恩纳德早已将此事明确划归几位行政官:昂格林负责东城,斯拉格负责西城,康德曼则总领协调。

    然而数月过去,城中粪便未见减少。

    并非几位行政官无能。昂格林与斯拉格近日痴迷于王都新近风行的“无畏”骑士角斗——两位铁甲骑士在圈中持钝器互搏,直至一方倒地。两人日日研究骑士的胜负赔率,将俸禄大半押在赌盘上。至于城中粪便,“不过是些秽物,迟一日早一日又有何妨?”

    而康德曼则另有一番本事。

    每逢莱恩纳德问起,康德曼总是满脸诚恳:“大人放心,属下已在安排。近日正与清运行会商谈,不日便有进展。”他说得如此笃定,如此流畅,仿佛真有一份详细的方案藏在他胸中。可出了议事厅,他便将此事抛诸脑后,继续研究下一场角斗的赔率。

    坦纳伯斯伯爵曾私下听闻,康德曼年轻时曾游历南方诸城邦,习得一种“政客之术”——用最动听的承诺换取最廉价的信任,至于承诺能否兑现,那便是另一回事了。

    起初,莱恩纳德尚能容忍。

    他自掏腰包,雇佣城中闲汉清运秽物。他有洁癖,无法忍受污秽满城,权当是为自己的安宁付账。可日复一日,月复一月,他的积蓄渐渐吃紧,而几位行政官依旧无动于衷。

    “我总不能替他们做一辈子。”莱恩纳德终于下了决心,他要看看,若自己不再插手,这些人究竟会不会动。

    于是他闭门不出,将自己锁在城堡的书房里,埋头批阅那些永远处理不完的文书——粮赋账册、边境巡逻报告、商队通行许可。他试图相信,几位行政官再不济,也不至于让整座城池淹没在粪便之中。

    然而命运偏要嘲弄他的信任。

    数周后,莱恩纳德染了风寒。头重脚轻之际,他想出门透一透气。城堡的大门缓缓打开,他深吸一口气——

    几乎窒息。

    那股恶臭扑面而来,浓烈得仿佛有形。他定睛看去,街巷之中,马粪、牛粪、狗粪、乃至人的排泄物,混杂着烂菜叶和污水,铺满了石板路。苍蝇成群,野狗在秽物中翻找残食。行人掩鼻疾走,孩童光着脚踩过泥泞——那泥泞的颜色令人作呕。

    莱恩纳德站在门口,久久未动。

    他去了东城,昂格林正与几个商贾热烈讨论下一场角斗的胜率,桌上摊着一幅画着两位骑士的羊皮纸。

    “昂格林,城中的粪便你打算何时处理?”

    “大人稍候,待我算完这场赔率……”

    莱恩纳德转身去了西城。斯拉格不在岗哨,旁人说他去酒馆与人兑换赌赢的金币了。

    最后他找到了康德曼。康德曼正端坐在自己的办公桌前,面前摊着一份空白的羊皮纸,笔搁在一旁,墨迹已干。

    “康德曼,你总说在安排。”

    “大人,确实在安排。只是清运行会最近人手紧缺……”

    莱恩纳德盯着他的眼睛看了很久。

    康德曼的目光坦然而诚恳,没有一丝闪躲——这才是最可怕的。他不是在撒谎,他只是在表演一种自己都信以为真的“正在处理”。

    莱恩纳德没有再说什么。

    他回到城堡,换了一身旧衣,从工具房取出一把铁锹。

    百姓们惊讶地看见,他们的领主——那位向来衣着整洁、连书案都要擦拭三遍的莱恩纳德伯爵——正弯着腰,一锹一锹地将街头的粪便铲入推车。他的鼻子塞着布条,额头上沁出细汗,不时咳嗽几声,显然风寒未愈。

    渐渐地,有几个老妇拎着桶出来了。接着是铁匠铺的学徒,然后是屠户,然后是酒馆的伙计。

    没有人说话。

    日落时分,主街终于露出了石板的本来面目。

    莱恩纳德直起腰,将铁锹靠在墙边,慢慢走回城堡。他的旧衣上沾满了污渍,他却没有像往常那样急着换洗。

    他只是坐在台阶上,望着渐暗的天色,一言不发。

    坦纳伯斯伯爵后来问及此事,莱恩纳德淡淡道:“我原想看看,没有我,他们能不能做成事。结果证明,他们确实不能。而我也不能眼睁睁看着自己的城淹在粪水里。”

    “所以你认了?”

    “我认了。”他站起身,拍了拍衣袍上并不存在的灰尘,“只是从今往后,我再不会对康德曼的‘正在安排’抱任何期待。他的诺言,比街上的粪便还不值钱——至少粪便还能肥田。”

    (坦纳伯斯伯爵的结语)

    女巫在搅拌一锅沸腾的粪水时曾说:世间有三种人最令人生厌——第一种是制造污秽却浑然不觉的人,第二种是眼见污秽却忙于赌斗的人,第三种则是用最动听的承诺把污秽掩盖起来、让你以为已经有人去清理的人。莱恩纳德错在何处?他错在相信了一件事——即那些坐在办公室里的人,会在意他坐在办公室里在意的事。他们不在意的。他们只在意角斗场上谁赢谁输,以及下一次该用什么漂亮话搪塞过去。而那个最厌恶污秽的人,最终注定要亲手铲除最多的污秽。这便是洁癖者的宿命:因为无法忍受,所以不得不做。

  • ESP8266电子时钟

    ESP8266电子时钟

    功能:自定义API访问
    显示天气
    显示时间

    材料
    • 一块大小不符合的面包板
    • NodeMCU ESP-12E(ESP8266 WiFi 开发板)
    • 0.96 寸 I2C 接口 SSD1306 OLED 显示屏
    • 有源蜂鸣器
    • 几根杜邦线
    arduino 代码
    #include <U8g2lib.h>
    #include <Wire.h>
    #include <ESP8266WiFi.h>
    #include <ESP8266HTTPClient.h>
    #include <ArduinoJson.h>
    
    // ==================== OLED配置 ====================
    U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 5, /* data=*/ 4);
    // ==================== 蜂鸣器配置 ====================
    #define BUZZER_PIN 0  // D3 (GPIO0)
    
    
    // ==================== WiFi配置 ====================
    const char* ssid = "N/A";
    const char* password = "N/A";
    
    // ==================== API配置 ====================
    const char* timeUrl = "N/A";
    const char* serverUrl = "N/A";
    
    // 心知天气配置(免费注册:https://www.seniverse.com/)
    const char* xinzhiKey = "N/A";
    const char* city = "N/A";
    const char* weatherUrl = "https://api.seniverse.com/v3/weather/now.json";
    
    WiFiClientSecure client;
    
    // ==================== 全局变量 ====================
    int currentHour = 0;
    int currentMinute = 0;
    int currentSecond = 0;
    int currentWeekday = 0;
    String currentDateFormatted = "";
    
    // 天气
    String weatherText = "";
    String weatherTemp = "";
    
    // 通知
    String notifications[30];
    int notificationCount = 0;
    int currentNotificationIndex = 0;
    
    // 定时
    unsigned long lastTimeUpdate = 0;
    unsigned long lastWeatherUpdate = 0;
    unsigned long lastDataUpdate = 0;
    unsigned long lastModeSwitch = 0;
    
    int displayMode = 0;  // 0:时间界面, 1:通知界面
    bool notificationJustShown = false;
    
    // ==================== 辅助函数 ====================
    String getWeekdayCN(int w) {
      String weekdays[] = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
      if (w >= 0 && w <= 6) return weekdays[w];
      return "周一";
    }
    
    String getWeatherCN(String weather) {
      if (weather.indexOf("Clear") >= 0) return "晴";
      if (weather.indexOf("Cloud") >= 0) return "多云";
      if (weather.indexOf("Overcast") >= 0) return "阴";
      if (weather.indexOf("Light Rain") >= 0) return "小雨";
      if (weather.indexOf("Moderate Rain") >= 0) return "中雨";
      if (weather.indexOf("Heavy Rain") >= 0) return "大雨";
      if (weather.indexOf("Rain") >= 0) return "雨";
      if (weather.indexOf("Snow") >= 0) return "雪";
      if (weather.indexOf("Fog") >= 0) return "雾";
      return weather;
    }
    
    void beepLight() {
      digitalWrite(BUZZER_PIN, LOW);
      delay(80);
      digitalWrite(BUZZER_PIN, HIGH);
    }
    
    // ==================== 获取数据 ====================
    void updateTime() {
      if (WiFi.status() != WL_CONNECTED) return;
      
      HTTPClient https;
      client.setInsecure();
      https.setTimeout(5000);
      
      if (!https.begin(client, timeUrl)) return;
      
      int httpCode = https.GET();
      if (httpCode == HTTP_CODE_OK) {
        String payload = https.getString();
        
        DynamicJsonDocument doc(512);
        deserializeJson(doc, payload);
        
        currentHour = doc["hour"];
        currentMinute = doc["minute"];
        currentWeekday = doc["weekday"];
        
        String timeStr = doc["time"].as<String>();
        if (timeStr.length() >= 19) {
          currentSecond = timeStr.substring(17, 19).toInt();
        }
        
        String dateStr = doc["date"].as<String>();
        if (dateStr.length() >= 10) {
          String month = dateStr.substring(5, 7);
          String day = dateStr.substring(8, 10);
          currentDateFormatted = month + "月" + day + "日";
        }
      }
      https.end();
    }
    
    void updateWeather() {
      if (WiFi.status() != WL_CONNECTED) return;
      if (String(xinzhiKey).length() == 0) return;
      
      String url = String(weatherUrl) + "?key=" + xinzhiKey + "&location=" + city + "&language=en&unit=c";
      
      HTTPClient https;
      client.setInsecure();
      https.setTimeout(5000);
      
      if (!https.begin(client, url)) return;
      
      int httpCode = https.GET();
      if (httpCode == HTTP_CODE_OK) {
        String payload = https.getString();
        
        DynamicJsonDocument doc(1024);
        deserializeJson(doc, payload);
        
        if (doc.containsKey("results")) {
          JsonObject now = doc["results"][0]["now"];
          weatherText = now["text"].as<String>();
          float temp = now["temperature"];
          weatherTemp = String(temp, 0);
        }
      }
      https.end();
    }
    
    void fetchNotifications() {
      if (WiFi.status() != WL_CONNECTED) return;
      
      HTTPClient https;
      client.setInsecure();
      https.setTimeout(10000);
      
      if (!https.begin(client, serverUrl)) return;
      
      int httpCode = https.GET();
      if (httpCode == HTTP_CODE_OK) {
        String payload = https.getString();
        
        DynamicJsonDocument doc(4096);
        deserializeJson(doc, payload);
        
        if (doc["status"] == "success") {
          notificationCount = 0;
          JsonArray notificationsArr = doc["notifications"];
          for (JsonObject n : notificationsArr) {
            if (notificationCount < 30) {
              notifications[notificationCount] = n["content"].as<String>();
              notificationCount++;
            }
          }
        }
      }
      https.end();
    }
    
    // ==================== 手表界面 ====================
    void displayWatchFace() {
      u8g2.firstPage();
      do {
        // ========== 顶部区域 ==========
        u8g2.setFont(u8g2_font_wqy12_t_chinese3);
        u8g2.drawHLine(0, 15, 128);  // 顶部分割线
        
        // 日期(左上角)
        u8g2.setCursor(5, 12);
        if (currentDateFormatted.length() > 0) {
          u8g2.print(currentDateFormatted);
        } else {
          u8g2.print("03月24日");
        }
        
        // 星期(右上角)
        u8g2.setCursor(95, 12);
        u8g2.print(getWeekdayCN(currentWeekday));
        
        // ========== 中间时间区域 ==========
        // 时间往下移(从y=42移到y=48)
        u8g2.setFont(u8g2_font_logisoso24_tf);
        u8g2.setCursor(25, 48);
        char timeBuf[6];
        sprintf(timeBuf, "%02d:%02d", currentHour, currentMinute);
        u8g2.print(timeBuf);
        
        // 秒数(放在时间右侧)
        u8g2.setFont(u8g2_font_helvB08_tf);
        u8g2.setCursor(105, 38);
        char secBuf[3];
        sprintf(secBuf, "%02d", currentSecond);
        u8g2.print(secBuf);
        
        // ========== 底部区域 ==========
        
        // 底部文字(放在线下方,y=63)
        u8g2.setCursor(10, 63);
        if (weatherText.length() > 0 && weatherTemp.length() > 0) {
          u8g2.print(getWeatherCN(weatherText));
          u8g2.print(" ");
          u8g2.print(weatherTemp);
          u8g2.print("°C");
        } else if (String(xinzhiKey).length() > 0) {
          u8g2.print("天气加载中");
        } else {
          u8g2.print("WiFi:");
          u8g2.print(WiFi.RSSI());
          u8g2.print("dBm");
        }
        
        // 通知数量(右侧)
        if (notificationCount > 0) {
          u8g2.setCursor(100, 63);
          u8g2.print("[");
          u8g2.print(notificationCount);
          u8g2.print("]");
        }
        
      } while (u8g2.nextPage());
    }
    
    // ==================== 通知界面 ====================
    void displayNotification() {
      u8g2.firstPage();
      do {
        u8g2.setFont(u8g2_font_wqy12_t_chinese3);
        
        u8g2.drawHLine(0, 15, 128);
        u8g2.setCursor(45, 12);
        u8g2.print("通 知");
        u8g2.drawHLine(0, 22, 128);
        
        if (notificationCount > 0 && currentNotificationIndex < notificationCount) {
          String content = notifications[currentNotificationIndex];
          
          int lineHeight = 12;
          int startPos = 0;
          int lines = 0;
          
          while (startPos < content.length() && lines < 3) {
            int endPos = startPos + 18;
            if (endPos > content.length()) endPos = content.length();
            
            u8g2.setCursor(5, 32 + lines * lineHeight);
            u8g2.print(content.substring(startPos, endPos));
            
            startPos = endPos;
            lines++;
          }
          
          u8g2.setCursor(100, 63);
          u8g2.print(currentNotificationIndex + 1);
          u8g2.print("/");
          u8g2.print(notificationCount);
          
        } else {
          u8g2.setCursor(35, 40);
          u8g2.print("暂无通知");
        }
        
        
      } while (u8g2.nextPage());
    }
    
    // ==================== 初始化 ====================
    void setup() {
      Serial.begin(115200);
      delay(100);
      
      pinMode(BUZZER_PIN, OUTPUT);
      digitalWrite(BUZZER_PIN, HIGH);
      
      u8g2.begin();
      u8g2.enableUTF8Print();
      u8g2.setFont(u8g2_font_wqy12_t_chinese3);
      
      u8g2.firstPage();
      do {
        u8g2.setCursor(35, 30);
        u8g2.print("连接WiFi");
      } while (u8g2.nextPage());
      
      WiFi.begin(ssid, password);
      int attempts = 0;
      while (WiFi.status() != WL_CONNECTED && attempts < 25) {
        delay(500);
        Serial.print(".");
        attempts++;
      }
      
      if (WiFi.status() == WL_CONNECTED) {
        Serial.println("\nWiFi已连接");
        u8g2.firstPage();
        do {
          u8g2.setCursor(40, 30);
          u8g2.print("WiFi已连");
        } while (u8g2.nextPage());
        delay(1000);
      }
      
      client.setInsecure();
      
      updateTime();
      updateWeather();
      fetchNotifications();
      
      beepLight();
    }
    
    // ==================== 主循环 ====================
    void loop() {
      unsigned long now = millis();
      
      if (now - lastTimeUpdate >= 1000) {
        updateTime();
        lastTimeUpdate = now;
      }
      
      if (now - lastWeatherUpdate >= 300000) {
        updateWeather();
        lastWeatherUpdate = now;
      }
      
      // 每15分钟检查通知
      if (now - lastDataUpdate >= 900000) {
        fetchNotifications();
        lastDataUpdate = now;
        
        if (notificationCount > 0) {
          displayMode = 1;
          lastModeSwitch = now;
          currentNotificationIndex = 0;
          notificationJustShown = true;
          beepLight();
        }
      }
      
      // 通知界面显示10秒后切回
      if (displayMode == 1 && notificationJustShown) {
        if (now - lastModeSwitch >= 10000) {
          displayMode = 0;
          notificationJustShown = false;
          lastModeSwitch = now;
        }
      }
      
      // 通知界面自动翻页
      if (displayMode == 1 && notificationCount > 0 && notificationJustShown) {
        static unsigned long lastNotiSwitch = 0;
        if (now - lastNotiSwitch >= 3000) {
          currentNotificationIndex = (currentNotificationIndex + 1) % notificationCount;
          lastNotiSwitch = now;
        }
      }
      
      if (displayMode == 0) {
        displayWatchFace();
      } else {
        displayNotification();
      }
      
      delay(50);
    }
    C++

    “记住他人名字带给他人被记住的感觉是这个时代所稀缺的,因为效率至上的时代,每个人都忽视了彼此包括自己”

    –

    “Making someone feel remembered just by knowing their name—that’s something rare in today’s world. In an era that prioritizes efficiency, people often neglect others, and even themselves.“

    It’s a funny thing about life; if you refuse to accept anything but the best, you very often get it.

    生活的讽刺之处在于:如果你只接受最好的,你经常会得到最好的。

    —— 《刀锋》威廉·萨默塞特·毛姆

  • 旧甲与无路之途

    ——摘自《坦纳伯斯伯爵手记·卷五》

    坦纳伯斯伯爵途经边陲时,曾在一间小酒馆里,听见邻桌的商人低声议论:“听说了吗?莱恩纳德伯爵家出事了。”

    他放下酒杯,侧耳倾听。

    莱恩纳德家族的起家,在边地并非秘密。老莱恩纳德并非生而显贵,年轻时不过是戍边军团的一名普通甲士。某次蛮族夜袭,他独守隘口至援军抵达,战后先帝感其勇,赐了一小块边陲封地——便是如今的莱恩纳德郡下。

    老莱恩纳德卸甲归田后,始终忘不了那些戍边的岁月。他将那套随他出生入死的旧甲胄偷偷藏在谷仓深处,每年擦拭一回,仿佛这样就能留住自己曾经的身份。

    如今老莱恩纳德年事已高,思乡之情日甚。他想回到幼年居住的怡人之滨,在故土终老。临行前,他舍不得那套旧甲,便将其装入箱中,随车队一同带走。

    途经王都检查站时,守兵打开了那口箱子。

    甲胄在阳光下泛着冷光。按帝国律法,私藏制式甲胄者,以谋逆论处。

    消息传到王都时,昔日的先帝早已驾崩。如今的皇帝坐在金殿上听完奏报,只淡淡问了句:“此人如今任何官职?”

    “回陛下,一介边陲老卒,已无军职。”

    皇帝便不再多问。他没有兴趣为一个没有用处的小人物翻旧账,也没有兴趣展现仁慈。重罚便是了。

    判决很快下达:老莱恩纳德罚没半数家产,本人监禁三年。其子孙三代不得入仕,不得担任任何公职,不得参与帝国任何层级的人才选拔。

    三代不得触及权力核心。

    判决书上甚至附了一笔——有人曾提议将莱恩纳德郡下收回王室,但经吏员核查,那片封地“过于偏远贫瘠,年贡不足修缮王都一段城墙”,便作罢了。

    消息传到莱恩纳德伯爵耳中时,他正在书案前批阅秋收账册。

    他沉默了许久,然后继续批阅。

    但坦纳伯斯伯爵后来听说,那几天夜里,城堡的书房灯火彻夜未熄。管家送进去的晚餐,常常原样端出来。

    其实莱恩纳德早有经商之意。他秉公廉洁多年,未曾借职权敛过一枚铜板,积蓄寥寥。他也曾试着做几回买卖——贩过毛皮,倒过铁器,甚至动过酿酒的心思——但每每浅尝辄止,多以亏损收尾。他骨子里终究是个务实的人,对商贾之事既无天赋,也无热忱,只是觉得或许该为郡下多寻一条出路。

    如今这判决落下,他未来的路,又少了一条。

    他本就在犹豫:郡下的未来,是该倾力发展商贸,还是该广纳贤才,兴办学堂?前者见效快但根基不稳,后者见效慢却利在长远。他为此辗转了无数个夜晚,始终未能决断。

    如今倒好,不必决断了。

    三代不得入仕,不得参与选拔。他的子孙,他的郡下子弟,即便再有才华,也触摸不到帝国权力的门槛。兴办学堂、培养人才,又有什么意义呢?

    而商贸之路——他自己都做不成的买卖,又如何指望郡下能靠它繁荣?

    某个黄昏,坦纳伯斯伯爵在城墙上找到了莱恩纳德。他独自站在那里,望着西沉的日头,面色平静,只是眉心拧着一道深深的纹路。

    “你可还好?”坦纳伯斯问。

    莱恩纳德沉默片刻,缓缓开口:“我父亲那套甲胄,其实早已锈蚀。他留着它,不过是想记住自己曾经是谁。”

    他顿了顿,又说:“先帝赐他封地时,说这是‘酬忠义之士’。如今新帝罚他三代,也是依律而行。我怨不得谁。”

    “只是……”他的声音低了下去,“我勤勤恳恳治理这片土地,从未懈怠一日。我清廉自守,不取分毫不义之财。我以为只要把郡下治理好,便算对得起先帝的恩赐,对得起父亲留下的这份家业。”

    “可现在我才明白——在权力中心的眼里,我和我的郡下,不过是一片‘过于偏远贫瘠、不值得收回’的地方。”

    他苦笑了一下。

    “连被剥夺的资格,都是因为太不值钱。”

    坦纳伯斯没有说话。

    风吹过城墙,带着秋末的凉意。

    良久,莱恩纳德直起身,整了整衣襟,朝城墙下走去。

    “但郡下还是需要治理的,不是吗?”他在经过坦纳伯斯身边时,说了这么一句,便头也不回地走了。

    坦纳伯斯站在原地,看着他的背影消失在暮色里。

    那背影依旧挺直,只是脚步比来时沉重了些。

    (坦纳伯斯伯爵的结语)

    沼泽女巫在翻看旧羊皮卷时曾说:忠诚是一种极其脆弱的货币,它的价值完全取决于发行它的人是否还在位。先帝用它换来了一块封地,新帝却连兑换的机会都不再给予。最荒谬的莫过于此——那套甲胄从未伤人,它只是提醒了一位老者他曾是谁。而帝国惩罚他的,恰恰是他曾经忠心的证明。至于莱恩纳德……他如今才知,勤恳和廉洁,在权力的账簿上,从不被记作资产。

  • 未射出的箭与迟来的靶

    ——摘自《坦纳伯斯伯爵手记·卷四》

    据传,莱恩纳德伯爵年少时,曾在王立治术学堂修习。彼时他一心钻研法典、粮秣与城防,视同窗间的宴饮嬉游为无用之物,独来独往,如一头不合群的幼狼。

    直到一个名叫奎因桑的女子出现在他的世界里。

    她是友人之友,初时不过是巡猎途中偶然同行的身影。但古怪之人自有古怪之人才能辨认的磁场——莱恩纳德发现,她同样不善言辞,同样会在旁人谈笑时走神去看天边的云,同样对猎犬的耳朵比对人脸更感兴趣。

    他们开始结伴巡猎。

    那些日子里,莱恩纳德第一次觉得,清晨的露水是有温度的,林间的风声是有语言的。他学会了辨认她箭囊上那根歪斜的羽毛,她记住了他整理马鬃时那种近乎偏执的认真。他们可以在沉默中共度整个下午,谁也不觉得尴尬。

    他没有说。

    他有一千个理由:学业未成,领地未继,前途未卜。他告诉自己,真正的爱意应当等到配得上她的那一天。于是那支箭始终搭在弦上,引而不发。

    毕业那日,她朝他挥了挥手,转身消失在王都的街道里。他没有追。

    此后的年月,莱恩纳德伯爵果然将封地治理得井井有条。只是每当巡猎经过那片旧林,他总会在某个树桩前勒马片刻——那是她曾经坐过的地方。他暗自发愿:待领地再无饥馑,待城墙再无裂缝,待所有麻烦都平息,他便去找她。

    然而领地如活物,旧的沟渠填平,新的税案便来;春荒刚过,夏汛又至。他永远在“还差一点”的路上。

    直到某个秋日午后,他在边境集市处理牲畜贸易纠纷时,听见两个皮毛商贩的闲谈。

    “听说了吗?北境那位传奇猎人,去年娶了个怪脾气的女人。”
    “怎么个怪法?”
    “据说她能在林中静坐半日不动,就为看一只松鼠埋橡果。还能叫出每只猎犬的名字。那猎人逢人便夸,说她是森林赐给他的礼物。”

    商贩们哄笑。莱恩纳德手中的账册滑落在地。

    他派了最可靠的人去北境查探。半月后回报:奎因桑,确已嫁与那位以箭术闻名的猎人,夫妻二人居于林畔木屋,出入成双,据说颇为和睦。

    那天夜里,莱恩纳德的城堡灯火通明。他没有处理任何政务,只是坐在议事厅的高背椅上,对着壁炉里跳动的火焰,沉默了一整夜。

    次日清晨,他的管家发现伯爵已经坐在书案前批阅积压的文书,字迹如常工整,只是墨痕有几处洇开了。

    后来,坦纳伯斯伯爵在路过他的领地时,曾与他共饮一杯。席间问及此事,莱恩纳德放下酒杯,目光落在窗外远处那片模糊的林线上,缓缓说道:

    “我用了很久才想明白。我许下的那个‘等我治好领地就去找她’的誓言,不过是一张永远不必兑现的借口。因为领地永远会有新的麻烦——正如我永远会有新的理由。我以为自己在等一个对的时机,其实只是在等自己足够勇敢。而勇气这种东西,等是等不来的。”

    他顿了顿,又说:“但有一件事,我确实没有骗自己。治理这片领地,从来不是为了她,也不是为了逃避她。我脚下的土地和土地上的人,才是真实的。那支没有射出的箭,就让它永远留在箭囊里吧。至少它提醒我,有些东西,错过了就是错过了。但手里剩下的箭,还得射向该去的地方。”

    (坦纳伯斯伯爵的结语)

    沼泽女巫在占卜时曾说:世间最锋利的箭,往往不是射中靶心的那一支,而是搭在弦上太久、最终被收回箭囊的那一支。它不曾射向何,却日复一日地磨损着持弓者的掌心。世人总以为遗憾是因为没有勇气,却不知有时候,正是因为没有勇气,我们才得以保全那些本会在日常琐碎中碎裂的幻梦。莱恩纳德的悲剧不在于他错过了她,而在于他用一个永远无法兑现的“以后”,欺骗了自己那么多年。所幸,他终于学会了区分——什么是可以弥补的,什么是只能咽下的。

  • Do And Done


    Do And Done

    风很大,但我还站着。这就够了。这就是我的 Done。

    一、站在风里的那个人

    2026年的某一天,我站在学校操场上,吹着冷风,和自己说了很久的话。

    那天我知道了:她有了男朋友。

    这件事我早就模拟过无数次——从我意识到“她会有男朋友”的那天起,我就在心里预演过这个场景。但当它真的发生时,我还是去了操场。不是去哭的。一滴眼泪都流不出来。

    我只是觉得有点冷。

    然后我开始和自己说话。不是自言自语,是真的说话——像对着另一个自己,把那些年积压的东西,全部摊开来,一件一件地看。

    那段录音,我今天翻出来听了。声音被风吹得有点抖,但每句话都像钉子,钉在那个晚上的空气里。

    这是我“Do and Done”诞生的夜晚。


    二、我曾经是个拯救者

    “我做任何事,都是为了拯救去的。这个课题很高尚。”

    这是我过去人生的全部脚本。

    我有一个“白骑士综合征”。我把喜欢的人变成了一个需要被拯救的符号,然后把“拯救她”设定为我活着的意义。考大学是为了拯救她,变好是为了拯救她,做一切事情都是为了那个宏大的目标。

    这个剧本有一个致命的漏洞:扮演英雄的人,自己却没有血包。

    “连自己都拯救不了的人,遑论拯救他人”——这句话我曾经说得理直气壮。我以为这是谦卑,后来才明白,这是逃避。我把爱“私有化”了:爱是需要先“配得上”才能领取的东西。而我永远配不上,因为我永远“还没拯救好自己”。

    所以我什么都不用真正去做。

    高尚的口号挂在嘴边,行动却停在原地。口号没有让我多10%的效率,但我仍然不肯放下。为什么?因为放下它,我就不知道我是谁了。


    三、神像的倒塌

    “现在好了,梦碎了。你连这个理由都没有了。”

    她找到那个人的时候,我的神像塌了。

    不是突然塌的。我早就模拟过这一天。从上学期末开始,我已经在慢慢接受她不在我生命中的事实。我只是没想到,当预言被验证的那一刻,我会这么……平静。

    一滴眼泪都没有。

    我难过吗?不难过。我只是把过去所有积压的情绪,重新过了一遍。然后发现:那个我曾经以为非她不可的人,其实早就不是我生活的一部分了。

    最讽刺的是什么?

    她过得很好。比我好。

    我一直在担心“她别死了”,结果活得比我还滋润。那个我曾经想要“拯救”的人,根本不需要我拯救。她靠自己,或者靠别人,走到了我当初设定的“拯救目标”那里——比如,找到一个可靠的男友。

    而我自己呢?

    “你考了个破大专,躺了两年。你做出什么成绩了?你连一等奖学金都没得。你做什么事情都不做出百分百的努力?”

    这是我对自己说的话。每句都扎在自己身上。


    四、空转的人生

    “你一直在做计划,但是你去执行了吗?很少。你的脑子一直在空想我该怎么解决问题,但是你真的落地去解决了吗?”

    这是我对自己的第二个发现。

    过去的我,活在一个奇怪的循环里:

    做计划 → 空想怎么执行 → 焦虑 → 再做计划

    就像一个传动轴,拼命转,却没有接上发动机。我以为自己在努力,其实只是在空转。我做项目,做题库,做小程序——但碰到一点困难就掉头。

    “你只敢撞一次南墙,你不敢撞第二次。你分不清哪些是小石子,哪些是真正的南墙。”

    小石子,掉头就走。
    真正的南墙,从来不敢撞。

    因为撞墙会痛。而我已经没有“为了她”这个理由,去承受那个痛了。


    五、“Do and Done”的诞生

    “事情的意义大多是事后赋予的。我只需要 Do and Done 就行了。”

    这句话,是在那片废墟上长出来的。

    它不是一句漂亮的口号。它是我在发现自己所有“高尚”都是骗局之后,能找到的、唯一可以握住的、最小的东西。

    什么是“Do and Done”?

    • 不做计划,先做一件事。做完,就打一个勾。
    • 不为“拯救谁”,就为“今天把这件事做完”。
    • 不问“这有什么意义”,做完之后,再回头去看。

    它和“得过且过”的区别是什么?

    得过且过是:反正没意义,所以我什么都不做。
    Do and Done是:正因为意义不明,所以我要先做点什么。

    每一个“Done”,都是在虚无里钉下的木桩。

    我按时吃饭了——Done。
    我跑完步了——Done。
    我把这个项目做完了——Done。

    这些木桩可能很小,但它们证明一件事:我存在过,我行动过,我没有停在原地。


    六、带着疑惑,走下去

    “接着走下去,带着疑惑,接着走下去。生命会自己找出出路。”

    我不知道这个哲学能带我走多远。

    我不知道做完一堆“Done”之后,我的人生会不会有答案。

    但我站在那个晚上的风里时,想明白了一件事:

    出路不是想出来的,是走出来的。

    我过去一直在空想“出路在哪里”。现在我决定,先迈一步。迈完一步,再迈一步。走完之后,回头看,那条路可能就是出路。

    那个晚上,风很大,人很多,每个人都拿着手机,每个人都像一座孤岛。

    “我觉得我是一个内部极大丰富的人,但是没有人能理解我,因为大家都被手机给困住了。”

    我也想被理解。但我知道,在被理解之前,我得先把自己活出来。

    活出来,不是靠“高尚的口号”活出来,而是靠一个又一个微小的“Do”,把自己从废墟里一点点挖出来。


    七、风吹过的时候

    “风吹过我的指尖,风吹过我的脸颊,风吹过我的发梢,好凉快,好舒服。但是感受过后呢,我确确实实的活着,但我活着我干嘛呢?”

    这是那天晚上,我问自己的最后一个问题。

    我没有答案。

    但我选择继续活着。继续感受风。继续做下一件小事。继续在每个夜晚,对自己说:

    今天,我又完成了一个 Done。

    那个曾经需要靠拯救别人来证明自己有价值的人,现在只需要靠做完一件小事,就能在深夜里对自己说:

    看,我今天存在过了。

    这就够了。

    风很大,但我还站着。

    一、重点原话摘录


    关于“拯救者”的幻灭:

    “我做任何事,都是为了拯救去的。这个课题很高尚,现在这份高尚被击碎了,你的高尚一点都不高尚,他一点都不在乎。这只是你一直一直在欺骗自己。”

    关于“私有化的爱”:

    “你不敢面对他的根本原因,就是你不敢面对你自己。你不敢把这个自己都拿不出手的人去面对他。所以你会说:连自己都拯救不了的人,遑论拯救他人呢。”

    关于“神像倒塌”:

    “梦碎了,你现在连这个理由都没有了。现在好了,梦碎了,你现在连这个理由都没有了。”

    关于“被验证的预言”:

    “你接触了你一早就模拟好这种——她会有男朋友,她已经有男朋友,现在只是把事实摆在你面前。这件事你已经试想过发生了,但是现在确实发生了,它只是验证了你的预言。”


    【旧模式的本质:空转的人生】

    关于“计划与执行的断裂”:

    “你一直在做计划,在做计划,但是你去执行了吗?很少。你的脑子一直在空想我该怎么解决问题,但是你真的落地去解决这个问题了没有?……就像那个传动轴没有接上那个发动机。”

    关于“不敢撞南墙”:

    “你只敢撞一次南墙,你不敢撞第二次。拿你的破头,一个项目撞一次南墙,哪怕是轻微的,哪怕是踩了一个石头,你都要往回掉头……你现在分不清哪些该调头,哪些是小石子,哪些是真正的南墙。”

    关于“用微小成就欺骗自己”:

    “还是在骗自己,拿一点微不足道的成就去骗自己。我今天做完一个项目,但是你真的学到了吗?你只是会用AI而已,给你的幻觉把你骗住了。”

    关于“缺乏宏大目标”:

    “所有事情都完成之后,你现在还是跟个无头苍蝇一样乱撞,因为你缺乏一个宏大的目标。你之前宏大的目标就是我要去变得更好,我要去拯救他……现在我缺乏一个宏大目标。”


    【新哲学的萌芽:Do and Done】

    关于“意义在事后赋予”:

    “事情的意义大多是事后赋予的。我只需要 Do and Done 就行了。”

    关于“带着疑惑走下去”:

    “接着走下去,带着疑惑,接着走下去。坚持下去,然后呢?然后说,生命会自己找出出路。”

    关于“真实的活着”:

    “我能感受到我有些时候我确实在感受到,风吹过我的指尖,风吹过我的脸颊,风吹过我的发梢,好凉快,好舒服。但是感受过后呢,我确确实实的活着,但我活着我干嘛呢?”


    【最后的诚实:站在废墟上】

    关于“哭不出来”:

    “一滴眼泪都流不出来。你难过吗?你这些事情你早预料到了。你难过吗?你不难过。我只是觉得有点冷。”

    关于“人和人的隔阂”:

    “每一个人拿着手机,都像一座无形的牢笼,把这彼此隔开了。我们再也不对话,然后矛盾越来越深。”

    关于“渴望被理解”:

    “我觉得我是一个内部极大丰富的人,但是没有人能理解我、来解读我,因为大家都被手机给困住了。”


    二、核心思维点梳理


    【思维点 01】“拯救者”的虚伪性

    核心洞察:

    “高尚的口号并没有为我的行事+10%效率,但我仍然不肯放下。”

    本质剖析:

    • 所谓“拯救他人”,本质是逃避面对真实的自己
    • “连自己都拯救不了”不是谦卑,而是把爱“私有化”的借口——把爱变成需要“配得上”才能领取的东西
    • 当拯救对象不再需要拯救,神像自然崩塌

    【思维点 02】“意义先于存在”的陷阱

    核心洞察:

    “在做之前就赋予意义的,叫预设意义,或本质先于存在。”

    本质剖析:

    • 预设意义让人获得方向感,但也让人依赖外部对象赋予价值
    • 一旦外部对象(如“她”)变化,意义大厦随之倾覆
    • 这是“空转人生”的根源:所有行动都指向一个虚幻的终点,而非过程本身

    【思维点 03】“传动轴没有接上发动机”

    核心洞察:

    “你一直在做计划,但不去执行;你在空想如何解决问题,但不落地解决。”

    本质剖析:

    • 思维与行动脱节,形成“空想-焦虑-再空想”的死循环
    • 看似比他人努力(做计划、做项目),实则没有真正的产出
    • 本质是恐惧:恐惧真实的行动会带来真实的失败

    【思维点 04】“只敢撞一次南墙”

    核心洞察:

    “你只敢撞一次南墙,你不敢撞第二次。你分不清哪些是小石子,哪些是真正的南墙。”

    本质剖析:

    • 缺乏持续试错的勇气,遇到一点阻力就调头
    • 这导致无法积累真正的经验,也无法区分“该放弃的”和“该坚持的”
    • 根源是:预设意义崩塌后,缺乏新的内在驱动力去支撑坚持

    【思维点 05】“意义是事后赋予的”

    核心洞察:

    “事情的意义大多是做完之后被赋予的。在做之前就赋予意义的,叫预设意义。”

    本质剖析:

    • 这是对“本质先于存在”的根本性翻转
    • 意义不再是行动的起点,而是行动可能带来的终点
    • 这让行动本身获得独立价值:行动不是为了实现某个预设的“高尚”,而是为了在行动后,自己可以回看、命名、赋予意义

    【思维点 06】“Do and Done”作为最低限度的行动哲学

    核心洞察:

    “我只需要 Do and Done 就行了。”

    本质剖析:

    • 在宏大目标缺失、意义感真空的状态下,这是唯一可行的起点
    • “Do”是行动的最小单位,“Done”是对行动的确认
    • 它不是“得过且过”,而是:用最小的行动单位,对抗宏大的虚无
    • 每一个“Done”,都是在废墟上钉下的木桩,证明自己存在过

    【思维点 07】“带着疑惑,走下去”

    核心洞察:

    “接着走下去,带着疑惑,接着走下去。生命会自己找出出路。”

    本质剖析:

    • 这是对“不确定性”的接纳——不再强求在行动前就看清全部意义
    • 这是一种“存在主义式”的勇气:在意义缺席时,依然选择行动
    • 出路不是想出来的,是走出来的

    【思维点 08】“被手机困住的一代人”

    核心洞察:

    “每一个人拿着手机,都像一座无形的牢笼,把彼此隔开了。我觉得我是一个内部极大丰富的人,但是没有人能理解我。”

    本质剖析:

    • 科技带来连接的幻觉,却加深了真实的隔阂
    • 每个人都渴望被深度理解,却没有人有勇气走出手机,去真正对话
    • 这构成了当代人普遍的孤独与迷茫

    【思维点 09】“遗憾被证实后,就不再是遗憾”

    核心洞察:

    “遗憾只是被证实了,现在遗憾就是遗憾了。你已经无法做到遗憾的事情,那你就不用担心那么多了。”

    本质剖析:

    • 真正折磨人的不是遗憾本身,而是“可能还未确定”的悬置状态
    • 当最坏的结果被证实,悬着的心反而落地
    • 这是一种奇怪的解脱:你终于可以不再为“如果”而内耗

    【思维点 10】“风吹过的时候,我确实活着”

    核心洞察:

    “风吹过我的指尖,风吹过我的脸颊,风吹过我的发梢,好凉快,好舒服。但是感受过后呢,我确确实实的活着,但我活着我干嘛呢?”

    本质剖析:

    • 这是最根本的存在主义困境:我感知到我活着,但我不知道为何而活
    • “Do and Done”无法回答“为何而活”,但它提供了一个起点:先活着,先行动,答案可能在后头
    • 这也是一种诚实:承认自己暂时没有答案,但不因此停止呼吸和行动

    2026年3月12日,一滴眼泪都没有,只是觉得有点冷”


    Happiness depends upon ourselves.

    幸福取决于我们自己。

    —— 亚里士多德