summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authori-shm <[email protected]>2026-08-20 02:41:23 +0000
committeri-shm <[email protected]>2026-08-20 02:41:23 +0000
commit50c3d7ad735b9edf3eaaf9f47da1d93fd6d5c264 (patch)
tree27f2054454a7657d05e051cf1471454175d31339
parentbce8cf8b87662b11deaa2cfdfe68ed6d8f7e1554 (diff)
downloadblog-50c3d7ad735b9edf3eaaf9f47da1d93fd6d5c264.tar.gz
deploy: cca9af916a79a76ed5408b765da3afeec6fbd8a4
-rw-r--r--2026/08/18/房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中/index.html5
-rw-r--r--2026/08/20/房颤心电图解析/index.html303
-rw-r--r--archives/2026/08/index.html18
-rw-r--r--archives/2026/index.html36
-rw-r--r--archives/2026/page/2/index.html18
-rw-r--r--archives/index.html36
-rw-r--r--archives/page/10/index.html36
-rw-r--r--archives/page/11/index.html38
-rw-r--r--archives/page/12/index.html36
-rw-r--r--archives/page/13/index.html36
-rw-r--r--archives/page/14/index.html36
-rw-r--r--archives/page/15/index.html36
-rw-r--r--archives/page/16/index.html38
-rw-r--r--archives/page/17/index.html36
-rw-r--r--archives/page/18/index.html20
-rw-r--r--archives/page/2/index.html36
-rw-r--r--archives/page/3/index.html36
-rw-r--r--archives/page/4/index.html36
-rw-r--r--archives/page/5/index.html36
-rw-r--r--archives/page/6/index.html36
-rw-r--r--archives/page/7/index.html36
-rw-r--r--archives/page/8/index.html36
-rw-r--r--archives/page/9/index.html36
-rw-r--r--search.xml597
-rw-r--r--tags/Medicine/index.html36
-rw-r--r--tags/Medicine/page/2/index.html36
-rw-r--r--tags/Medicine/page/3/index.html36
-rw-r--r--tags/Medicine/page/4/index.html36
-rw-r--r--tags/Medicine/page/5/index.html18
29 files changed, 1108 insertions, 667 deletions
diff --git a/2026/08/18/房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中/index.html b/2026/08/18/房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中/index.html
index 556dc147..d0db974c 100644
--- a/2026/08/18/房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中/index.html
+++ b/2026/08/18/房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中/index.html
@@ -380,6 +380,11 @@ mjx-container[display="true"] + br {
<nav class="post-nav">
<div class="prev-item">
+ <div class="icon arrow-left"></div>
+ <div class="post-link">
+ <a href="/2026/08/20/%E6%88%BF%E9%A2%A4%E5%BF%83%E7%94%B5%E5%9B%BE%E8%A7%A3%E6%9E%90/">Prev</a>
+ </div>
+
</div>
<div class="next-item">
diff --git a/2026/08/20/房颤心电图解析/index.html b/2026/08/20/房颤心电图解析/index.html
new file mode 100644
index 00000000..f44f0966
--- /dev/null
+++ b/2026/08/20/房颤心电图解析/index.html
@@ -0,0 +1,303 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+<meta http-equiv="X-UA-Compatible" content="ie=edge">
+
+ <meta name="author" content="韩暮秋">
+
+
+ <meta name="subtitle" content="暮秋小屋">
+
+
+ <meta name="description" content="这里是暮秋小屋,思念和灵感的寄存处">
+
+
+ <meta name="keywords" content="韩暮秋,MuqiuHan,'Muqiu Han', 'muqiu han', muqiuhan">
+
+
+
+
+ <title>
+
+ 房颤心电图解析:从 P 波消失到不规则心室节律 |
+ 暮秋小屋
+ </title>
+
+
+
+ <link rel="icon" href="/favicon.ico">
+
+
+
+
+ <!-- stylesheets list from _config.yml -->
+
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+
+ <link rel="preload" href="/fonts/FZYouSongS-509R.woff2" as="font" type="font/woff2" crossorigin>
+
+
+
+ <!-- scripts list from _config.yml -->
+
+ <script
+ src="/js/menu.js"></script>
+
+
+
+
+
+ <script
+ src="https://polyfill.alicdn.com/polyfill.js?features=es6"></script>
+ <script
+ id="MathJax-script"
+ async
+ src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/mathjax/3.2.0/es5/tex-mml-chtml.js"></script>
+
+
+
+
+ <meta name="generator" content="Hexo 6.3.0"></head>
+ <body>
+ <div class="wrapper">
+
+ <div class="header">
+ <div class="flex-container">
+ <div class="header-inner">
+ <div class="site-brand-container">
+ <a href="/">
+
+ 暮秋小屋
+
+ </a>
+ </div>
+ <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
+ 菜单
+ </div>
+ <nav class="site-nav">
+ <ul class="menu-list">
+
+
+ <li class="menu-item">
+ <a href="/">
+ 主页
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/categories/gallery/">
+ 日记本
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Medicine/">
+ 泛医学
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Technique/">
+ 计算机
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/tags/Life/">
+ 生活
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/archives">
+ 全部
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/about">
+ 关于
+ </a>
+ </li>
+
+
+
+ <li class="menu-item">
+ <a href="/search">搜索</a>
+ </li>
+
+ </ul>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+ <div class="main">
+ <div class="flex-container">
+ <article id="post">
+
+
+ <div class="post-head">
+ <div class="post-info">
+ <div class="tag-list">
+
+
+ <span class="post-tag">
+ <a href="/tags/Medicine/">
+ Medicine
+ </a>
+ </span>
+
+
+ </div>
+ <div class="post-title">
+
+
+ 房颤心电图解析:从 P 波消失到不规则心室节律
+
+
+ </div>
+ <span class="post-date">
+ Aug 20, 2026
+ </span>
+ </div>
+ <div class="post-img">
+
+ <div class="h-line-primary"></div>
+
+ </div>
+</div>
+ <div class="post-content">
+ <p>房颤的心电图识别,主要依靠三个关系:<strong>P 波是否存在、R-R 间期是否规则、QRS 波群是否增宽</strong>。其中,P 波消失和心室节律绝对不规则最支持房颤;QRS 波群的宽窄则帮助判断心室内传导情况,但不能单独用来判断患者是否安全。</p>
+<h2 id="先看一条标准心电图"><a class="header-anchor" href="#先看一条标准心电图">¶</a>先看一条标准心电图</h2>
+<p>临床诊断房颤需要记录到典型心律,再由医生结合病史确认。2024 年欧洲房颤指南把房颤诊断、卒中预防、症状控制和危险因素管理放在同一个长期管理框架中<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>。</p>
+<p>一张常规十二导联心电图首先观察三件事:有没有规律出现的 P 波;相邻 QRS 波群之间的 R-R 间期是否长短不一;QRS 波群是否增宽。三个特征需要一起判断。单独看到心率快、一次 R-R 间期变化,或者某个导联中的 P 波不清楚,都不足以完成房颤诊断。</p>
+<h2 id="第一处:P-波消失,基线出现细小波动"><a class="header-anchor" href="#第一处:P-波消失,基线出现细小波动">¶</a>第一处:P 波消失,基线出现细小波动</h2>
+<p>窦性心律中,心房由窦房结发出有序电活动。每次心室激动前,心电图通常可以看到一个形态相对稳定的 P 波。P 波代表心房去极化,随后电活动经过房室结传向心室,形成 QRS 波群。</p>
+<p>房颤时,心房电活动快速而无序,不能形成一次有效的整体收缩。心电图上常见的表现是找不到持续、规则、形态稳定的 P 波,QRS 波群之间的基线出现细小而不规则的波动。不同导联中的基线波动清晰度可能不同,肌肉震颤和电极接触不良也可能制造类似干扰。</p>
+<p>因此,“没有看到 P 波”不能机械地等同于房颤。需要把纸速、导联、基线质量和 R-R 间期一起纳入判断。</p>
+<h2 id="第二处:R-R-间期绝对不规则"><a class="header-anchor" href="#第二处:R-R-间期绝对不规则">¶</a>第二处:R-R 间期绝对不规则</h2>
+<p>房颤的另一个核心特征是心室节律不规则。由于房室结接收到的心房冲动没有固定规律,传到心室的冲动间隔会发生变化,表现为 R-R 间期长短不一,而且通常不存在可重复的规律。</p>
+<p>这和呼吸性窦性心律不齐不同。后者的 R-R 间期变化往往与呼吸周期有关,仍然可以找到规律的 P 波。房性早搏、室性早搏、房扑伴不规则传导和部分多源性房性心动过速,也可能造成节律不齐,需要结合完整心电图鉴别。</p>
+<p>心率是平均值,不能代替节律判断。一次记录显示 116 次/分,只能说明这段记录中的平均心室率偏快;它不能单独证明房颤,也不能单独判断症状严重程度。</p>
+<h2 id="第三处:QRS-波群窄,不等于房颤风险低"><a class="header-anchor" href="#第三处:QRS-波群窄,不等于房颤风险低">¶</a>第三处:QRS 波群窄,不等于房颤风险低</h2>
+<p>QRS 波群反映心室去极化。若 QRS 时限相对较窄,通常说明这次心室激动主要沿正常或接近正常的传导路径下传;若 QRS 明显增宽,则需要考虑束支传导阻滞、室内传导延迟、预激或室性心律等情况。</p>
+<p>房颤可以伴窄 QRS,也可以伴宽 QRS。快速房颤伴原有束支阻滞、差异性传导或预激时,QRS 可能增宽。因此,窄 QRS 只能说明当前记录中的室内传导没有明显增宽,不能推出“不会发生心脏骤停”,也不能替代对卒中、心衰和基础心脏病的评估。</p>
+<h2 id="交互示意:把三处观察点分开看"><a class="header-anchor" href="#交互示意:把三处观察点分开看">¶</a>交互示意:把三处观察点分开看</h2>
+<p>下面的图是教学示意,不是任何患者原始心电图的逐点重建。点击按钮后,可以分别突出 P 波、R-R 间期和 QRS 波群。</p>
+<div class="ecg-demo" data-ecg-demo>
+<style>
+.ecg-demo{--ink:#1c1917;--muted:#78716c;--paper:#faf8f5;--grid:rgba(210,190,174,.42);--red:#dc2626;--blue:#2563eb;--green:#15803d;margin:2rem 0;padding:1rem;background:var(--paper);border:2px solid var(--ink);box-shadow:5px 5px 0 var(--ink);color:var(--ink);overflow:hidden}.ecg-demo *{box-sizing:border-box}.ecg-demo h3{margin:0;font-size:1rem}.ecg-demo p{margin:.35rem 0 0;color:var(--muted);font-size:.8rem;line-height:1.65}.ecg-demo-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem;border-bottom:1px solid #d6d3d1;padding-bottom:.7rem}.ecg-demo-badge{padding:.2rem .45rem;border:1px solid var(--red);color:var(--red);font:700 .7rem/1.2 monospace;transform:rotate(-1deg)}.ecg-demo-controls{display:flex;flex-wrap:wrap;gap:.45rem;margin:.8rem 0}.ecg-demo button{cursor:pointer;padding:.38rem .58rem;border:1px solid #a8a29e;background:#fff;color:var(--ink);font:700 .72rem/1.2 monospace}.ecg-demo button:hover,.ecg-demo button[data-active=true]{border-color:var(--ink);background:var(--ink);color:#fff}.ecg-demo-canvas{overflow-x:auto;padding:.55rem;border:1px solid #78716c;background-color:#fffdfb;background-image:linear-gradient(to right,var(--grid) 1px,transparent 1px),linear-gradient(to bottom,var(--grid) 1px,transparent 1px);background-size:10px 10px}.ecg-demo-canvas svg{display:block;width:100%;min-width:620px;height:auto}.ecg-demo-note{margin-top:.7rem;padding:.65rem .75rem;border-left:4px solid var(--blue);background:#eff6ff;color:#1e3a8a;font-size:.82rem;line-height:1.7}.ecg-demo-legend{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin-top:.75rem;font:.7rem/1.5 monospace}.ecg-demo-legend span{padding:.35rem;background:#fff;border:1px solid #d6d3d1}.ecg-demo .layer{transition:opacity .22s ease}@media(max-width:640px){.ecg-demo-head{display:block}.ecg-demo-badge{display:inline-block;margin-top:.55rem}.ecg-demo-legend{grid-template-columns:1fr}}
+</style>
+<div class="ecg-demo-head"><div><h3>交互示意:窦性心律与房颤的三个观察点</h3><p>教学示意|不代表任何患者的原始心电图</p></div><span class="ecg-demo-badge">ECG SKETCH</span></div>
+<div class="ecg-demo-controls" role="group" aria-label="选择心电图观察点"><button type="button" data-focus="all" data-active="true">总览</button><button type="button" data-focus="pwave">P 波 / f 波</button><button type="button" data-focus="rr">R-R 间期</button><button type="button" data-focus="qrs">QRS 波群</button></div>
+<div class="ecg-demo-canvas"><svg viewBox="0 0 760 250" role="img" aria-label="窦性心律与房颤心电图示意"><text x="10" y="20" fill="#15803d" font-size="14" font-family="monospace" font-weight="700">窦性心律</text><text x="10" y="137" fill="#dc2626" font-size="14" font-family="monospace" font-weight="700">房颤示意</text><path d="M90 55 Q102 43 114 55 L126 55 L130 22 L136 82 L142 50 L148 55 Q160 43 172 55 L205 55 Q217 43 229 55 L241 55 L245 22 L251 82 L257 50 L263 55 Q275 43 287 55 L320 55 Q332 43 344 55 L356 55 L360 22 L366 82 L372 50 L378 55 Q390 43 402 55 L435 55 Q447 43 459 55 L471 55 L475 22 L481 82 L487 50 L493 55 Q505 43 517 55" fill="none" stroke="#15803d" stroke-width="2.4" stroke-linecap="round"/><text x="91" y="98" fill="#15803d" font-size="11" font-family="monospace">P 波规则出现</text><line x1="130" y1="32" x2="245" y2="32" stroke="#15803d" stroke-dasharray="3 3"/><line x1="245" y1="32" x2="360" y2="32" stroke="#15803d" stroke-dasharray="3 3"/><text x="300" y="28" fill="#15803d" font-size="10" font-family="monospace">R-R 间期规则</text><path d="M90 174 Q100 169 108 177 T124 172 T140 176 T155 171 L168 175 L172 142 L178 207 L184 168 L190 175 Q202 170 214 178 T232 171 T250 177 T268 170 T286 176 L300 175 L304 142 L310 207 L316 168 L322 175 Q333 169 344 178 T360 171 T377 177 T396 170 T415 176 T434 171 L448 175 L452 142 L458 207 L464 168 L470 175 Q483 170 498 178 T518 171 T536 177 T553 170 T570 176 L585 175 L589 142 L595 207 L601 168 L607 175 Q620 170 636 178 T655 171 T673 176" fill="none" stroke="#dc2626" stroke-width="2.4" stroke-linecap="round"/><rect class="layer" data-layer="pwave" x="195" y="161" width="105" height="27" fill="#fee2e2" stroke="#dc2626" stroke-dasharray="3 2"/><text class="layer" data-layer="pwave" x="247" y="205" text-anchor="middle" fill="#dc2626" font-size="10" font-family="monospace" font-weight="700">P 波消失,基线细小波动</text><line class="layer" data-layer="rr" x1="172" y1="130" x2="304" y2="130" stroke="#b45309" stroke-dasharray="3 3"/><line class="layer" data-layer="rr" x1="304" y1="130" x2="452" y2="130" stroke="#2563eb" stroke-dasharray="3 3"/><text class="layer" data-layer="rr" x="365" y="125" text-anchor="middle" fill="#2563eb" font-size="10" font-family="monospace" font-weight="700">R-R 间期长短不一</text><rect class="layer" data-layer="qrs" x="448" y="139" width="28" height="74" fill="#dcfce7" stroke="#15803d"/><text class="layer" data-layer="qrs" x="465" y="229" text-anchor="middle" fill="#15803d" font-size="10" font-family="monospace" font-weight="700">QRS</text></svg></div>
+<div class="ecg-demo-note" data-explain>总览:房颤示意中可以同时观察 P 波缺失、R-R 间期不规则和 QRS 波群形态。三者需要结合判断。</div><div class="ecg-demo-legend"><span style="color:#dc2626">红色:房颤示意</span><span style="color:#15803d">绿色:窦性心律或相对窄的 QRS</span><span style="color:#2563eb">蓝色:节律间期标注</span></div>
+<script>
+(function(){var root=document.querySelector('[data-ecg-demo]');if(!root)return;var explain=root.querySelector('[data-explain]');var texts={all:'总览:房颤示意中可以同时观察 P 波缺失、R-R 间期不规则和 QRS 波群形态。三者需要结合判断。',pwave:'P 波 / f 波:窦性心律通常有规则 P 波;房颤时找不到持续、规则的 P 波,基线可能出现细小而不规则的波动。',rr:'R-R 间期:房颤常表现为心室节律绝对不规则。仅有一次间期变化,不能单独完成房颤诊断。',qrs:'QRS 波群:图中绿色框只是标出相对窄的 QRS。窄 QRS 不等于整体风险低,也不能单独排除其他心律问题。'};var layers={pwave:root.querySelectorAll('[data-layer=pwave]'),rr:root.querySelectorAll('[data-layer=rr]'),qrs:root.querySelectorAll('[data-layer=qrs]')};function focus(mode){Object.keys(layers).forEach(function(key){layers[key].forEach(function(node){node.style.opacity=mode==='all'||mode===key?'1':'.12';});});root.querySelectorAll('[data-focus]').forEach(function(button){button.dataset.active=button.dataset.focus===mode?'true':'false';});explain.textContent=texts[mode];}root.querySelectorAll('[data-focus]').forEach(function(button){button.addEventListener('click',function(){focus(button.dataset.focus);});});focus('all');}());
+</script>
+</div>
+<h2 id="房颤和房扑不能混为一谈"><a class="header-anchor" href="#房颤和房扑不能混为一谈">¶</a>房颤和房扑不能混为一谈</h2>
+<p>房扑也可能造成心房活动异常和心室节律不齐,但其心房电活动常呈现较规则的锯齿样扑动波,尤其在下壁导联中更容易观察到。房颤的基线活动通常更加无序,R-R 间期也更不规则。不过,真实心电图可能受到心率、房室传导比例、药物、导联质量和合并心律失常影响,不能只凭一小段波形截图下结论。</p>
+<h2 id="手表提示“可能房颤”,下一步做什么"><a class="header-anchor" href="#手表提示“可能房颤”,下一步做什么">¶</a>手表提示“可能房颤”,下一步做什么</h2>
+<p>智能手表和手环可以帮助发现异常节律,但“设备提示”与“临床确诊”不是同一件事。Apple Heart Study 纳入 419,297 名参与者;研究结果显示,设备提示具有筛查价值,但提示本身不等于确诊<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。</p>
+<p>具有单导联心电图功能的设备,能够提供比单纯脉搏波更接近心电信号的记录。研究显示,单导联设备在部分心律识别任务中有帮助,但对不同类型的室上性心动过速,判读准确度仍低于标准十二导联心电图<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>。</p>
+<p>如果设备反复提示可能存在房颤,应保存原始记录,记录发生时间、持续时间和伴随症状,并到心内科接受标准心电图或动态心电图评估。不要依据手表提示自行开始抗凝,也不要因为一次“未发现房颤”就认为以后不会发生房颤。</p>
+<h2 id="房颤心电图之后,还要评估什么"><a class="header-anchor" href="#房颤心电图之后,还要评估什么">¶</a>房颤心电图之后,还要评估什么</h2>
+<p>心电图回答的是“这段时间有没有记录到怎样的心律”。它不能单独回答患者长期卒中风险、出血风险、心脏结构和诱发因素。</p>
+<p>确诊或高度怀疑房颤后,医生还需要结合年龄、既往卒中或短暂性脑缺血发作、高血压、糖尿病、心力衰竭、血管疾病、肾功能、贫血、甲状腺功能和用药情况,判断后续检查与治疗方向。抗凝、控制心率、节律控制和危险因素管理需要放在同一套决策中,不能只盯着心率数字。</p>
+<p>如果同时出现单侧肢体无力、口角歪斜、言语含糊、突发视物异常、持续胸痛、晕厥或严重呼吸困难,应立即急诊处理。即使症状很快缓解,也不能排除短暂性脑缺血发作或其他急症。</p>
+<h2 id="结语"><a class="header-anchor" href="#结语">¶</a>结语</h2>
+<p>房颤心电图的识别可以从三个问题开始:<strong>有没有规则 P 波,R-R 间期是否绝对不规则,QRS 波群是否增宽</strong>。最有价值的判断来自这些特征的组合,而不是某一个数字或某一个设备提示。</p>
+<p>心电图确认的是当时记录到的电活动。患者是否需要抗凝、控制心率、恢复节律或进一步检查,还要结合卒中风险、出血风险、心脏结构和基础疾病综合决定。</p>
+<hr>
+<h2 id="参考文献"><a class="header-anchor" href="#参考文献">¶</a>参考文献</h2>
+<hr class="footnotes-sep">
+<section class="footnotes">
+<ol class="footnotes-list">
+<li id="fn1" class="footnote-item"><p>Van Gelder IC, et al. 2024 ESC Guidelines for the management of atrial fibrillation developed in collaboration with the EACTS. <em>European Heart Journal</em>. 2024;45(36):3314-3414. PMID: <a target="_blank" rel="noopener" href="https://pubmed.ncbi.nlm.nih.gov/39210723/">39210723</a>. DOI: <a target="_blank" rel="noopener" href="https://doi.org/10.1093/eurheartj/ehae176">10.1093/eurheartj/ehae176</a>. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn2" class="footnote-item"><p>Perez MV, et al. Large-Scale Assessment of a Smartwatch to Identify Atrial Fibrillation. <em>New England Journal of Medicine</em>. 2019;381:1909-1917. PMID: <a target="_blank" rel="noopener" href="https://pubmed.ncbi.nlm.nih.gov/31722151/">31722151</a>. DOI: <a target="_blank" rel="noopener" href="https://doi.org/10.1056/NEJMoa1901183">10.1056/NEJMoa1901183</a>. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn3" class="footnote-item"><p>Vukadinovic D, et al. Diagnostic accuracy of Apple Watch Series 6 recorded single-lead ECGs for identifying supraventricular tachyarrhythmias: a comparative analysis with invasive electrophysiological study. <em>Europace</em>. 2024. PMID: <a target="_blank" rel="noopener" href="https://pubmed.ncbi.nlm.nih.gov/37985539/">37985539</a>. <a href="#fnref3" class="footnote-backref">↩︎</a></p>
+</li>
+</ol>
+</section>
+
+</div>
+
+<script>
+ window.onload = detectors();
+</script>
+ <div class="post-footer">
+ <div class="h-line-primary"></div>
+ <nav class="post-nav">
+ <div class="prev-item">
+
+ </div>
+ <div class="next-item">
+
+ <div class="icon arrow-right"></div>
+ <div class="post-link">
+ <a href="/2026/08/18/%E6%88%BF%E9%A2%A4%E4%B8%8E%E8%A1%80%E6%A0%93%E6%A0%93%E5%A1%9E%EF%BC%9A%E4%BB%8E%E5%B7%A6%E5%BF%83%E8%80%B3%E8%A1%80%E6%B5%81%E6%B7%A4%E6%BB%9E%E5%88%B0%E7%BC%BA%E8%A1%80%E6%80%A7%E5%8D%92%E4%B8%AD/">Next</a>
+ </div>
+
+ </div>
+ </nav>
+</div>
+
+
+ <div class="post-comment">
+
+
+
+
+
+
+
+</div>
+
+
+</article>
+ </div>
+ </div>
+
+ <div class="footer">
+ <div class="flex-container">
+ <div class="footer-text">
+
+
+ 韩暮秋 |
+
+
+ 希望路过的人可以添点柴火让这里暖和点
+
+ </div>
+ </div>
+</div>
+
+
+ </div>
+
+ <script src="/js/mermaid-zoom.js"></script>
+
+ </body>
+</html>
diff --git a/archives/2026/08/index.html b/archives/2026/08/index.html
index 5b5ab4a5..cac6a090 100644
--- a/archives/2026/08/index.html
+++ b/archives/2026/08/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2026/08/20/%E6%88%BF%E9%A2%A4%E5%BF%83%E7%94%B5%E5%9B%BE%E8%A7%A3%E6%9E%90/">
+
+ 房颤心电图解析:从 P 波消失到不规则心室节律
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 20, 2026</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2026/08/18/%E6%88%BF%E9%A2%A4%E4%B8%8E%E8%A1%80%E6%A0%93%E6%A0%93%E5%A1%9E%EF%BC%9A%E4%BB%8E%E5%B7%A6%E5%BF%83%E8%80%B3%E8%A1%80%E6%B5%81%E6%B7%A4%E6%BB%9E%E5%88%B0%E7%BC%BA%E8%A1%80%E6%80%A7%E5%8D%92%E4%B8%AD/">
房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中
diff --git a/archives/2026/index.html b/archives/2026/index.html
index 970718b8..1d77822d 100644
--- a/archives/2026/index.html
+++ b/archives/2026/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2026/08/20/%E6%88%BF%E9%A2%A4%E5%BF%83%E7%94%B5%E5%9B%BE%E8%A7%A3%E6%9E%90/">
+
+ 房颤心电图解析:从 P 波消失到不规则心室节律
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 20, 2026</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2026/08/18/%E6%88%BF%E9%A2%A4%E4%B8%8E%E8%A1%80%E6%A0%93%E6%A0%93%E5%A1%9E%EF%BC%9A%E4%BB%8E%E5%B7%A6%E5%BF%83%E8%80%B3%E8%A1%80%E6%B5%81%E6%B7%A4%E6%BB%9E%E5%88%B0%E7%BC%BA%E8%A1%80%E6%80%A7%E5%8D%92%E4%B8%AD/">
房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2026/03/06/Tacrolimus-for-Stasis-Dermatitis-in-Palliative-Heart-Failure-and-COPD/">
-
- 他克莫司在心衰合并COPD晚期患者淤积性皮炎中的姑息治疗可行性报告
-
- </a>
- </div>
-
- <span class="post-date">Mar 6, 2026</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/2026/page/2/index.html b/archives/2026/page/2/index.html
index e64b3508..fcd1d8df 100644
--- a/archives/2026/page/2/index.html
+++ b/archives/2026/page/2/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2026/03/06/Tacrolimus-for-Stasis-Dermatitis-in-Palliative-Heart-Failure-and-COPD/">
+
+ 他克莫司在心衰合并COPD晚期患者淤积性皮炎中的姑息治疗可行性报告
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 6, 2026</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2026/02/16/%E8%80%81%E5%B9%B4%E4%BA%BA%E8%90%A5%E5%85%BB%E8%AF%AF%E5%8C%BA/">
老年人营养不良误区
diff --git a/archives/index.html b/archives/index.html
index 229c5976..123fb445 100644
--- a/archives/index.html
+++ b/archives/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2026/08/20/%E6%88%BF%E9%A2%A4%E5%BF%83%E7%94%B5%E5%9B%BE%E8%A7%A3%E6%9E%90/">
+
+ 房颤心电图解析:从 P 波消失到不规则心室节律
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 20, 2026</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2026/08/18/%E6%88%BF%E9%A2%A4%E4%B8%8E%E8%A1%80%E6%A0%93%E6%A0%93%E5%A1%9E%EF%BC%9A%E4%BB%8E%E5%B7%A6%E5%BF%83%E8%80%B3%E8%A1%80%E6%B5%81%E6%B7%A4%E6%BB%9E%E5%88%B0%E7%BC%BA%E8%A1%80%E6%80%A7%E5%8D%92%E4%B8%AD/">
房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2026/03/06/Tacrolimus-for-Stasis-Dermatitis-in-Palliative-Heart-Failure-and-COPD/">
-
- 他克莫司在心衰合并COPD晚期患者淤积性皮炎中的姑息治疗可行性报告
-
- </a>
- </div>
-
- <span class="post-date">Mar 6, 2026</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/10/index.html b/archives/page/10/index.html
index 1bc7423d..f0851d0a 100644
--- a/archives/page/10/index.html
+++ b/archives/page/10/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/07/01/OCaml-News-2024-4/">
+
+ OCaml News 2024-4
+
+ </a>
+ </div>
+
+ <span class="post-date">Jul 1, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/06/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
二〇二四年六月二十七日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
-
- 二〇二四年三月二十二日
-
- </a>
- </div>
-
- <span class="post-date">Mar 22, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/11/index.html b/archives/page/11/index.html
index 924be0c1..28e03d9d 100644
--- a/archives/page/11/index.html
+++ b/archives/page/11/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/03/22/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B8%89%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/">
+
+ 二〇二四年三月二十二日
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 22, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/02/26/OCaml-News-2024-3/">
OCaml News 2024-3
@@ -319,26 +337,6 @@
</div>
-
-
-
-
- <div class="year-title">2023</div>
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/12/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/">
-
- 二〇二三年十二月二日
-
- </a>
- </div>
-
- <span class="post-date">Dec 2, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/12/index.html b/archives/page/12/index.html
index 90c3c41a..c3b9b532 100644
--- a/archives/page/12/index.html
+++ b/archives/page/12/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/12/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/">
+
+ 二〇二三年十二月二日
+
+ </a>
+ </div>
+
+ <span class="post-date">Dec 2, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/12/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/">
二〇二三年十二月一日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/10/21/OCaml-Core-Int-pow-%E7%9A%84%E5%AE%9E%E7%8E%B0/">
-
- OCaml Core.Int.pow 的实现
-
- </a>
- </div>
-
- <span class="post-date">Oct 21, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/13/index.html b/archives/page/13/index.html
index e4ac84d8..1d5feb2f 100644
--- a/archives/page/13/index.html
+++ b/archives/page/13/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/10/21/OCaml-Core-Int-pow-%E7%9A%84%E5%AE%9E%E7%8E%B0/">
+
+ OCaml Core.Int.pow 的实现
+
+ </a>
+ </div>
+
+ <span class="post-date">Oct 21, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/10/13/%E8%82%9D%E5%8A%9F%E8%83%BD%E6%A3%80%E6%9F%A5%E5%8C%96%E9%AA%8C%E5%8D%95/">
肝功能检查化验单阅读指南
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/08/15/poll-error-attribute-in-OCaml/">
-
- 使用 [@poll error] 实现线程安全的数据结构
-
- </a>
- </div>
-
- <span class="post-date">Aug 15, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/14/index.html b/archives/page/14/index.html
index 80ba3c36..f3208ab8 100644
--- a/archives/page/14/index.html
+++ b/archives/page/14/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/08/15/poll-error-attribute-in-OCaml/">
+
+ 使用 [@poll error] 实现线程安全的数据结构
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 15, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/08/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/">
二〇二三年八月一日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/">
-
- Rust 闭包 lifetime may not live long enough 问题
-
- </a>
- </div>
-
- <span class="post-date">May 24, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/15/index.html b/archives/page/15/index.html
index 7c496f0b..685bc934 100644
--- a/archives/page/15/index.html
+++ b/archives/page/15/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/">
+
+ Rust 闭包 lifetime may not live long enough 问题
+
+ </a>
+ </div>
+
+ <span class="post-date">May 24, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/05/03/Rust-NewType-%E6%A8%A1%E5%BC%8F/">
Rust NewType 模式
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/">
-
- 金匮要略
-
- </a>
- </div>
-
- <span class="post-date">Mar 4, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/16/index.html b/archives/page/16/index.html
index 04bb9ca5..570564ec 100644
--- a/archives/page/16/index.html
+++ b/archives/page/16/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/">
+
+ 金匮要略
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 4, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/03/01/%E6%B0%94%E8%83%B8/">
气胸
@@ -319,26 +337,6 @@
</div>
-
-
-
-
- <div class="year-title">2022</div>
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2022/12/31/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%89%E5%8D%81%E4%B8%80%E6%97%A5/">
-
- 二零二二年十二月三十一日
-
- </a>
- </div>
-
- <span class="post-date">Dec 31, 2022</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/17/index.html b/archives/page/17/index.html
index 8c0ab24d..9829e6fe 100644
--- a/archives/page/17/index.html
+++ b/archives/page/17/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2022/12/31/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%B8%89%E5%8D%81%E4%B8%80%E6%97%A5/">
+
+ 二零二二年十二月三十一日
+
+ </a>
+ </div>
+
+ <span class="post-date">Dec 31, 2022</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2022/11/03/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E6%9C%88%E4%B8%89%E6%97%A5/">
二零二二年十一月月三日
@@ -321,24 +339,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2021/02/14/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%80%E5%B9%B4%E4%BA%8C%E6%9C%88%E5%8D%81%E5%9B%9B%E6%97%A5/">
-
- 二零二一年二月十四日
-
- </a>
- </div>
-
- <span class="post-date">Feb 14, 2021</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/18/index.html b/archives/page/18/index.html
index c93e76bf..843d494d 100644
--- a/archives/page/18/index.html
+++ b/archives/page/18/index.html
@@ -159,6 +159,26 @@
+ <div class="year-title">2021</div>
+
+
+ <div class="post-list-item">
+ <div class="post-title">
+ <a href="/2021/02/14/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%80%E5%B9%B4%E4%BA%8C%E6%9C%88%E5%8D%81%E5%9B%9B%E6%97%A5/">
+
+ 二零二一年二月十四日
+
+ </a>
+ </div>
+
+ <span class="post-date">Feb 14, 2021</span>
+ </div>
+
+
+
+
+
+
<div class="year-title">2020</div>
diff --git a/archives/page/2/index.html b/archives/page/2/index.html
index fac0106f..b7f1633c 100644
--- a/archives/page/2/index.html
+++ b/archives/page/2/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2026/03/06/Tacrolimus-for-Stasis-Dermatitis-in-Palliative-Heart-Failure-and-COPD/">
+
+ 他克莫司在心衰合并COPD晚期患者淤积性皮炎中的姑息治疗可行性报告
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 6, 2026</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2026/02/16/%E8%80%81%E5%B9%B4%E4%BA%BA%E8%90%A5%E5%85%BB%E8%AF%AF%E5%8C%BA/">
老年人营养不良误区
@@ -321,24 +339,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/11/29/FDA-%E4%BB%BF%E5%88%B6%E8%8D%AF%E6%B5%81%E7%A8%8B/">
-
- FDA 仿制药流程
-
- </a>
- </div>
-
- <span class="post-date">Nov 29, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/3/index.html b/archives/page/3/index.html
index 2e317604..a4eac3b8 100644
--- a/archives/page/3/index.html
+++ b/archives/page/3/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/11/29/FDA-%E4%BB%BF%E5%88%B6%E8%8D%AF%E6%B5%81%E7%A8%8B/">
+
+ FDA 仿制药流程
+
+ </a>
+ </div>
+
+ <span class="post-date">Nov 29, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/11/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/">
二〇二五年十一月二十七日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/10/19/Gram-stain/">
-
- 什么是 G⁺
-
- </a>
- </div>
-
- <span class="post-date">Oct 19, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/4/index.html b/archives/page/4/index.html
index 07fa75ec..91670a10 100644
--- a/archives/page/4/index.html
+++ b/archives/page/4/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/10/19/Gram-stain/">
+
+ 什么是 G⁺
+
+ </a>
+ </div>
+
+ <span class="post-date">Oct 19, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/10/19/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E6%9C%88%E5%8D%81%E4%B9%9D%E6%97%A5/">
二〇二五年十月十九日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/07/08/dadgad/">
-
- DADGAD 定弦
-
- </a>
- </div>
-
- <span class="post-date">Jul 8, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/5/index.html b/archives/page/5/index.html
index d746697f..ff23e27e 100644
--- a/archives/page/5/index.html
+++ b/archives/page/5/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/07/08/dadgad/">
+
+ DADGAD 定弦
+
+ </a>
+ </div>
+
+ <span class="post-date">Jul 8, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/06/30/ibs/">
肠易激综合征 (IBS) 的病理学与药物治疗
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/04/03/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%89%E6%97%A5/">
-
- 二〇二五年四月三日
-
- </a>
- </div>
-
- <span class="post-date">Apr 3, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/6/index.html b/archives/page/6/index.html
index bdb673cb..767eec72 100644
--- a/archives/page/6/index.html
+++ b/archives/page/6/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/04/03/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%89%E6%97%A5/">
+
+ 二〇二五年四月三日
+
+ </a>
+ </div>
+
+ <span class="post-date">Apr 3, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/04/02/N-1-selects-problem-%E4%B8%8E-Prisma-ORM/">
N+1 selects problem 与 Prisma ORM
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/03/14/DDD-%E4%B8%AD%E7%9A%84-Ubiquitous-Languages/">
-
- DDD 中的 Ubiquitous Language
-
- </a>
- </div>
-
- <span class="post-date">Mar 14, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/7/index.html b/archives/page/7/index.html
index a5b0eb24..b3c88cb9 100644
--- a/archives/page/7/index.html
+++ b/archives/page/7/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/03/14/DDD-%E4%B8%AD%E7%9A%84-Ubiquitous-Languages/">
+
+ DDD 中的 Ubiquitous Language
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 14, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/03/13/%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1%E4%B8%AD%E7%9A%84%E2%80%9C%E8%81%9A%E5%90%88%E6%A0%B9%E2%80%9D/">
领域驱动设计中的“聚合根”
@@ -321,24 +339,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/11/26/%E5%A6%82%E4%BD%95%E7%AE%A1%E7%90%86%E7%94%A8%E6%88%B7%E7%95%8C%E9%9D%A2%E4%B8%AD%E7%9A%84%E5%8D%B1%E9%99%A9%E6%93%8D%E4%BD%9C/">
-
- 如何管理用户界面中的危险操作
-
- </a>
- </div>
-
- <span class="post-date">Nov 26, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/8/index.html b/archives/page/8/index.html
index 10fbe68f..9e2e5267 100644
--- a/archives/page/8/index.html
+++ b/archives/page/8/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/11/26/%E5%A6%82%E4%BD%95%E7%AE%A1%E7%90%86%E7%94%A8%E6%88%B7%E7%95%8C%E9%9D%A2%E4%B8%AD%E7%9A%84%E5%8D%B1%E9%99%A9%E6%93%8D%E4%BD%9C/">
+
+ 如何管理用户界面中的危险操作
+
+ </a>
+ </div>
+
+ <span class="post-date">Nov 26, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/11/17/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%8D%81%E4%B8%83%E6%97%A5/">
二〇二四年十一月十七日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
-
- Functional Reactive Programming in F#
-
- </a>
- </div>
-
- <span class="post-date">Sep 12, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/archives/page/9/index.html b/archives/page/9/index.html
index bf835f24..b8bb2a54 100644
--- a/archives/page/9/index.html
+++ b/archives/page/9/index.html
@@ -164,6 +164,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/12/Functional-Reactive-Programming-in-F/">
+
+ Functional Reactive Programming in F#
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 12, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/">
二〇二四年九月十二日
@@ -319,24 +337,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/07/01/OCaml-News-2024-4/">
-
- OCaml News 2024-4
-
- </a>
- </div>
-
- <span class="post-date">Jul 1, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/search.xml b/search.xml
index 7a1efd04..c9211e67 100644
--- a/search.xml
+++ b/search.xml
@@ -507,58 +507,6 @@ char sa_data[] socket address (variable-length data)</p>
</tags>
</entry>
<entry>
- <title>F# 重载解析问题</title>
- <url>/2025/03/30/F-%E9%87%8D%E8%BD%BD%E8%A7%A3%E6%9E%90%E9%97%AE%E9%A2%98/</url>
- <content><![CDATA[<p>当在 F# 中使用一些 C# 类库的时候,可能会遇到类似如下的问题:</p>
-<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">open</span> System</span><br><span class="line"><span class="keyword">open</span> System.Numerics</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> someFunction () <span class="operator">=</span></span><br><span class="line"> <span class="keyword">let</span> v<span class="operator">:</span> Vector<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span> <span class="operator">=</span> Vector(<span class="number">0</span>uy)</span><br><span class="line"> <span class="keyword">let</span> array<span class="operator">:</span> <span class="type">byte</span>[] <span class="operator">=</span> [<span class="operator">||</span>]</span><br><span class="line"> <span class="keyword">let</span> span<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span> <span class="operator">=</span> Span(array)</span><br><span class="line"> v.CopyTo(span)</span><br><span class="line">Compiler error</span><br><span class="line"> v.CopyTo(span)</span><br><span class="line"> <span class="operator">----^^^^^^^^^^^^^^</span></span><br><span class="line"></span><br><span class="line"><span class="operator">/</span>home<span class="operator">/</span>muqiu<span class="operator">/</span>stdin(<span class="number">99</span>,<span class="number">5</span>)<span class="operator">:</span> error FS0041<span class="operator">:</span> A unique overload <span class="keyword">for</span> method <span class="symbol">&#x27;CopyTo</span>&#x27; could <span class="built_in">not</span> be determined based on <span class="keyword">type</span> information prior <span class="keyword">to</span> this program point. A <span class="keyword">type</span> annotation may be needed.</span><br><span class="line"></span><br><span class="line">Known <span class="keyword">type</span> <span class="title class_">of</span> argument<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span></span><br><span class="line"></span><br><span class="line">Candidates<span class="operator">:</span></span><br><span class="line"> <span class="operator">-</span> Vector.CopyTo(destination<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span>) <span class="operator">:</span> <span class="type">unit</span></span><br><span class="line"> <span class="operator">-</span> Vector.CopyTo(destination<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span>) <span class="operator">:</span> <span class="type">unit</span></span><br></pre></td></tr></table></figure>
-<p>编译器认为存在两个相同的 <code>CopyTo</code> 重载无法区分。但查阅文档发现,<code>Vector&lt;T&gt;</code> 的 <code>CopyTo</code> 方法实际上只有一个匹配的重载(接受 <code>Span&lt;T&gt;</code>),这似乎矛盾。</p>
-<p>这是因为 F# 编译器处理泛型方法重载的方式:</p>
-<ul>
-<li>泛型接口继承:<code>Vector&lt;T&gt;</code> 可能实现了多个接口,导致编译器看到两个签名相同的 <code>CopyTo</code> 方法(例如通过不同接口继承)。</li>
-<li>语言设计差异:F# 缺乏 C# 的 “most concrete” 重载选择机制。当多个重载来自不同继承路径时,F# 不会自动选择最具体的实现,需要显式指引。</li>
-</ul>
-<p>仅我所知的一种解决方案是通过添加扩展方法显式指引编译器:</p>
-<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">type</span> <span class="title class_">Vector</span><span class="operator">&lt;</span><span class="symbol">&#x27;T</span><span class="operator">&gt;</span> <span class="keyword">with</span></span><br><span class="line"> <span class="keyword">member</span> <span class="keyword">inline</span> this.CopyToByteSpan (span <span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span>) <span class="operator">=</span> </span><br><span class="line"> this.CopyTo(span) <span class="comment">// 显式绑定具体重载</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用时使用新方法</span></span><br><span class="line">v.CopyToByteSpan(span)</span><br></pre></td></tr></table></figure>
-<p>这种方法通过创建具体的类型路径,帮助编译器绕过复杂的重载解析逻辑。</p>
-<p>学艺不精,不知道这是不是语言设计的差异,可能 F# 倾向于要求更明确的类型信息以避免意外行为?或许当泛型类型继承多个接口时,有没有可能出现在具体类型中不易察觉的隐式重载冲突?</p>
-<h2 id="Refs"><a class="header-anchor" href="#Refs">¶</a>Refs.</h2>
-<ul>
-<li><a href="https://github.com/fsharp/fslang-suggestions/issues/905">“Most concrete” tiebreaker for generic overloads #905</a></li>
-<li><a href="https://github.com/dotnet/fsharp/issues/1647">Fail to resolve to non generic overload. #1647</a></li>
-</ul>
-]]></content>
- <tags>
- <tag>Technique</tag>
- </tags>
- </entry>
- <entry>
- <title>FDA 仿制药流程</title>
- <url>/2025/11/29/FDA-%E4%BB%BF%E5%88%B6%E8%8D%AF%E6%B5%81%E7%A8%8B/</url>
- <content><![CDATA[<p>#药物研发</p>
-<p>在FDA监管的药物研发、临床试验和上市流程中,当一个已上市药物(通常指创新药,通过新药申请NDA获得批准)出现一种更低廉的制药方式,但其活性成分的分子式保持完全相同时,这种情况本质上涉及仿制药(generic drug)的开发或工艺优化申请,而非从零开始的全新药物研发。简单来说,不需要重新进行完整的临床试验(即I-III期的大规模人体试验),但必须通过简化的监管路径证明新制药方式生产的药物与原药在质量、安全性和疗效上等效。</p>
-<p>首先,理解核心前提:分子式完全相同意味着活性成分(active pharmaceutical ingredient, API)是相同的化学实体,例如从专利保护的原研药转向无专利保护的仿制药生产。这不同于生物制品(如单克隆抗体)的生物类似药,后者可能需要更多比较性临床试验。FDA将此类药物归类为“仿制药”,其审批路径是缩减新药申请(Abbreviated New Drug Application, ANDA),而非完整的NDA。ANDA的目的是避免重复证明已知的安全性和有效性数据,这些数据已在原药的NDA中确立<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>。</p>
-<p>FDA的《仿制药用户费用法案》(GDUFA)和相关指南明确规定,对于相同分子式的药物,新制药方式(如改进的合成路线、晶型优化或更高效的提取工艺)只需证明“生物等效性”(bioequivalence),而非全面临床试验。生物等效性研究通常包括:1)体外溶出测试(in vitro dissolution),评估药物在模拟生理条件下的释放速率;2)人体药代动力学研究(pharmacokinetic studies),在健康志愿者中比较新药与原药的吸收、分布、代谢和排泄曲线(如AUC和Cmax参数的90%置信区间在80%-125%内)。这些研究规模小,通常只需24-36名受试者,持续数周,而非数年<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。如果新工艺导致杂质谱或稳定性变化,FDA可能要求额外的数据,如加速稳定性测试或毒性评估,但仍无需重复疗效试验,除非有证据显示潜在差异(如新杂质超过许可阈值)<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>。</p>
-<p>在实际操作中,这一路径大大降低了成本和时间:ANDA审批平均需10-15个月,费用远低于NDA的数亿美元和数年周期。新制药方式的低廉性往往源于规模化生产或工艺创新,但FDA要求申请者提交化学、制造和控制(CMC)信息,证明新工艺符合良好生产规范(cGMP)。例如,阿司匹林或扑热息痛等经典药物,其多种仿制药版本均通过此路径上市,而无需重新验证其止痛或抗炎疗效<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup>。然而,如果新方式涉及重大变更(如从化学合成转为生物合成,尽管分子式相同),FDA可能视其为“混合型”申请,需要桥接研究来确认等效性。</p>
-<p>如果生物等效性未能证明(例如,新工艺导致生物利用度差异&gt;20%),申请将被拒,或需额外桥接试验,这可能增加延误和成本。不过上市后监测(post-marketing surveillance)仍适用,包括不良事件报告(FAERS系统),以捕捉任何罕见差异。</p>
-<hr class="footnotes-sep">
-<section class="footnotes">
-<ol class="footnotes-list">
-<li id="fn1" class="footnote-item"><p>U.S. Food and Drug Administration. (2023). <em>Frequently Asked Questions about Generic Drugs</em>. Retrieved from <a href="https://www.fda.gov/drugs/generic-drugs/frequently-asked-questions-about-generic-drugs">https://www.fda.gov/drugs/generic-drugs/frequently-asked-questions-about-generic-drugs</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
-</li>
-<li id="fn2" class="footnote-item"><p>U.S. Food and Drug Administration. (2019). <em>Bioequivalence Studies with Pharmacokinetic Endpoints for Drugs Submitted Under an ANDA</em>. Guidance for Industry. Retrieved from <a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/bioequivalence-studies-pharmacokinetic-endpoints-drugs-submitted-under-abbreviated-new-drug">https://www.fda.gov/regulatory-information/search-fda-guidance-documents/bioequivalence-studies-pharmacokinetic-endpoints-drugs-submitted-under-abbreviated-new-drug</a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
-</li>
-<li id="fn3" class="footnote-item"><p>U.S. Food and Drug Administration. (2020). <em>Changes to an Approved NDA or ANDA</em>. Guidance for Industry. Retrieved from <a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/changes-approved-nda-or-anda">https://www.fda.gov/regulatory-information/search-fda-guidance-documents/changes-approved-nda-or-anda</a> <a href="#fnref3" class="footnote-backref">↩︎</a></p>
-</li>
-<li id="fn4" class="footnote-item"><p>U.S. Food and Drug Administration. (2023). <em>Approved Drug Products with Therapeutic Equivalence Evaluations (Orange Book)</em>. Retrieved from <a href="https://www.fda.gov/drugs/drug-approvals-and-databases/approved-drug-products-therapeutic-equivalence-evaluations-orange-book">https://www.fda.gov/drugs/drug-approvals-and-databases/approved-drug-products-therapeutic-equivalence-evaluations-orange-book</a> <a href="#fnref4" class="footnote-backref">↩︎</a></p>
-</li>
-</ol>
-</section>
-]]></content>
- <tags>
- <tag>Medicine</tag>
- </tags>
- </entry>
- <entry>
<title>Dealing with complex dependency injection in FSharp</title>
<url>/2024/10/18/Dealing-with-complex-dependency-injection-in-FSharp/</url>
<content><![CDATA[<p>Today, we’re going to cover different ways of encapsulating capabilities and supplying them between functions using functional programming techniques which can be realized in F#.</p>
@@ -653,6 +601,58 @@ char sa_data[] socket address (variable-length data)</p>
</tags>
</entry>
<entry>
+ <title>F# 重载解析问题</title>
+ <url>/2025/03/30/F-%E9%87%8D%E8%BD%BD%E8%A7%A3%E6%9E%90%E9%97%AE%E9%A2%98/</url>
+ <content><![CDATA[<p>当在 F# 中使用一些 C# 类库的时候,可能会遇到类似如下的问题:</p>
+<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">open</span> System</span><br><span class="line"><span class="keyword">open</span> System.Numerics</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> someFunction () <span class="operator">=</span></span><br><span class="line"> <span class="keyword">let</span> v<span class="operator">:</span> Vector<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span> <span class="operator">=</span> Vector(<span class="number">0</span>uy)</span><br><span class="line"> <span class="keyword">let</span> array<span class="operator">:</span> <span class="type">byte</span>[] <span class="operator">=</span> [<span class="operator">||</span>]</span><br><span class="line"> <span class="keyword">let</span> span<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span> <span class="operator">=</span> Span(array)</span><br><span class="line"> v.CopyTo(span)</span><br><span class="line">Compiler error</span><br><span class="line"> v.CopyTo(span)</span><br><span class="line"> <span class="operator">----^^^^^^^^^^^^^^</span></span><br><span class="line"></span><br><span class="line"><span class="operator">/</span>home<span class="operator">/</span>muqiu<span class="operator">/</span>stdin(<span class="number">99</span>,<span class="number">5</span>)<span class="operator">:</span> error FS0041<span class="operator">:</span> A unique overload <span class="keyword">for</span> method <span class="symbol">&#x27;CopyTo</span>&#x27; could <span class="built_in">not</span> be determined based on <span class="keyword">type</span> information prior <span class="keyword">to</span> this program point. A <span class="keyword">type</span> annotation may be needed.</span><br><span class="line"></span><br><span class="line">Known <span class="keyword">type</span> <span class="title class_">of</span> argument<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span></span><br><span class="line"></span><br><span class="line">Candidates<span class="operator">:</span></span><br><span class="line"> <span class="operator">-</span> Vector.CopyTo(destination<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span>) <span class="operator">:</span> <span class="type">unit</span></span><br><span class="line"> <span class="operator">-</span> Vector.CopyTo(destination<span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span>) <span class="operator">:</span> <span class="type">unit</span></span><br></pre></td></tr></table></figure>
+<p>编译器认为存在两个相同的 <code>CopyTo</code> 重载无法区分。但查阅文档发现,<code>Vector&lt;T&gt;</code> 的 <code>CopyTo</code> 方法实际上只有一个匹配的重载(接受 <code>Span&lt;T&gt;</code>),这似乎矛盾。</p>
+<p>这是因为 F# 编译器处理泛型方法重载的方式:</p>
+<ul>
+<li>泛型接口继承:<code>Vector&lt;T&gt;</code> 可能实现了多个接口,导致编译器看到两个签名相同的 <code>CopyTo</code> 方法(例如通过不同接口继承)。</li>
+<li>语言设计差异:F# 缺乏 C# 的 “most concrete” 重载选择机制。当多个重载来自不同继承路径时,F# 不会自动选择最具体的实现,需要显式指引。</li>
+</ul>
+<p>仅我所知的一种解决方案是通过添加扩展方法显式指引编译器:</p>
+<figure class="highlight fsharp"><table><tr><td class="code"><pre><span class="line"><span class="keyword">type</span> <span class="title class_">Vector</span><span class="operator">&lt;</span><span class="symbol">&#x27;T</span><span class="operator">&gt;</span> <span class="keyword">with</span></span><br><span class="line"> <span class="keyword">member</span> <span class="keyword">inline</span> this.CopyToByteSpan (span <span class="operator">:</span> Span<span class="operator">&lt;</span><span class="type">byte</span><span class="operator">&gt;</span>) <span class="operator">=</span> </span><br><span class="line"> this.CopyTo(span) <span class="comment">// 显式绑定具体重载</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用时使用新方法</span></span><br><span class="line">v.CopyToByteSpan(span)</span><br></pre></td></tr></table></figure>
+<p>这种方法通过创建具体的类型路径,帮助编译器绕过复杂的重载解析逻辑。</p>
+<p>学艺不精,不知道这是不是语言设计的差异,可能 F# 倾向于要求更明确的类型信息以避免意外行为?或许当泛型类型继承多个接口时,有没有可能出现在具体类型中不易察觉的隐式重载冲突?</p>
+<h2 id="Refs"><a class="header-anchor" href="#Refs">¶</a>Refs.</h2>
+<ul>
+<li><a href="https://github.com/fsharp/fslang-suggestions/issues/905">“Most concrete” tiebreaker for generic overloads #905</a></li>
+<li><a href="https://github.com/dotnet/fsharp/issues/1647">Fail to resolve to non generic overload. #1647</a></li>
+</ul>
+]]></content>
+ <tags>
+ <tag>Technique</tag>
+ </tags>
+ </entry>
+ <entry>
+ <title>FDA 仿制药流程</title>
+ <url>/2025/11/29/FDA-%E4%BB%BF%E5%88%B6%E8%8D%AF%E6%B5%81%E7%A8%8B/</url>
+ <content><![CDATA[<p>#药物研发</p>
+<p>在FDA监管的药物研发、临床试验和上市流程中,当一个已上市药物(通常指创新药,通过新药申请NDA获得批准)出现一种更低廉的制药方式,但其活性成分的分子式保持完全相同时,这种情况本质上涉及仿制药(generic drug)的开发或工艺优化申请,而非从零开始的全新药物研发。简单来说,不需要重新进行完整的临床试验(即I-III期的大规模人体试验),但必须通过简化的监管路径证明新制药方式生产的药物与原药在质量、安全性和疗效上等效。</p>
+<p>首先,理解核心前提:分子式完全相同意味着活性成分(active pharmaceutical ingredient, API)是相同的化学实体,例如从专利保护的原研药转向无专利保护的仿制药生产。这不同于生物制品(如单克隆抗体)的生物类似药,后者可能需要更多比较性临床试验。FDA将此类药物归类为“仿制药”,其审批路径是缩减新药申请(Abbreviated New Drug Application, ANDA),而非完整的NDA。ANDA的目的是避免重复证明已知的安全性和有效性数据,这些数据已在原药的NDA中确立<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>。</p>
+<p>FDA的《仿制药用户费用法案》(GDUFA)和相关指南明确规定,对于相同分子式的药物,新制药方式(如改进的合成路线、晶型优化或更高效的提取工艺)只需证明“生物等效性”(bioequivalence),而非全面临床试验。生物等效性研究通常包括:1)体外溶出测试(in vitro dissolution),评估药物在模拟生理条件下的释放速率;2)人体药代动力学研究(pharmacokinetic studies),在健康志愿者中比较新药与原药的吸收、分布、代谢和排泄曲线(如AUC和Cmax参数的90%置信区间在80%-125%内)。这些研究规模小,通常只需24-36名受试者,持续数周,而非数年<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。如果新工艺导致杂质谱或稳定性变化,FDA可能要求额外的数据,如加速稳定性测试或毒性评估,但仍无需重复疗效试验,除非有证据显示潜在差异(如新杂质超过许可阈值)<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>。</p>
+<p>在实际操作中,这一路径大大降低了成本和时间:ANDA审批平均需10-15个月,费用远低于NDA的数亿美元和数年周期。新制药方式的低廉性往往源于规模化生产或工艺创新,但FDA要求申请者提交化学、制造和控制(CMC)信息,证明新工艺符合良好生产规范(cGMP)。例如,阿司匹林或扑热息痛等经典药物,其多种仿制药版本均通过此路径上市,而无需重新验证其止痛或抗炎疗效<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup>。然而,如果新方式涉及重大变更(如从化学合成转为生物合成,尽管分子式相同),FDA可能视其为“混合型”申请,需要桥接研究来确认等效性。</p>
+<p>如果生物等效性未能证明(例如,新工艺导致生物利用度差异&gt;20%),申请将被拒,或需额外桥接试验,这可能增加延误和成本。不过上市后监测(post-marketing surveillance)仍适用,包括不良事件报告(FAERS系统),以捕捉任何罕见差异。</p>
+<hr class="footnotes-sep">
+<section class="footnotes">
+<ol class="footnotes-list">
+<li id="fn1" class="footnote-item"><p>U.S. Food and Drug Administration. (2023). <em>Frequently Asked Questions about Generic Drugs</em>. Retrieved from <a href="https://www.fda.gov/drugs/generic-drugs/frequently-asked-questions-about-generic-drugs">https://www.fda.gov/drugs/generic-drugs/frequently-asked-questions-about-generic-drugs</a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn2" class="footnote-item"><p>U.S. Food and Drug Administration. (2019). <em>Bioequivalence Studies with Pharmacokinetic Endpoints for Drugs Submitted Under an ANDA</em>. Guidance for Industry. Retrieved from <a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/bioequivalence-studies-pharmacokinetic-endpoints-drugs-submitted-under-abbreviated-new-drug">https://www.fda.gov/regulatory-information/search-fda-guidance-documents/bioequivalence-studies-pharmacokinetic-endpoints-drugs-submitted-under-abbreviated-new-drug</a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn3" class="footnote-item"><p>U.S. Food and Drug Administration. (2020). <em>Changes to an Approved NDA or ANDA</em>. Guidance for Industry. Retrieved from <a href="https://www.fda.gov/regulatory-information/search-fda-guidance-documents/changes-approved-nda-or-anda">https://www.fda.gov/regulatory-information/search-fda-guidance-documents/changes-approved-nda-or-anda</a> <a href="#fnref3" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn4" class="footnote-item"><p>U.S. Food and Drug Administration. (2023). <em>Approved Drug Products with Therapeutic Equivalence Evaluations (Orange Book)</em>. Retrieved from <a href="https://www.fda.gov/drugs/drug-approvals-and-databases/approved-drug-products-therapeutic-equivalence-evaluations-orange-book">https://www.fda.gov/drugs/drug-approvals-and-databases/approved-drug-products-therapeutic-equivalence-evaluations-orange-book</a> <a href="#fnref4" class="footnote-backref">↩︎</a></p>
+</li>
+</ol>
+</section>
+]]></content>
+ <tags>
+ <tag>Medicine</tag>
+ </tags>
+ </entry>
+ <entry>
<title>FHIR 记录患者的用药记录</title>
<url>/2025/12/29/FHIR-%E8%AE%B0%E5%BD%95%E6%82%A3%E8%80%85%E7%9A%84%E7%94%A8%E8%8D%AF%E8%AE%B0%E5%BD%95/</url>
<content><![CDATA[<p>FHIR 中的“用药记录”并非一个单一概念,而是一个由不同角色、不同时间点和不同意图构成的连续工作流。</p>
@@ -838,21 +838,6 @@ Given the impracticality of prolonged hospitalizations and advancing technology
</tags>
</entry>
<entry>
- <title>什么是 G⁺</title>
- <url>/2025/10/19/Gram-stain/</url>
- <content><![CDATA[<p><strong>G⁺(Gram‑positive)</strong> 是细菌在 <strong>Gram 染色</strong>(Gram stain)技术下呈现的染色特征。Gram 染色是一种经典的显微镜染色方法,依据细菌细胞壁结构的差异,将细菌分为两大类:<strong>Gram‑positive(G⁺)</strong> 和 <strong>Gram‑negative(G⁻)</strong>。在染色程序中,细菌首先被结晶紫染料染色,随后加入碘液形成复合物,接着用酒精或丙酮脱色,最后用沙黄或复红复染。若细菌的细胞壁能够 <strong>保留结晶紫‑碘复合物</strong>,则在显微镜下呈现紫蓝色,这类细菌即被归类为 <strong>Gram‑positive(G⁺)</strong>;若细胞壁结构不保留复合物而被脱色,随后被沙黄染成红色,则为 <strong>Gram‑negative(G⁻)</strong>。</p>
-<p>G⁺ 细菌的细胞壁外层主要由 <strong>厚度约 20–80 nm 的肽聚糖(peptidoglycan)</strong> 组成,这层结构密集且富含交联的糖肽链,能够在脱色步骤中形成物理屏障,阻止酒精/丙酮的渗透,从而保留结晶紫‑碘复合物。</p>
-<p>与 G⁻ 细菌不同,G⁺ 细菌没有外膜(outer membrane)和脂多糖(LPS)层。外膜的缺失使得脱色剂难以进入细胞内部,进一步加强了紫色的保留。</p>
-<p>某些 G⁺ 细菌在细胞壁上表达的酶(如酸性磷酸酶)可与染料形成更为稳定的复合物,进一步提升染色的持久性。</p>
-<p>在呼吸道痰涂片中出现 <strong>“有荚膜的双球菌(capsulated diplococci)”</strong>,最典型的病原体是 <strong>肺炎链球菌(Streptococcus pneumoniae)</strong>。它是一种 <strong>革兰氏阳性(G⁺)</strong>、<strong>α‑hemolytic</strong>、<strong>嗜血清素</strong> 的双球菌,表面包裹有厚厚的多糖荚膜,正是该荚膜赋予它在显微镜下呈现明显的荧光或“胶状”外观。</p>
-<p>在痰涂片或血培养的显微镜检查中,观察到 G⁺ 双球菌提示肺炎链球菌感染的可能性较大,帮助临床医生在培养结果出来前就能启动经验性抗生素治疗(如 β‑lactam 类药物)。</p>
-<p>肺炎链球菌的荚膜多型性(&gt; 90 种血清型)是疫苗设计的核心依据,同时也影响抗体介导的吞噬作用。了解其 G⁺ 特性有助于解释为何某些血清型(如 3 型)在免疫逃逸方面更具优势。</p>
-]]></content>
- <tags>
- <tag>Medicine</tag>
- </tags>
- </entry>
- <entry>
<title>G-Machine</title>
<url>/2024/01/23/G-Machine/</url>
<content><![CDATA[<ul>
@@ -879,6 +864,21 @@ Given the impracticality of prolonged hospitalizations and advancing technology
</tags>
</entry>
<entry>
+ <title>什么是 G⁺</title>
+ <url>/2025/10/19/Gram-stain/</url>
+ <content><![CDATA[<p><strong>G⁺(Gram‑positive)</strong> 是细菌在 <strong>Gram 染色</strong>(Gram stain)技术下呈现的染色特征。Gram 染色是一种经典的显微镜染色方法,依据细菌细胞壁结构的差异,将细菌分为两大类:<strong>Gram‑positive(G⁺)</strong> 和 <strong>Gram‑negative(G⁻)</strong>。在染色程序中,细菌首先被结晶紫染料染色,随后加入碘液形成复合物,接着用酒精或丙酮脱色,最后用沙黄或复红复染。若细菌的细胞壁能够 <strong>保留结晶紫‑碘复合物</strong>,则在显微镜下呈现紫蓝色,这类细菌即被归类为 <strong>Gram‑positive(G⁺)</strong>;若细胞壁结构不保留复合物而被脱色,随后被沙黄染成红色,则为 <strong>Gram‑negative(G⁻)</strong>。</p>
+<p>G⁺ 细菌的细胞壁外层主要由 <strong>厚度约 20–80 nm 的肽聚糖(peptidoglycan)</strong> 组成,这层结构密集且富含交联的糖肽链,能够在脱色步骤中形成物理屏障,阻止酒精/丙酮的渗透,从而保留结晶紫‑碘复合物。</p>
+<p>与 G⁻ 细菌不同,G⁺ 细菌没有外膜(outer membrane)和脂多糖(LPS)层。外膜的缺失使得脱色剂难以进入细胞内部,进一步加强了紫色的保留。</p>
+<p>某些 G⁺ 细菌在细胞壁上表达的酶(如酸性磷酸酶)可与染料形成更为稳定的复合物,进一步提升染色的持久性。</p>
+<p>在呼吸道痰涂片中出现 <strong>“有荚膜的双球菌(capsulated diplococci)”</strong>,最典型的病原体是 <strong>肺炎链球菌(Streptococcus pneumoniae)</strong>。它是一种 <strong>革兰氏阳性(G⁺)</strong>、<strong>α‑hemolytic</strong>、<strong>嗜血清素</strong> 的双球菌,表面包裹有厚厚的多糖荚膜,正是该荚膜赋予它在显微镜下呈现明显的荧光或“胶状”外观。</p>
+<p>在痰涂片或血培养的显微镜检查中,观察到 G⁺ 双球菌提示肺炎链球菌感染的可能性较大,帮助临床医生在培养结果出来前就能启动经验性抗生素治疗(如 β‑lactam 类药物)。</p>
+<p>肺炎链球菌的荚膜多型性(&gt; 90 种血清型)是疫苗设计的核心依据,同时也影响抗体介导的吞噬作用。了解其 G⁺ 特性有助于解释为何某些血清型(如 3 型)在免疫逃逸方面更具优势。</p>
+]]></content>
+ <tags>
+ <tag>Medicine</tag>
+ </tags>
+ </entry>
+ <entry>
<title>多人协作系统中的实现策略 (CRDT,锁等实现方案)</title>
<url>/2025/05/08/Multiplayer-Collaborative-Systems-tips/</url>
<content><![CDATA[<p>最近碰到一块业务:在系统中可以存在多个用户同时对某个项目信息进行编辑,这种多人协作的场景挺有意思的,不过在我们的业务中,并不需要实时协作,只需要保证不会出错就行,话虽如此,但也可以探索一下实时协作的实现方案,防止老年痴呆。</p>
@@ -1102,6 +1102,40 @@ await prisma.$transaction(async tx =&gt; &#123;
</tags>
</entry>
<entry>
+ <title>OCaml Core.Int.pow 的实现</title>
+ <url>/2023/10/21/OCaml-Core-Int-pow-%E7%9A%84%E5%AE%9E%E7%8E%B0/</url>
+ <content><![CDATA[<p>Core内部直接引用的Base的实现, Base的实现在 <a href="https://github.com/janestreet/base/blob/494a0876168d24cda695cbb9a3d86ad8d1eb97d8/src/int_math.ml#L11-L18">src/int_math.ml</a> 中:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> int_pow base exponent =</span><br><span class="line"> <span class="keyword">if</span> exponent &lt; <span class="number">0</span> <span class="keyword">then</span> negative_exponent <span class="literal">()</span>;</span><br><span class="line"> <span class="keyword">if</span> abs base &gt; <span class="number">1</span></span><br><span class="line"> &amp;&amp; (exponent &gt; <span class="number">63</span></span><br><span class="line"> || abs base &gt; <span class="type">Pow_overflow_bounds</span>.int_positive_overflow_bounds.(exponent))</span><br><span class="line"> <span class="keyword">then</span> overflow <span class="literal">()</span>;</span><br><span class="line"> int_math_int_pow base exponent</span><br><span class="line">;;</span><br></pre></td></tr></table></figure>
+<p>其中 <code>int_math_int_pow()</code> 由 C 实现:</p>
+<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">external</span> int_math_int_pow : <span class="built_in">int</span> -&gt; <span class="built_in">int</span> -&gt; <span class="built_in">int</span> = <span class="string">&quot;Base_int_math_int_pow_stub&quot;</span> [@@noalloc]</span><br></pre></td></tr></table></figure>
+<p>其实现在 <a href="https://github.com/janestreet/base/blob/494a0876168d24cda695cbb9a3d86ad8d1eb97d8/src/int_math_stubs.c#L56-L92">src/int_math_stubs.c</a> 中:</p>
+<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">int64_t</span> <span class="title function_">int_pow</span><span class="params">(<span class="type">int64_t</span> base, <span class="type">int64_t</span> exponent)</span> &#123;</span><br><span class="line"> <span class="type">int64_t</span> ret = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int64_t</span> mul[<span class="number">4</span>];</span><br><span class="line"> mul[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> mul[<span class="number">1</span>] = base;</span><br><span class="line"> mul[<span class="number">3</span>] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (exponent != <span class="number">0</span>) &#123;</span><br><span class="line"> mul[<span class="number">1</span>] *= mul[<span class="number">3</span>];</span><br><span class="line"> mul[<span class="number">2</span>] = mul[<span class="number">1</span>] * mul[<span class="number">1</span>];</span><br><span class="line"> mul[<span class="number">3</span>] = mul[<span class="number">2</span>] * mul[<span class="number">1</span>];</span><br><span class="line"> ret *= mul[exponent &amp; <span class="number">3</span>];</span><br><span class="line"> exponent &gt;&gt;= <span class="number">2</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+<p>这是一个四分快速幂的实现,它是二分快速幂的一种变种。二分快速幂将指数分为两部分,然后递归地计算每一部分的结果。<br>
+而四分快速幂将指数分为四部分,然后递归地计算每一部分的结果。<br>
+这里通过将指数右移2位(相当于除以4)和使用位与操作来实现,进一步减少了乘法次数。</p>
+<p>主要步骤:</p>
+<ul>
+<li>初始化返回值ret为1,和一个包含4个元素的数组mul, mul[0]和mul[3]被初始化为1, mul[1]被初始化为基数</li>
+<li>当指数不为0时,执行循环, 在每次循环中,首先更新mul数组的值
+<blockquote>
+<p>mul[1]是基数和mul[3]的乘积,mul[2]是mul[1]的平方,mul[3]是mul[2]和基数的乘积</p>
+</blockquote>
+</li>
+<li>然后,将ret乘以mul数组中的一个元素, 这个元素的索引是指数和3的位与运算的结果
+<blockquote>
+<p>这样做的目的是为了选择正确的乘数,因为指数被分解为4的倍数</p>
+</blockquote>
+</li>
+<li>最后,将指数右移2位,相当于将指数除以4</li>
+<li>当指数变为0时,循环结束,返回ret</li>
+</ul>
+<p>这个实现的优点是它可以在对数时间内计算出幂运算,而且每次循环只需要4次乘法。这比标准的二分快速幂算法需要的乘法次数更少。</p>
+]]></content>
+ <tags>
+ <tag>Technique</tag>
+ </tags>
+ </entry>
+ <entry>
<title>OCaml News 2024-1</title>
<url>/2024/01/08/OCaml-News-2024-1/</url>
<content><![CDATA[<h2 id="News"><a class="header-anchor" href="#News">¶</a>News</h2>
@@ -1165,40 +1199,6 @@ await prisma.$transaction(async tx =&gt; &#123;
</tags>
</entry>
<entry>
- <title>OCaml Core.Int.pow 的实现</title>
- <url>/2023/10/21/OCaml-Core-Int-pow-%E7%9A%84%E5%AE%9E%E7%8E%B0/</url>
- <content><![CDATA[<p>Core内部直接引用的Base的实现, Base的实现在 <a href="https://github.com/janestreet/base/blob/494a0876168d24cda695cbb9a3d86ad8d1eb97d8/src/int_math.ml#L11-L18">src/int_math.ml</a> 中:</p>
-<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> int_pow base exponent =</span><br><span class="line"> <span class="keyword">if</span> exponent &lt; <span class="number">0</span> <span class="keyword">then</span> negative_exponent <span class="literal">()</span>;</span><br><span class="line"> <span class="keyword">if</span> abs base &gt; <span class="number">1</span></span><br><span class="line"> &amp;&amp; (exponent &gt; <span class="number">63</span></span><br><span class="line"> || abs base &gt; <span class="type">Pow_overflow_bounds</span>.int_positive_overflow_bounds.(exponent))</span><br><span class="line"> <span class="keyword">then</span> overflow <span class="literal">()</span>;</span><br><span class="line"> int_math_int_pow base exponent</span><br><span class="line">;;</span><br></pre></td></tr></table></figure>
-<p>其中 <code>int_math_int_pow()</code> 由 C 实现:</p>
-<figure class="highlight ocaml"><table><tr><td class="code"><pre><span class="line"><span class="keyword">external</span> int_math_int_pow : <span class="built_in">int</span> -&gt; <span class="built_in">int</span> -&gt; <span class="built_in">int</span> = <span class="string">&quot;Base_int_math_int_pow_stub&quot;</span> [@@noalloc]</span><br></pre></td></tr></table></figure>
-<p>其实现在 <a href="https://github.com/janestreet/base/blob/494a0876168d24cda695cbb9a3d86ad8d1eb97d8/src/int_math_stubs.c#L56-L92">src/int_math_stubs.c</a> 中:</p>
-<figure class="highlight c"><table><tr><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">int64_t</span> <span class="title function_">int_pow</span><span class="params">(<span class="type">int64_t</span> base, <span class="type">int64_t</span> exponent)</span> &#123;</span><br><span class="line"> <span class="type">int64_t</span> ret = <span class="number">1</span>;</span><br><span class="line"> <span class="type">int64_t</span> mul[<span class="number">4</span>];</span><br><span class="line"> mul[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> mul[<span class="number">1</span>] = base;</span><br><span class="line"> mul[<span class="number">3</span>] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (exponent != <span class="number">0</span>) &#123;</span><br><span class="line"> mul[<span class="number">1</span>] *= mul[<span class="number">3</span>];</span><br><span class="line"> mul[<span class="number">2</span>] = mul[<span class="number">1</span>] * mul[<span class="number">1</span>];</span><br><span class="line"> mul[<span class="number">3</span>] = mul[<span class="number">2</span>] * mul[<span class="number">1</span>];</span><br><span class="line"> ret *= mul[exponent &amp; <span class="number">3</span>];</span><br><span class="line"> exponent &gt;&gt;= <span class="number">2</span>;</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>这是一个四分快速幂的实现,它是二分快速幂的一种变种。二分快速幂将指数分为两部分,然后递归地计算每一部分的结果。<br>
-而四分快速幂将指数分为四部分,然后递归地计算每一部分的结果。<br>
-这里通过将指数右移2位(相当于除以4)和使用位与操作来实现,进一步减少了乘法次数。</p>
-<p>主要步骤:</p>
-<ul>
-<li>初始化返回值ret为1,和一个包含4个元素的数组mul, mul[0]和mul[3]被初始化为1, mul[1]被初始化为基数</li>
-<li>当指数不为0时,执行循环, 在每次循环中,首先更新mul数组的值
-<blockquote>
-<p>mul[1]是基数和mul[3]的乘积,mul[2]是mul[1]的平方,mul[3]是mul[2]和基数的乘积</p>
-</blockquote>
-</li>
-<li>然后,将ret乘以mul数组中的一个元素, 这个元素的索引是指数和3的位与运算的结果
-<blockquote>
-<p>这样做的目的是为了选择正确的乘数,因为指数被分解为4的倍数</p>
-</blockquote>
-</li>
-<li>最后,将指数右移2位,相当于将指数除以4</li>
-<li>当指数变为0时,循环结束,返回ret</li>
-</ul>
-<p>这个实现的优点是它可以在对数时间内计算出幂运算,而且每次循环只需要4次乘法。这比标准的二分快速幂算法需要的乘法次数更少。</p>
-]]></content>
- <tags>
- <tag>Technique</tag>
- </tags>
- </entry>
- <entry>
<title>OCaml News 2024-2</title>
<url>/2024/01/18/OCaml-News-2024-2/</url>
<content><![CDATA[<h2 id="News"><a class="header-anchor" href="#News">¶</a>News</h2>
@@ -2043,28 +2043,6 @@ await prisma.$transaction(async tx =&gt; &#123;
</tags>
</entry>
<entry>
- <title>Radiographic Absence of the Left Humeral Head</title>
- <url>/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/</url>
- <content><![CDATA[<p>A 67-year-old man with thoracolumbar scoliosis, poor mobility, and history of frequent falls presented to the emergency department with 2 months of left shoulder pain, stiffness and reduced range of motion, and numbness and paresthesias in his left upper extremity.</p>
-<p>Ten years prior to presentation, he underwent surgical decompression for syringomyelia.</p>
-<p>A magnetic resonance imaging (MRI) scan of his cervical and thoracic spine performed 2 years prior to presentation revealed a recurrent syrinx extending from Cl C1 to T11, which was not resected because it did not cause symptoms at that time.</p>
-<p>On physical examination, he had mild tenderness to palpation and reduced range of motion of the left shoulder with abduction and flexion limited to 120° (normal range of motion, 180°).</p>
-<p>The left scapular muscles were atrophic, and pain and temperature sensation were reduced in his proximal left arm, and dorsal aspect of his left shoulder.</p>
-<p>His complete blood cell count, serum glucose levels, C-reactive protein levels, and erythrocyte sedimentation rate were normal.</p>
-<p>Results of tests for rheumatoid factor and antinuclear antibody were negative.</p>
-<p>Left shoulder radiograph showed complete absence of the left humeral head and a well-demarcated smooth osseous margin of the proximal humerus with associated soft tissue swelling and periarticular calcification.</p>
-<p>A chest radiograph taken 2 years prior revealed a normal left shoulder joint. The patient was hospitalized for further evaluation and treatment.</p>
-<ul>
-<li><a href="/papers/Radiographic%20Absence%20of%20the%20Left%20Humeral%20Head.pdf">报告原档</a></li>
-</ul>
-<p>这里提到了一种罕见的进展性疾病, 叫Charcot肩, 是一种神经性关节病变,特点是关节迅速被破坏和相关软组织肿胀。患者通常表现为肩部逐渐增大的肿胀,可能伴有疼痛或无痛,肩部无力和活动范围减少。<br>
-大约80%的Charcot肩患者有脊髓空洞症, 表现为脊髓中的液体充满腔体</p>
-]]></content>
- <tags>
- <tag>Medicine</tag>
- </tags>
- </entry>
- <entry>
<title>Prisma 关系型数据库的 Self-relations</title>
<url>/2025/02/18/Prisma-%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E7%9A%84-Self-relations/</url>
<content><![CDATA[<blockquote>
@@ -2133,6 +2111,28 @@ A relation table (also sometimes called a <em>JOIN</em>, <em>link</em> or <em>pi
</tags>
</entry>
<entry>
+ <title>Radiographic Absence of the Left Humeral Head</title>
+ <url>/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/</url>
+ <content><![CDATA[<p>A 67-year-old man with thoracolumbar scoliosis, poor mobility, and history of frequent falls presented to the emergency department with 2 months of left shoulder pain, stiffness and reduced range of motion, and numbness and paresthesias in his left upper extremity.</p>
+<p>Ten years prior to presentation, he underwent surgical decompression for syringomyelia.</p>
+<p>A magnetic resonance imaging (MRI) scan of his cervical and thoracic spine performed 2 years prior to presentation revealed a recurrent syrinx extending from Cl C1 to T11, which was not resected because it did not cause symptoms at that time.</p>
+<p>On physical examination, he had mild tenderness to palpation and reduced range of motion of the left shoulder with abduction and flexion limited to 120° (normal range of motion, 180°).</p>
+<p>The left scapular muscles were atrophic, and pain and temperature sensation were reduced in his proximal left arm, and dorsal aspect of his left shoulder.</p>
+<p>His complete blood cell count, serum glucose levels, C-reactive protein levels, and erythrocyte sedimentation rate were normal.</p>
+<p>Results of tests for rheumatoid factor and antinuclear antibody were negative.</p>
+<p>Left shoulder radiograph showed complete absence of the left humeral head and a well-demarcated smooth osseous margin of the proximal humerus with associated soft tissue swelling and periarticular calcification.</p>
+<p>A chest radiograph taken 2 years prior revealed a normal left shoulder joint. The patient was hospitalized for further evaluation and treatment.</p>
+<ul>
+<li><a href="/papers/Radiographic%20Absence%20of%20the%20Left%20Humeral%20Head.pdf">报告原档</a></li>
+</ul>
+<p>这里提到了一种罕见的进展性疾病, 叫Charcot肩, 是一种神经性关节病变,特点是关节迅速被破坏和相关软组织肿胀。患者通常表现为肩部逐渐增大的肿胀,可能伴有疼痛或无痛,肩部无力和活动范围减少。<br>
+大约80%的Charcot肩患者有脊髓空洞症, 表现为脊髓中的液体充满腔体</p>
+]]></content>
+ <tags>
+ <tag>Medicine</tag>
+ </tags>
+ </entry>
+ <entry>
<title>Repository pattern in Typescript</title>
<url>/2025/02/19/Repository-pattern-in-Typescript/</url>
<content><![CDATA[<blockquote>
@@ -2275,22 +2275,6 @@ A relation table (also sometimes called a <em>JOIN</em>, <em>link</em> or <em>pi
</tags>
</entry>
<entry>
- <title>Rust 闭包 lifetime may not live long enough 问题</title>
- <url>/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/</url>
- <content><![CDATA[<p>代码:</p>
-<figure class="highlight rust"><table><tr><td class="code"><pre><span class="line">...</span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">handlers</span>(<span class="keyword">self</span>) <span class="punctuation">-&gt;</span> crate::server::request::Handlers &#123;</span><br><span class="line"> <span class="built_in">vec!</span>[(</span><br><span class="line"> <span class="string">&quot;/tree&quot;</span>,</span><br><span class="line"> routing::<span class="title function_ invoke__">get</span>(<span class="keyword">move</span> || <span class="keyword">async</span> &#123;</span><br><span class="line"> (</span><br><span class="line"> StatusCode::OK,</span><br><span class="line"> <span class="title function_ invoke__">Json</span>(json!(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().<span class="title function_ invoke__">tree</span>(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().root))),</span><br><span class="line"> )</span><br><span class="line"> &#125;),</span><br><span class="line"> )]</span><br><span class="line"> &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
-<p>编译错误:</p>
-<figure class="highlight text"><table><tr><td class="code"><pre><span class="line">error: lifetime may not live long enough</span><br><span class="line"> --&gt; src/storage/filesystem/mod.rs:45:34</span><br><span class="line"> |</span><br><span class="line">45 | routing::get(move || async &#123;</span><br><span class="line"> | __________________________-------_^</span><br><span class="line"> | | | |</span><br><span class="line"> | | | return type of closure `&#123;async block@src/storage/filesystem/mod.rs:45:34: 50:14&#125;` contains a lifetime `&#x27;2`</span><br><span class="line"> | | lifetime `&#x27;1` represents this closure&#x27;s body</span><br><span class="line">46 | | (</span><br><span class="line">47 | | StatusCode::OK,</span><br><span class="line">48 | | Json(json!(self.clone().tree(self.clone().root))),</span><br><span class="line">49 | | )</span><br><span class="line">50 | | &#125;),</span><br><span class="line"> | |_____________^ returning this value requires that `&#x27;1` must outlive `&#x27;2`</span><br><span class="line"> |</span><br><span class="line"> = note: closure implements `Fn`, so references to captured variables can&#x27;t escape the closure</span><br></pre></td></tr></table></figure>
-<p>这是因为 <code>handlers</code> 里面的闭包捕获了一个引用,并且尝试返回一个包含该引用的值导致的。</p>
-<p>细说就是:闭包内部使用了 <code>self.clone()</code> 来获取一个新的实例,然后在异步块中返回一个 JSON 对象,这个 JSON 对象依赖于 <code>self.tree()</code> 的结果。因为闭包捕获了 <code>self</code> 的引用,所以它必须保证 <code>self</code> 在闭包执行完毕后仍然有效。</p>
-<p>解决这个问题的思路是:确保闭包中的所有引用都在闭包执行完毕之前就不再被使用。<br>
-就是说,要将闭包的作用域限制在一个更短的生命周期内,或者使用其他方式来避免闭包捕获长期存在的引用:</p>
-<figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line">...</span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">handlers</span>(<span class="keyword">self</span>) <span class="punctuation">-&gt;</span> crate::server::request::Handlers &#123;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">tree</span> = json!(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().<span class="title function_ invoke__">tree</span>(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().root));</span><br><span class="line"> <span class="built_in">vec!</span>[(</span><br><span class="line"> <span class="string">&quot;/tree&quot;</span>,</span><br><span class="line"> routing::<span class="title function_ invoke__">get</span>(<span class="keyword">move</span> || <span class="keyword">async</span> &#123; (StatusCode::OK, <span class="title function_ invoke__">Json</span>(tree)) &#125;),</span><br><span class="line"> )]</span><br><span class="line"> &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>]]></content>
- <tags>
- <tag>Technique</tag>
- </tags>
- </entry>
- <entry>
<title>Rust 虚表布局规则介绍</title>
<url>/2023/05/01/Rust-%E8%99%9A%E8%A1%A8%E5%B8%83%E5%B1%80%E8%A7%84%E5%88%99%E4%BB%8B%E7%BB%8D/</url>
<content><![CDATA[<p>在 Rust 中,一个指向未知大小对象(!Sized)的引用或指针被实现为一个由两个 usize 大小的域构成的胖指针。这两个域中,其中一个域保存了被引用或被指向的对象的地址,另一个域保存了一个名为 metadata 的数据。对于 slice 的引用或指针来说,其 metadata 为 slice 的长度。对于 trait object 的引用或指针来说,其 metadata 为虚表(vtable)地址。与 C++ 虚表类似,Rust 虚表的存在使得诸多动态语言特性得以实现,例如动态派发(dynamic dispatch)、向上转换(upcasting)、向下转换(downcast)等。本文将对 Rust 中虚表的布局规则进行简要介绍,并在此过程中对 Rust 中若干动态特性的实现方法进行简要介绍。</p>
@@ -2337,6 +2321,22 @@ A relation table (also sometimes called a <em>JOIN</em>, <em>link</em> or <em>pi
</tags>
</entry>
<entry>
+ <title>Rust 闭包 lifetime may not live long enough 问题</title>
+ <url>/2023/05/24/Rust-%E9%97%AD%E5%8C%85-lifetime-may-not-live-long-enough-%E9%97%AE%E9%A2%98/</url>
+ <content><![CDATA[<p>代码:</p>
+<figure class="highlight rust"><table><tr><td class="code"><pre><span class="line">...</span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">handlers</span>(<span class="keyword">self</span>) <span class="punctuation">-&gt;</span> crate::server::request::Handlers &#123;</span><br><span class="line"> <span class="built_in">vec!</span>[(</span><br><span class="line"> <span class="string">&quot;/tree&quot;</span>,</span><br><span class="line"> routing::<span class="title function_ invoke__">get</span>(<span class="keyword">move</span> || <span class="keyword">async</span> &#123;</span><br><span class="line"> (</span><br><span class="line"> StatusCode::OK,</span><br><span class="line"> <span class="title function_ invoke__">Json</span>(json!(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().<span class="title function_ invoke__">tree</span>(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().root))),</span><br><span class="line"> )</span><br><span class="line"> &#125;),</span><br><span class="line"> )]</span><br><span class="line"> &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
+<p>编译错误:</p>
+<figure class="highlight text"><table><tr><td class="code"><pre><span class="line">error: lifetime may not live long enough</span><br><span class="line"> --&gt; src/storage/filesystem/mod.rs:45:34</span><br><span class="line"> |</span><br><span class="line">45 | routing::get(move || async &#123;</span><br><span class="line"> | __________________________-------_^</span><br><span class="line"> | | | |</span><br><span class="line"> | | | return type of closure `&#123;async block@src/storage/filesystem/mod.rs:45:34: 50:14&#125;` contains a lifetime `&#x27;2`</span><br><span class="line"> | | lifetime `&#x27;1` represents this closure&#x27;s body</span><br><span class="line">46 | | (</span><br><span class="line">47 | | StatusCode::OK,</span><br><span class="line">48 | | Json(json!(self.clone().tree(self.clone().root))),</span><br><span class="line">49 | | )</span><br><span class="line">50 | | &#125;),</span><br><span class="line"> | |_____________^ returning this value requires that `&#x27;1` must outlive `&#x27;2`</span><br><span class="line"> |</span><br><span class="line"> = note: closure implements `Fn`, so references to captured variables can&#x27;t escape the closure</span><br></pre></td></tr></table></figure>
+<p>这是因为 <code>handlers</code> 里面的闭包捕获了一个引用,并且尝试返回一个包含该引用的值导致的。</p>
+<p>细说就是:闭包内部使用了 <code>self.clone()</code> 来获取一个新的实例,然后在异步块中返回一个 JSON 对象,这个 JSON 对象依赖于 <code>self.tree()</code> 的结果。因为闭包捕获了 <code>self</code> 的引用,所以它必须保证 <code>self</code> 在闭包执行完毕后仍然有效。</p>
+<p>解决这个问题的思路是:确保闭包中的所有引用都在闭包执行完毕之前就不再被使用。<br>
+就是说,要将闭包的作用域限制在一个更短的生命周期内,或者使用其他方式来避免闭包捕获长期存在的引用:</p>
+<figure class="highlight rust"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line">...</span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">handlers</span>(<span class="keyword">self</span>) <span class="punctuation">-&gt;</span> crate::server::request::Handlers &#123;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">tree</span> = json!(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().<span class="title function_ invoke__">tree</span>(<span class="keyword">self</span>.<span class="title function_ invoke__">clone</span>().root));</span><br><span class="line"> <span class="built_in">vec!</span>[(</span><br><span class="line"> <span class="string">&quot;/tree&quot;</span>,</span><br><span class="line"> routing::<span class="title function_ invoke__">get</span>(<span class="keyword">move</span> || <span class="keyword">async</span> &#123; (StatusCode::OK, <span class="title function_ invoke__">Json</span>(tree)) &#125;),</span><br><span class="line"> )]</span><br><span class="line"> &#125;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>]]></content>
+ <tags>
+ <tag>Technique</tag>
+ </tags>
+ </entry>
+ <entry>
<title>Scala 3 (Capture Checking)</title>
<url>/2025/03/25/Scala-3-Capture-Checking/</url>
<content><![CDATA[<blockquote>
@@ -3267,58 +3267,6 @@ A relation table (also sometimes called a <em>JOIN</em>, <em>link</em> or <em>pi
</tags>
</entry>
<entry>
- <title>NestJS 中 enableImplicitConversion 与 @Transform 的冲突</title>
- <url>/2025/08/13/nestjs-enableImplicitConversion-and-transform/</url>
- <content><![CDATA[<p>在 NestJS 生态中,<code>class-validator</code> 和 <code>class-transformer</code> 这两个库提供了以声明式的方式对 DTO 进行验证和转换。然而在处理布尔值时,如果在全局验证管道或仅仅是在局部同时开启了 <code>enableImplicitConversion</code>,可能会引入一个极其隐蔽且违反直觉的 Bug:前端传过来的布尔值恒为 true。</p>
-<h2 id="一个简单的筛选功能"><a class="header-anchor" href="#一个简单的筛选功能">¶</a>一个简单的筛选功能</h2>
-<p>假设正在开发一个电子商务平台的 API,需要实现一个产品列表的筛选功能。希望能够根据产品是否有库存 (<code>hasStock</code>)、是否为特色产品 (<code>isFeatured</code>) 等布尔条件进行筛选。</p>
-<p>前端发出的请求 URL 可能如下所示: <code>/products?filter[hasStock]=true&amp;filter[isFeatured]=false</code></p>
-<p>在 NestJS 后端,首先会在 <code>main.ts</code> 中配置一个全局的 <code>ValidationPipe</code>,以自动处理 DTO 的验证和转换。为了方便,通常会启用 <code>enableImplicitConversion</code>,期望它能自动将 URL 查询参数中的字符串(如 <code>&quot;123&quot;</code>, <code>&quot;true&quot;</code>)转换为 DTO 中定义的类型(<code>number</code>, <code>boolean</code>):</p>
-<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// main.ts</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">ValidationPipe</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@nestjs/common&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">NestFactory</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@nestjs/core&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">AppModule</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;./app.module&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">bootstrap</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> app = <span class="keyword">await</span> <span class="title class_">NestFactory</span>.<span class="title function_">create</span>(<span class="title class_">AppModule</span>);</span><br><span class="line"></span><br><span class="line"> app.<span class="title function_">useGlobalPipes</span>(</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">ValidationPipe</span>(&#123;</span><br><span class="line"> <span class="attr">transform</span>: <span class="literal">true</span>, <span class="comment">// 启用转换</span></span><br><span class="line"> <span class="attr">whitelist</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">forbidNonWhitelisted</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">transformOptions</span>: &#123;</span><br><span class="line"> <span class="comment">// 启用基于 TypeScript 类型的隐式转换</span></span><br><span class="line"> <span class="attr">enableImplicitConversion</span>: <span class="literal">true</span>, </span><br><span class="line"> &#125;,</span><br><span class="line"> &#125;),</span><br><span class="line"> );</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// ... 其他配置</span></span><br><span class="line"> <span class="keyword">await</span> app.<span class="title function_">listen</span>(<span class="number">3000</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">bootstrap</span>();</span><br></pre></td></tr></table></figure>
-<p>接着,定义一个 <code>ProductFilterDto</code> 来接收这些筛选条件。</p>
-<p><strong>一个看似正确的 DTO 定义:</strong></p>
-<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// product-filter.dto.ts</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">IsBoolean</span>, <span class="title class_">IsOptional</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-validator&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductFilterDto</span> &#123;</span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">hasStock</span>?: <span class="built_in">boolean</span>;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">isFeatured</span>?: <span class="built_in">boolean</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在控制器中使用这个 DTO:</p>
-<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// products.controller.ts</span></span><br><span class="line"><span class="meta">@Controller</span>(<span class="string">&#x27;products&#x27;</span>)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductsController</span> &#123;</span><br><span class="line"> <span class="meta">@Get</span>()</span><br><span class="line"> <span class="title function_">find</span>(<span class="params"><span class="meta">@Query</span>(<span class="string">&#x27;filter&#x27;</span>) <span class="attr">filter</span>: <span class="title class_">ProductFilterDto</span></span>) &#123;</span><br><span class="line"> <span class="comment">// 期望 filter.isFeatured 的值为 boolean false</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(filter); </span><br><span class="line"> <span class="comment">// ... 业务逻辑</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当请求 <code>.../products?filter[isFeatured]=false</code> 到达时,本来期望在 <code>find</code> 方法中得到的 <code>filter.isFeatured</code> 的值是布尔类型的 <code>false</code>。然而,控制台输出的结果却令人意外:<code>&#123; isFeatured: true &#125;</code></p>
-<h2 id="问题剖析"><a class="header-anchor" href="#问题剖析">¶</a>问题剖析</h2>
-<p>这个问题的根源在于 <code>class-transformer</code> 内部的转换执行顺序,以及 JavaScript 中 <code>Boolean</code> 函数的类型转换行为。</p>
-<p>所有通过 URL 查询参数传递的值,其本质都是字符串。当 NestJS 接收到请求时,<code>filter.isFeatured</code> 的原始值是字符串 <code>&quot;false&quot;</code>。</p>
-<p><code>ValidationPipe</code> 启动 <code>class-transformer</code> 的转换流程。由于在全局管道中设置了 <code>enableImplicitConversion: true</code>,转换器会首先检查 DTO 属性的 TypeScript 类型。</p>
-<ol>
-<li><strong>隐式转换优先执行</strong>:<code>class-transformer</code> 看到 <code>ProductFilterDto</code> 中的 <code>isFeatured</code> 属性被声明为 <code>boolean</code> 类型。</li>
-<li><strong>错误的类型转换</strong>:它立即尝试将字符串 <code>&quot;false&quot;</code> 转换为布尔值。这个转换等同于执行 <code>Boolean(&quot;false&quot;)</code>。在 JavaScript 中,任何非空字符串(包括 <code>&quot;false&quot;</code>)通过 <code>Boolean()</code> 构造函数转换后都会得到 <code>true</code>。</li>
-<li><strong>结果覆盖</strong>:这个错误的 <code>true</code> 值被作为该属性的转换结果。</li>
-</ol>
-<p>此时,即使尝试添加一个自定义的 <code>@Transform</code> 装饰器来手动处理这个问题,也为时已晚。</p>
-<p>例如,定义一个 <code>booleanTransformer</code>:</p>
-<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// boolean-transformer.ts</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">booleanTransformer</span> = (<span class="params">&#123; value &#125;: &#123; value: <span class="built_in">any</span> &#125;</span>) =&gt; &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> value === <span class="string">&#x27;true&#x27;</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> value;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
-<p>然后更新 dto:</p>
-<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// product-filter.dto.ts (错误的尝试)</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Transform</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-transformer&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">IsBoolean</span>, <span class="title class_">IsOptional</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-validator&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; booleanTransformer &#125; <span class="keyword">from</span> <span class="string">&#x27;./boolean-transformer&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductFilterDto</span> &#123;</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@Transform</span>(booleanTransformer) <span class="comment">// 添加自定义转换</span></span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">isFeatured</span>?: <span class="built_in">boolean</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>流程会变成这样:</p>
-<ol>
-<li>隐式转换首先执行:<code>Boolean(&quot;false&quot;)</code> -&gt; <code>true</code>。</li>
-<li><code>@Transform</code> 装饰器执行:此时传递给 <code>booleanTransformer</code> 的 <code>value</code> 已经是上一步错误转换后的布尔值 <code>true</code>,而不是原始的字符串 <code>&quot;false&quot;</code>。转换函数无从下手。</li>
-</ol>
-<p>最终结果依然是 <code>true</code>。</p>
-<h2 id="解决方案:用-any-绕过隐式转换"><a class="header-anchor" href="#解决方案:用-any-绕过隐式转换">¶</a>## 解决方案:用 <code>any</code> 绕过隐式转换</h2>
-<p>要解决这个问题,核心在于阻止 <code>class-transformer</code> 进行那次错误的、优先的隐式转换,从而确保自定义 <code>@Transform</code> 函数能接收到最原始的字符串值。</p>
-<p>最直接且侵入性最小的方法,是将 DTO 中相关属性的 TypeScript 类型从 <code>boolean</code> 改为 <code>any</code>。</p>
-<p><strong>修正后的 DTO 定义:</strong></p>
-<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// product-filter.dto.ts (正确的实现)</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Transform</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-transformer&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">IsBoolean</span>, <span class="title class_">IsOptional</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-validator&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; booleanTransformer &#125; <span class="keyword">from</span> <span class="string">&#x27;./boolean-transformer&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 一个更健壮的 booleanTransformer</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">robustBooleanTransformer</span> = (<span class="params">&#123; value &#125;: &#123; value: <span class="built_in">string</span> &#125;</span>) =&gt;</span><br><span class="line"> value === <span class="string">&#x27;true&#x27;</span> ? <span class="literal">true</span> : value === <span class="string">&#x27;false&#x27;</span> ? <span class="literal">false</span> : value;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductFilterDto</span> &#123;</span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@Transform</span>(robustBooleanTransformer)</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">hasStock</span>?: <span class="built_in">any</span>; <span class="comment">// &lt;-- 类型从 boolean 改为 any</span></span><br><span class="line"></span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@Transform</span>(robustBooleanTransformer)</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">isFeatured</span>?: <span class="built_in">any</span>; <span class="comment">// &lt;-- 类型从 boolean 改为 any</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>这个改动虽然看起来放弃了 TypeScript 的类型检查,但在这个特定的场景下,它非常安全且有效。原因如下:</p>
-<ol>
-<li><strong>阻止隐式转换</strong>:当 <code>class-transformer</code> 看到属性类型是 <code>any</code> 时,它不知道该隐式转换成什么目标类型,因此会“跳过”这个属性的隐式转换步骤。</li>
-<li><strong><code>@Transform</code> 接管</strong>:如此一来,原始的字符串值(<code>&quot;true&quot;</code> 或 <code>&quot;false&quot;</code>)就能原封不动地传递给 <code>robustBooleanTransformer</code> 函数。该函数现在可以正确地将字符串转换为期望的布尔值。</li>
-<li><strong><code>@IsBoolean</code> 守门</strong>:在自定义转换完成后,<code>@IsBoolean()</code> 装饰器会进行最后的验证,确保存入 DTO 的最终值必须是 <code>true</code> 或 <code>false</code>。这保证了在业务逻辑中,该属性的类型是绝对安全的。</li>
-</ol>
-<p>好用,爱用。</p>
-]]></content>
- <tags>
- <tag>Technique</tag>
- </tags>
- </entry>
- <entry>
<title>NestJS bullmq 邮件发送业务中的小 tips</title>
<url>/2025/05/07/nestjs-bullmq-mail-business/</url>
<content><![CDATA[<p>在 BullMQ(以及它在 NestJS 里包装的 <code>@Processor</code>/<code>WorkerHost</code>)里,整个生命周期大致是这样的:</p>
@@ -3375,6 +3323,58 @@ A relation table (also sometimes called a <em>JOIN</em>, <em>link</em> or <em>pi
</tags>
</entry>
<entry>
+ <title>NestJS 中 enableImplicitConversion 与 @Transform 的冲突</title>
+ <url>/2025/08/13/nestjs-enableImplicitConversion-and-transform/</url>
+ <content><![CDATA[<p>在 NestJS 生态中,<code>class-validator</code> 和 <code>class-transformer</code> 这两个库提供了以声明式的方式对 DTO 进行验证和转换。然而在处理布尔值时,如果在全局验证管道或仅仅是在局部同时开启了 <code>enableImplicitConversion</code>,可能会引入一个极其隐蔽且违反直觉的 Bug:前端传过来的布尔值恒为 true。</p>
+<h2 id="一个简单的筛选功能"><a class="header-anchor" href="#一个简单的筛选功能">¶</a>一个简单的筛选功能</h2>
+<p>假设正在开发一个电子商务平台的 API,需要实现一个产品列表的筛选功能。希望能够根据产品是否有库存 (<code>hasStock</code>)、是否为特色产品 (<code>isFeatured</code>) 等布尔条件进行筛选。</p>
+<p>前端发出的请求 URL 可能如下所示: <code>/products?filter[hasStock]=true&amp;filter[isFeatured]=false</code></p>
+<p>在 NestJS 后端,首先会在 <code>main.ts</code> 中配置一个全局的 <code>ValidationPipe</code>,以自动处理 DTO 的验证和转换。为了方便,通常会启用 <code>enableImplicitConversion</code>,期望它能自动将 URL 查询参数中的字符串(如 <code>&quot;123&quot;</code>, <code>&quot;true&quot;</code>)转换为 DTO 中定义的类型(<code>number</code>, <code>boolean</code>):</p>
+<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// main.ts</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">ValidationPipe</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@nestjs/common&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">NestFactory</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;@nestjs/core&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">AppModule</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;./app.module&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">bootstrap</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> app = <span class="keyword">await</span> <span class="title class_">NestFactory</span>.<span class="title function_">create</span>(<span class="title class_">AppModule</span>);</span><br><span class="line"></span><br><span class="line"> app.<span class="title function_">useGlobalPipes</span>(</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">ValidationPipe</span>(&#123;</span><br><span class="line"> <span class="attr">transform</span>: <span class="literal">true</span>, <span class="comment">// 启用转换</span></span><br><span class="line"> <span class="attr">whitelist</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">forbidNonWhitelisted</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">transformOptions</span>: &#123;</span><br><span class="line"> <span class="comment">// 启用基于 TypeScript 类型的隐式转换</span></span><br><span class="line"> <span class="attr">enableImplicitConversion</span>: <span class="literal">true</span>, </span><br><span class="line"> &#125;,</span><br><span class="line"> &#125;),</span><br><span class="line"> );</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// ... 其他配置</span></span><br><span class="line"> <span class="keyword">await</span> app.<span class="title function_">listen</span>(<span class="number">3000</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">bootstrap</span>();</span><br></pre></td></tr></table></figure>
+<p>接着,定义一个 <code>ProductFilterDto</code> 来接收这些筛选条件。</p>
+<p><strong>一个看似正确的 DTO 定义:</strong></p>
+<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// product-filter.dto.ts</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">IsBoolean</span>, <span class="title class_">IsOptional</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-validator&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductFilterDto</span> &#123;</span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">hasStock</span>?: <span class="built_in">boolean</span>;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">isFeatured</span>?: <span class="built_in">boolean</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+<p>在控制器中使用这个 DTO:</p>
+<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// products.controller.ts</span></span><br><span class="line"><span class="meta">@Controller</span>(<span class="string">&#x27;products&#x27;</span>)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductsController</span> &#123;</span><br><span class="line"> <span class="meta">@Get</span>()</span><br><span class="line"> <span class="title function_">find</span>(<span class="params"><span class="meta">@Query</span>(<span class="string">&#x27;filter&#x27;</span>) <span class="attr">filter</span>: <span class="title class_">ProductFilterDto</span></span>) &#123;</span><br><span class="line"> <span class="comment">// 期望 filter.isFeatured 的值为 boolean false</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(filter); </span><br><span class="line"> <span class="comment">// ... 业务逻辑</span></span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+<p>当请求 <code>.../products?filter[isFeatured]=false</code> 到达时,本来期望在 <code>find</code> 方法中得到的 <code>filter.isFeatured</code> 的值是布尔类型的 <code>false</code>。然而,控制台输出的结果却令人意外:<code>&#123; isFeatured: true &#125;</code></p>
+<h2 id="问题剖析"><a class="header-anchor" href="#问题剖析">¶</a>问题剖析</h2>
+<p>这个问题的根源在于 <code>class-transformer</code> 内部的转换执行顺序,以及 JavaScript 中 <code>Boolean</code> 函数的类型转换行为。</p>
+<p>所有通过 URL 查询参数传递的值,其本质都是字符串。当 NestJS 接收到请求时,<code>filter.isFeatured</code> 的原始值是字符串 <code>&quot;false&quot;</code>。</p>
+<p><code>ValidationPipe</code> 启动 <code>class-transformer</code> 的转换流程。由于在全局管道中设置了 <code>enableImplicitConversion: true</code>,转换器会首先检查 DTO 属性的 TypeScript 类型。</p>
+<ol>
+<li><strong>隐式转换优先执行</strong>:<code>class-transformer</code> 看到 <code>ProductFilterDto</code> 中的 <code>isFeatured</code> 属性被声明为 <code>boolean</code> 类型。</li>
+<li><strong>错误的类型转换</strong>:它立即尝试将字符串 <code>&quot;false&quot;</code> 转换为布尔值。这个转换等同于执行 <code>Boolean(&quot;false&quot;)</code>。在 JavaScript 中,任何非空字符串(包括 <code>&quot;false&quot;</code>)通过 <code>Boolean()</code> 构造函数转换后都会得到 <code>true</code>。</li>
+<li><strong>结果覆盖</strong>:这个错误的 <code>true</code> 值被作为该属性的转换结果。</li>
+</ol>
+<p>此时,即使尝试添加一个自定义的 <code>@Transform</code> 装饰器来手动处理这个问题,也为时已晚。</p>
+<p>例如,定义一个 <code>booleanTransformer</code>:</p>
+<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// boolean-transformer.ts</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">booleanTransformer</span> = (<span class="params">&#123; value &#125;: &#123; value: <span class="built_in">any</span> &#125;</span>) =&gt; &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">&#x27;string&#x27;</span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> value === <span class="string">&#x27;true&#x27;</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> value;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
+<p>然后更新 dto:</p>
+<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// product-filter.dto.ts (错误的尝试)</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Transform</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-transformer&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">IsBoolean</span>, <span class="title class_">IsOptional</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-validator&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; booleanTransformer &#125; <span class="keyword">from</span> <span class="string">&#x27;./boolean-transformer&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductFilterDto</span> &#123;</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@Transform</span>(booleanTransformer) <span class="comment">// 添加自定义转换</span></span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">isFeatured</span>?: <span class="built_in">boolean</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+<p>流程会变成这样:</p>
+<ol>
+<li>隐式转换首先执行:<code>Boolean(&quot;false&quot;)</code> -&gt; <code>true</code>。</li>
+<li><code>@Transform</code> 装饰器执行:此时传递给 <code>booleanTransformer</code> 的 <code>value</code> 已经是上一步错误转换后的布尔值 <code>true</code>,而不是原始的字符串 <code>&quot;false&quot;</code>。转换函数无从下手。</li>
+</ol>
+<p>最终结果依然是 <code>true</code>。</p>
+<h2 id="解决方案:用-any-绕过隐式转换"><a class="header-anchor" href="#解决方案:用-any-绕过隐式转换">¶</a>## 解决方案:用 <code>any</code> 绕过隐式转换</h2>
+<p>要解决这个问题,核心在于阻止 <code>class-transformer</code> 进行那次错误的、优先的隐式转换,从而确保自定义 <code>@Transform</code> 函数能接收到最原始的字符串值。</p>
+<p>最直接且侵入性最小的方法,是将 DTO 中相关属性的 TypeScript 类型从 <code>boolean</code> 改为 <code>any</code>。</p>
+<p><strong>修正后的 DTO 定义:</strong></p>
+<figure class="highlight typescript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// product-filter.dto.ts (正确的实现)</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Transform</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-transformer&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">IsBoolean</span>, <span class="title class_">IsOptional</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;class-validator&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; booleanTransformer &#125; <span class="keyword">from</span> <span class="string">&#x27;./boolean-transformer&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 一个更健壮的 booleanTransformer</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">robustBooleanTransformer</span> = (<span class="params">&#123; value &#125;: &#123; value: <span class="built_in">string</span> &#125;</span>) =&gt;</span><br><span class="line"> value === <span class="string">&#x27;true&#x27;</span> ? <span class="literal">true</span> : value === <span class="string">&#x27;false&#x27;</span> ? <span class="literal">false</span> : value;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">ProductFilterDto</span> &#123;</span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@Transform</span>(robustBooleanTransformer)</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">hasStock</span>?: <span class="built_in">any</span>; <span class="comment">// &lt;-- 类型从 boolean 改为 any</span></span><br><span class="line"></span><br><span class="line"> <span class="meta">@IsOptional</span>()</span><br><span class="line"> <span class="meta">@Transform</span>(robustBooleanTransformer)</span><br><span class="line"> <span class="meta">@IsBoolean</span>()</span><br><span class="line"> <span class="attr">isFeatured</span>?: <span class="built_in">any</span>; <span class="comment">// &lt;-- 类型从 boolean 改为 any</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
+<p>这个改动虽然看起来放弃了 TypeScript 的类型检查,但在这个特定的场景下,它非常安全且有效。原因如下:</p>
+<ol>
+<li><strong>阻止隐式转换</strong>:当 <code>class-transformer</code> 看到属性类型是 <code>any</code> 时,它不知道该隐式转换成什么目标类型,因此会“跳过”这个属性的隐式转换步骤。</li>
+<li><strong><code>@Transform</code> 接管</strong>:如此一来,原始的字符串值(<code>&quot;true&quot;</code> 或 <code>&quot;false&quot;</code>)就能原封不动地传递给 <code>robustBooleanTransformer</code> 函数。该函数现在可以正确地将字符串转换为期望的布尔值。</li>
+<li><strong><code>@IsBoolean</code> 守门</strong>:在自定义转换完成后,<code>@IsBoolean()</code> 装饰器会进行最后的验证,确保存入 DTO 的最终值必须是 <code>true</code> 或 <code>false</code>。这保证了在业务逻辑中,该属性的类型是绝对安全的。</li>
+</ol>
+<p>好用,爱用。</p>
+]]></content>
+ <tags>
+ <tag>Technique</tag>
+ </tags>
+ </entry>
+ <entry>
<title>NestJS 嵌套查询参数解析错误分析与解决方案</title>
<url>/2025/07/29/nestjs-nested-object-dto/</url>
<content><![CDATA[<p>在开发 NestJS 应用程序时,一个常见的场景是根据复杂的条件筛选资源。当使用嵌套查询参数来表达这些条件时,例如通过 URL <code>http://localhost:3000/products/filter?filters[price][min]=100</code>,可能会意外地遇到 <code>property filters[price][min] should not exist</code> 错误。本文将深入剖析此问题背后的原因,并提供针对 Express 和 Fastify 两种底层框架的解决方案。</p>
@@ -3492,6 +3492,17 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</tags>
</entry>
<entry>
+ <title>shadow-cljs 怎么设置代理</title>
+ <url>/2024/04/03/shadow-cljs-proxy/</url>
+ <content><![CDATA[<p>The library pomegranate used for retrieving maven dependencies does not read <code>.m2/settings.xml</code>. You can however set the :proxy config either in <code>shadow-cljs.edn</code> directly or <code>~/.shadow-cljs/config.edn</code>.</p>
+<p>See <a href="https://github.com/cemerick/pomegranate/blob/master/src/main/clojure/cemerick/pomegranate/aether.clj#L757-L765">https://github.com/cemerick/pomegranate/blob/master/src/main/clojure/cemerick/pomegranate/aether.clj#L757-L765</a>.</p>
+<p><em>shadow-cljs.edn:</em></p>
+<figure class="highlight clojure"><table><tr><td class="code"><pre><span class="line">&#123;<span class="symbol">:source-paths</span> [<span class="string">&quot;src/main&quot;</span></span><br><span class="line"> <span class="string">&quot;src/test&quot;</span>]</span><br><span class="line"></span><br><span class="line"> <span class="symbol">:dependencies</span> [[reagent <span class="string">&quot;1.2.0&quot;</span>]</span><br><span class="line"> [re-frame <span class="string">&quot;1.3.0&quot;</span>]]</span><br><span class="line"></span><br><span class="line"> <span class="comment">;; Here</span></span><br><span class="line"> <span class="symbol">:proxy</span> &#123;<span class="symbol">:host</span> <span class="string">&quot;localhost&quot;</span></span><br><span class="line"> <span class="symbol">:port</span> <span class="number">20171</span>&#125;</span><br><span class="line"></span><br><span class="line"> <span class="symbol">:builds</span> &#123;<span class="symbol">:app</span> &#123;<span class="symbol">:target</span> <span class="symbol">:react-native</span></span><br><span class="line"> <span class="symbol">:init-fn</span> example.app/init</span><br><span class="line"> <span class="symbol">:output-dir</span> <span class="string">&quot;app&quot;</span></span><br><span class="line"> <span class="symbol">:compiler-options</span> &#123;<span class="symbol">:infer-externs</span> <span class="symbol">:auto</span>&#125;</span><br><span class="line"> <span class="symbol">:devtools</span> &#123;<span class="symbol">:autoload</span> <span class="literal">true</span>&#125;&#125;&#125;&#125;</span><br></pre></td></tr></table></figure>]]></content>
+ <tags>
+ <tag>Technique</tag>
+ </tags>
+ </entry>
+ <entry>
<title>表面活性剂</title>
<url>/2025/10/28/sufactants/</url>
<content><![CDATA[<p>表面活性剂(surfactants)是一种两亲性分子,具有亲水基团和疏水基团,能够在水和油脂界面上降低表面张力,从而广泛应用于消毒剂、洗涤剂和药物制剂中。它们对细菌和真菌的杀灭作用主要源于其对微生物细胞膜的破坏,这是一种非特异性物理化学机制,而非针对特定生化途径的靶向攻击。这种作用在临床消毒和感染控制中被广泛利用,尤其在处理皮肤或表面污染时。</p>
@@ -3507,17 +3518,6 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</tags>
</entry>
<entry>
- <title>shadow-cljs 怎么设置代理</title>
- <url>/2024/04/03/shadow-cljs-proxy/</url>
- <content><![CDATA[<p>The library pomegranate used for retrieving maven dependencies does not read <code>.m2/settings.xml</code>. You can however set the :proxy config either in <code>shadow-cljs.edn</code> directly or <code>~/.shadow-cljs/config.edn</code>.</p>
-<p>See <a href="https://github.com/cemerick/pomegranate/blob/master/src/main/clojure/cemerick/pomegranate/aether.clj#L757-L765">https://github.com/cemerick/pomegranate/blob/master/src/main/clojure/cemerick/pomegranate/aether.clj#L757-L765</a>.</p>
-<p><em>shadow-cljs.edn:</em></p>
-<figure class="highlight clojure"><table><tr><td class="code"><pre><span class="line">&#123;<span class="symbol">:source-paths</span> [<span class="string">&quot;src/main&quot;</span></span><br><span class="line"> <span class="string">&quot;src/test&quot;</span>]</span><br><span class="line"></span><br><span class="line"> <span class="symbol">:dependencies</span> [[reagent <span class="string">&quot;1.2.0&quot;</span>]</span><br><span class="line"> [re-frame <span class="string">&quot;1.3.0&quot;</span>]]</span><br><span class="line"></span><br><span class="line"> <span class="comment">;; Here</span></span><br><span class="line"> <span class="symbol">:proxy</span> &#123;<span class="symbol">:host</span> <span class="string">&quot;localhost&quot;</span></span><br><span class="line"> <span class="symbol">:port</span> <span class="number">20171</span>&#125;</span><br><span class="line"></span><br><span class="line"> <span class="symbol">:builds</span> &#123;<span class="symbol">:app</span> &#123;<span class="symbol">:target</span> <span class="symbol">:react-native</span></span><br><span class="line"> <span class="symbol">:init-fn</span> example.app/init</span><br><span class="line"> <span class="symbol">:output-dir</span> <span class="string">&quot;app&quot;</span></span><br><span class="line"> <span class="symbol">:compiler-options</span> &#123;<span class="symbol">:infer-externs</span> <span class="symbol">:auto</span>&#125;</span><br><span class="line"> <span class="symbol">:devtools</span> &#123;<span class="symbol">:autoload</span> <span class="literal">true</span>&#125;&#125;&#125;&#125;</span><br></pre></td></tr></table></figure>]]></content>
- <tags>
- <tag>Technique</tag>
- </tags>
- </entry>
- <entry>
<title>使用 Runed intersection observer 与 tanstack query 实现通用的惰性加载组件</title>
<url>/2025/07/31/svelte-lazyquery/</url>
<content><![CDATA[<p>在前端,一个常见的性能瓶颈是初始加载时请求了用户当前 viewpoint 之外的非必要数据。惰性加载(Lazy Loading)是一种关键策略,它将数据获取推迟到组件进入 viewpoint 时才执行。本文将阐述如何结合使用 Svelte 5、<code>@tanstack/svelte-query</code> 和 <code>runed.dev</code> 的 <code>useIntersectionObserver</code>,构建一个通用的、可复用的惰性加载组件。</p>
@@ -3740,18 +3740,6 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</tags>
</entry>
<entry>
- <title>二〇二三年八月一日</title>
- <url>/2023/08/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/</url>
- <content><![CDATA[<p>阳光给他病态一般白的皮肤注入了一些生机,左手手臂上斑驳的伤痕,每一道都诉诸着他对家人浓重的思念。那是在暗无天日的岁月里,他通过痛楚得到的慰藉。</p>
-<p>时光对谁都不温柔,愿意对我温柔的,只有身边陪我一起迎接时光洗礼的人。</p>
-<p>宇宙中也不会有什么声音, 视觉上再震撼的毁灭也只是发生在沉默之中。</p>
-<p>一切重新沉寂下来。</p>
-]]></content>
- <categories>
- <category>gallery</category>
- </categories>
- </entry>
- <entry>
<title>乙酰半脱氨酸的药理学与药代动力学特性</title>
<url>/2025/12/30/%E4%B9%99%E9%85%B0%E5%8D%8A%E8%84%B1%E6%B0%A8%E9%85%B8%E7%9A%84%E8%8D%AF%E7%90%86%E5%AD%A6%E4%B8%8E%E8%8D%AF%E4%BB%A3%E5%8A%A8%E5%8A%9B%E5%AD%A6%E7%89%B9%E6%80%A7/</url>
<content><![CDATA[<p>乙酰半胱氨酸的药理活性核心在于其分子中的游离巯基(-SH)。这一化学基团赋予其两项主要且机制迥异的临床应用:作为粘痰溶解剂和作为对乙酰氨基酚(扑热息痛)过量的特效解毒剂。</p>
@@ -3784,6 +3772,18 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</tags>
</entry>
<entry>
+ <title>二〇二三年八月一日</title>
+ <url>/2023/08/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/</url>
+ <content><![CDATA[<p>阳光给他病态一般白的皮肤注入了一些生机,左手手臂上斑驳的伤痕,每一道都诉诸着他对家人浓重的思念。那是在暗无天日的岁月里,他通过痛楚得到的慰藉。</p>
+<p>时光对谁都不温柔,愿意对我温柔的,只有身边陪我一起迎接时光洗礼的人。</p>
+<p>宇宙中也不会有什么声音, 视觉上再震撼的毁灭也只是发生在沉默之中。</p>
+<p>一切重新沉寂下来。</p>
+]]></content>
+ <categories>
+ <category>gallery</category>
+ </categories>
+ </entry>
+ <entry>
<title>二〇二三年六月二十九日</title>
<url>/2023/06/29/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B9%9D%E6%97%A5/</url>
<content><![CDATA[<p>我能走遍大街小巷,但我走不出时间,这里有太多东西网住我了,每一个不知所措的老人家,每一个满身泥土的农民,每一只嬉戏打闹的猫狗和每一寸土地下的家人。</p>
@@ -3876,18 +3876,6 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
- <title>二〇二五年二月二十四日</title>
- <url>/2025/02/24/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/</url>
- <content><![CDATA[<p>街上的人躲进建筑,道路上的车变得缓慢。路边的黑猫坐在屋檐下张望,在雨天,它也有了思考的地方与时间。除了淅淅沥沥的雨声再无其他。</p>
-<p>衣服买大了,他们走路好急,地铁上只有老人没看手机,天怎么黑那么快是我起晚了吗,那个蹦蹦跳跳的女孩耳机里在听什么歌,我还在原地吗,我要再等等吗。</p>
-<p>家就像厚酒之后突然明晰的想象,时间不语,只是沉默,我沉默地走进时间,看着我和你的年龄相差越来越小。</p>
-<p>这雨天,世界都温柔的可以掐出水来。</p>
-]]></content>
- <categories>
- <category>gallery</category>
- </categories>
- </entry>
- <entry>
<title>二〇二五年九月二十四日</title>
<url>/2025/09/24/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/</url>
<content><![CDATA[<p>从小到大,我好像一直是个独立的人。</p>
@@ -3936,6 +3924,18 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
+ <title>二〇二五年二月二十四日</title>
+ <url>/2025/02/24/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E5%9B%9B%E6%97%A5/</url>
+ <content><![CDATA[<p>街上的人躲进建筑,道路上的车变得缓慢。路边的黑猫坐在屋檐下张望,在雨天,它也有了思考的地方与时间。除了淅淅沥沥的雨声再无其他。</p>
+<p>衣服买大了,他们走路好急,地铁上只有老人没看手机,天怎么黑那么快是我起晚了吗,那个蹦蹦跳跳的女孩耳机里在听什么歌,我还在原地吗,我要再等等吗。</p>
+<p>家就像厚酒之后突然明晰的想象,时间不语,只是沉默,我沉默地走进时间,看着我和你的年龄相差越来越小。</p>
+<p>这雨天,世界都温柔的可以掐出水来。</p>
+]]></content>
+ <categories>
+ <category>gallery</category>
+ </categories>
+ </entry>
+ <entry>
<title>二〇二五年四月三日</title>
<url>/2025/04/03/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E4%BA%94%E6%9C%88%E4%B8%89%E6%97%A5/</url>
<content><![CDATA[<p>日历被一页页撕去,出钞口的暖风比任何毛毯更忠实,数字键盘的荧光就像圣徒光环般笼罩着我。</p>
@@ -4091,20 +4091,20 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
- <title>二〇二五年十月三十一日</title>
- <url>/2025/10/31/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E6%9C%88%E4%B8%89%E5%8D%81%E4%B8%80%E6%97%A5/</url>
- <content><![CDATA[<p>傍晚的海风带着盐的咸味和鱼网的腥气吹上岸。她独自站在礁石上眺望。巨大的海面起伏不定,深蓝的尽头与灰暗的天空交融成一个模糊的线。巨大的落日悬浮其上,像一颗即将坠入海面的橙红心脏。霞光将她的脸庞染成暖色。海风掀起她披在肩上的丝巾,丝巾像一面旗帜在身后猎猎作响。她深深吸了一口气,咸冷的空气涌入肺腑,带着一种辽阔的清醒。</p>
-<p>时间会带走了一个人,也带走了他的呼吸,他的声音,他掌心的温度。但似乎又留下了些什么</p>
-<p>光的颗粒在空气里浮动,在记忆里游走,她闭上眼睛,光从睫毛上滑过,像许多个早晨,像许多个傍晚,像她们再次相遇的无数个灿然的瞬间。她在其中走走停停,像一粒微尘,又像一颗星。</p>
+ <title>二〇二五年十二月十九日</title>
+ <url>/2025/12/19/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E5%8D%81%E4%B9%9D%E6%97%A5/</url>
+ <content><![CDATA[<p>一个尚未开始就已葬于山海的情欲,在无人知晓的深夜,完成了它短暂一生中最私密的绽放。</p>
]]></content>
<categories>
<category>gallery</category>
</categories>
</entry>
<entry>
- <title>二〇二五年十二月十九日</title>
- <url>/2025/12/19/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E5%8D%81%E4%B9%9D%E6%97%A5/</url>
- <content><![CDATA[<p>一个尚未开始就已葬于山海的情欲,在无人知晓的深夜,完成了它短暂一生中最私密的绽放。</p>
+ <title>二〇二五年十月三十一日</title>
+ <url>/2025/10/31/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%BA%94%E5%B9%B4%E5%8D%81%E6%9C%88%E4%B8%89%E5%8D%81%E4%B8%80%E6%97%A5/</url>
+ <content><![CDATA[<p>傍晚的海风带着盐的咸味和鱼网的腥气吹上岸。她独自站在礁石上眺望。巨大的海面起伏不定,深蓝的尽头与灰暗的天空交融成一个模糊的线。巨大的落日悬浮其上,像一颗即将坠入海面的橙红心脏。霞光将她的脸庞染成暖色。海风掀起她披在肩上的丝巾,丝巾像一面旗帜在身后猎猎作响。她深深吸了一口气,咸冷的空气涌入肺腑,带着一种辽阔的清醒。</p>
+<p>时间会带走了一个人,也带走了他的呼吸,他的声音,他掌心的温度。但似乎又留下了些什么</p>
+<p>光的颗粒在空气里浮动,在记忆里游走,她闭上眼睛,光从睫毛上滑过,像许多个早晨,像许多个傍晚,像她们再次相遇的无数个灿然的瞬间。她在其中走走停停,像一粒微尘,又像一颗星。</p>
]]></content>
<categories>
<category>gallery</category>
@@ -4271,18 +4271,18 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
- <title>二〇二四年九月十二日</title>
- <url>/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/</url>
- <content><![CDATA[<p>人只不过是一根苇草,是自然界最脆弱的东西,但却是一根能思想的苇草。用不着整个宇宙都拿起武器来才能毁灭人类,一口气、一滴水就足以致人类于死命了。然而纵使宇宙毁灭了人类,在人类的视角下自己却仍然要比致其于死命的东西高贵得多,因为人类知道自己要死亡,以及宇宙对其所具有的优势,还可以主动地认为宇宙对此一无所知。</p>
+ <title>二〇二四年九月一日</title>
+ <url>/2024/09/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%B8%80%E6%97%A5/</url>
+ <content><![CDATA[<p>通过忠实地映射宇宙来隐藏自我,是融入永恒的唯一途径。</p>
]]></content>
<categories>
<category>gallery</category>
</categories>
</entry>
<entry>
- <title>二〇二四年九月一日</title>
- <url>/2024/09/01/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E4%B8%80%E6%97%A5/</url>
- <content><![CDATA[<p>通过忠实地映射宇宙来隐藏自我,是融入永恒的唯一途径。</p>
+ <title>二〇二四年九月十二日</title>
+ <url>/2024/09/12/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%BA%8C%E6%97%A5/</url>
+ <content><![CDATA[<p>人只不过是一根苇草,是自然界最脆弱的东西,但却是一根能思想的苇草。用不着整个宇宙都拿起武器来才能毁灭人类,一口气、一滴水就足以致人类于死命了。然而纵使宇宙毁灭了人类,在人类的视角下自己却仍然要比致其于死命的东西高贵得多,因为人类知道自己要死亡,以及宇宙对其所具有的优势,还可以主动地认为宇宙对此一无所知。</p>
]]></content>
<categories>
<category>gallery</category>
@@ -4346,6 +4346,18 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
+ <title>二〇二四年八月一日</title>
+ <url>/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/</url>
+ <content><![CDATA[<p>阿公烧烟成老瘾,<br>
+阿公饮酒会面红,<br>
+他说日子要开心,<br>
+他说人生要尽兴。</p>
+]]></content>
+ <categories>
+ <category>gallery</category>
+ </categories>
+ </entry>
+ <entry>
<title>二〇二四年六月二十七日</title>
<url>/2024/06/27/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AD%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%83%E6%97%A5/</url>
<content><![CDATA[<p>钟摆晃荡 走出时间,<br>
@@ -4369,18 +4381,6 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
- <title>二〇二四年八月一日</title>
- <url>/2024/08/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%85%AB%E6%9C%88%E4%B8%80%E6%97%A5/</url>
- <content><![CDATA[<p>阿公烧烟成老瘾,<br>
-阿公饮酒会面红,<br>
-他说日子要开心,<br>
-他说人生要尽兴。</p>
-]]></content>
- <categories>
- <category>gallery</category>
- </categories>
- </entry>
- <entry>
<title>二〇二四年十一月十七日</title>
<url>/2024/11/17/%E4%BA%8C%E3%80%87%E4%BA%8C%E5%9B%9B%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E5%8D%81%E4%B8%83%E6%97%A5/</url>
<content><![CDATA[<p>伤春悲秋、离愁别绪太容易了,读几首诗词即可,但获取欢乐太难。</p>
@@ -4481,15 +4481,6 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
- <title>二零二三年二月一日</title>
- <url>/2023/02/01/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/</url>
- <content><![CDATA[<p>我想在六点和日出打招呼,我想去菜市场看看卖蔬菜的阿婆,我想花一上午去准备一餐中午饭,我想下午能在阳台捧着一盏热茶慢慢看书,再慢点,慢到能透过阳台栏杆的缝隙看看马路上车水马龙映衬下的老人家提着新鲜的一荤一素蹒跚走回家,看看贼几把大的夕阳在冒着热气的水杯中慢慢融化。</p>
-]]></content>
- <categories>
- <category>gallery</category>
- </categories>
- </entry>
- <entry>
<title>二零二三年九月十三日</title>
<url>/2023/09/13/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%B9%9D%E6%9C%88%E5%8D%81%E4%B8%89%E6%97%A5/</url>
<content><![CDATA[<p>“站好! 要拍了啊,倒数三秒,都不要眨眼。” 门口路过的陌生男人拿着相机,充当起了临时的摄影师。</p>
@@ -4503,6 +4494,15 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
+ <title>二零二三年二月一日</title>
+ <url>/2023/02/01/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%B8%80%E6%97%A5/</url>
+ <content><![CDATA[<p>我想在六点和日出打招呼,我想去菜市场看看卖蔬菜的阿婆,我想花一上午去准备一餐中午饭,我想下午能在阳台捧着一盏热茶慢慢看书,再慢点,慢到能透过阳台栏杆的缝隙看看马路上车水马龙映衬下的老人家提着新鲜的一荤一素蹒跚走回家,看看贼几把大的夕阳在冒着热气的水杯中慢慢融化。</p>
+]]></content>
+ <categories>
+ <category>gallery</category>
+ </categories>
+ </entry>
+ <entry>
<title>二零二三年二月二十二日</title>
<url>/2023/02/22/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%B8%89%E5%B9%B4%E4%BA%8C%E6%9C%88%E4%BA%8C%E5%8D%81%E4%BA%8C%E6%97%A5/</url>
<content><![CDATA[<p>这个小城市还有很多老人家,她们跟不上这个时代的脚步,要有人带她们跟上这个时代,再目送她们去下一个时代。</p>
@@ -4635,18 +4635,18 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</categories>
</entry>
<entry>
- <title>二零二二年十一月月三日</title>
- <url>/2022/11/03/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E6%9C%88%E4%B8%89%E6%97%A5/</url>
- <content><![CDATA[<p>我独自冒着冷风,去薄霜铺地的林子里,为听鸟语,为盼朝阳,为寻泥土里渐次苏醒的花草,但春信不至。我是如此单独而完整,在无数个夜晚,独自顶着冷风 伫立在老橘树下的桥头,只为听一曲夜莺的哀歌,倚暖了石栏上的青苔,青苔凉透了我的心坎,但夜莺不来,夜莺不来。</p>
+ <title>二零二二年八月二十一日</title>
+ <url>/2022/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/</url>
+ <content><![CDATA[<p>不管是什么样的生活,都只是为了让自己满意,我这样活着,没什么不满的,我很痛快。这世上所有东西,我留意它时,它就存在,不留意时,它就是虚无。幸运的是我留意的事物很少,不致于身心劳碌一生奔忙。岁月会锤炼我一副丰满的灵魂和清瘦的欲望。</p>
]]></content>
<categories>
<category>gallery</category>
</categories>
</entry>
<entry>
- <title>二零二二年八月二十一日</title>
- <url>/2022/08/21/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%85%AB%E6%9C%88%E4%BA%8C%E5%8D%81%E4%B8%80%E6%97%A5/</url>
- <content><![CDATA[<p>不管是什么样的生活,都只是为了让自己满意,我这样活着,没什么不满的,我很痛快。这世上所有东西,我留意它时,它就存在,不留意时,它就是虚无。幸运的是我留意的事物很少,不致于身心劳碌一生奔忙。岁月会锤炼我一副丰满的灵魂和清瘦的欲望。</p>
+ <title>二零二二年十一月月三日</title>
+ <url>/2022/11/03/%E4%BA%8C%E9%9B%B6%E4%BA%8C%E4%BA%8C%E5%B9%B4%E5%8D%81%E4%B8%80%E6%9C%88%E6%9C%88%E4%B8%89%E6%97%A5/</url>
+ <content><![CDATA[<p>我独自冒着冷风,去薄霜铺地的林子里,为听鸟语,为盼朝阳,为寻泥土里渐次苏醒的花草,但春信不至。我是如此单独而完整,在无数个夜晚,独自顶着冷风 伫立在老橘树下的桥头,只为听一曲夜莺的哀歌,倚暖了石栏上的青苔,青苔凉透了我的心坎,但夜莺不来,夜莺不来。</p>
]]></content>
<categories>
<category>gallery</category>
@@ -6213,6 +6213,69 @@ NestJS 依赖其底层 HTTP 适配器(默认为 Express)来解析传入的�
</tags>
</entry>
<entry>
+ <title>房颤心电图解析:从 P 波消失到不规则心室节律</title>
+ <url>/2026/08/20/%E6%88%BF%E9%A2%A4%E5%BF%83%E7%94%B5%E5%9B%BE%E8%A7%A3%E6%9E%90/</url>
+ <content><![CDATA[<p>房颤的心电图识别,主要依靠三个关系:<strong>P 波是否存在、R-R 间期是否规则、QRS 波群是否增宽</strong>。其中,P 波消失和心室节律绝对不规则最支持房颤;QRS 波群的宽窄则帮助判断心室内传导情况,但不能单独用来判断患者是否安全。</p>
+<h2 id="先看一条标准心电图"><a class="header-anchor" href="#先看一条标准心电图">¶</a>先看一条标准心电图</h2>
+<p>临床诊断房颤需要记录到典型心律,再由医生结合病史确认。2024 年欧洲房颤指南把房颤诊断、卒中预防、症状控制和危险因素管理放在同一个长期管理框架中<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>。</p>
+<p>一张常规十二导联心电图首先观察三件事:有没有规律出现的 P 波;相邻 QRS 波群之间的 R-R 间期是否长短不一;QRS 波群是否增宽。三个特征需要一起判断。单独看到心率快、一次 R-R 间期变化,或者某个导联中的 P 波不清楚,都不足以完成房颤诊断。</p>
+<h2 id="第一处:P-波消失,基线出现细小波动"><a class="header-anchor" href="#第一处:P-波消失,基线出现细小波动">¶</a>第一处:P 波消失,基线出现细小波动</h2>
+<p>窦性心律中,心房由窦房结发出有序电活动。每次心室激动前,心电图通常可以看到一个形态相对稳定的 P 波。P 波代表心房去极化,随后电活动经过房室结传向心室,形成 QRS 波群。</p>
+<p>房颤时,心房电活动快速而无序,不能形成一次有效的整体收缩。心电图上常见的表现是找不到持续、规则、形态稳定的 P 波,QRS 波群之间的基线出现细小而不规则的波动。不同导联中的基线波动清晰度可能不同,肌肉震颤和电极接触不良也可能制造类似干扰。</p>
+<p>因此,“没有看到 P 波”不能机械地等同于房颤。需要把纸速、导联、基线质量和 R-R 间期一起纳入判断。</p>
+<h2 id="第二处:R-R-间期绝对不规则"><a class="header-anchor" href="#第二处:R-R-间期绝对不规则">¶</a>第二处:R-R 间期绝对不规则</h2>
+<p>房颤的另一个核心特征是心室节律不规则。由于房室结接收到的心房冲动没有固定规律,传到心室的冲动间隔会发生变化,表现为 R-R 间期长短不一,而且通常不存在可重复的规律。</p>
+<p>这和呼吸性窦性心律不齐不同。后者的 R-R 间期变化往往与呼吸周期有关,仍然可以找到规律的 P 波。房性早搏、室性早搏、房扑伴不规则传导和部分多源性房性心动过速,也可能造成节律不齐,需要结合完整心电图鉴别。</p>
+<p>心率是平均值,不能代替节律判断。一次记录显示 116 次/分,只能说明这段记录中的平均心室率偏快;它不能单独证明房颤,也不能单独判断症状严重程度。</p>
+<h2 id="第三处:QRS-波群窄,不等于房颤风险低"><a class="header-anchor" href="#第三处:QRS-波群窄,不等于房颤风险低">¶</a>第三处:QRS 波群窄,不等于房颤风险低</h2>
+<p>QRS 波群反映心室去极化。若 QRS 时限相对较窄,通常说明这次心室激动主要沿正常或接近正常的传导路径下传;若 QRS 明显增宽,则需要考虑束支传导阻滞、室内传导延迟、预激或室性心律等情况。</p>
+<p>房颤可以伴窄 QRS,也可以伴宽 QRS。快速房颤伴原有束支阻滞、差异性传导或预激时,QRS 可能增宽。因此,窄 QRS 只能说明当前记录中的室内传导没有明显增宽,不能推出“不会发生心脏骤停”,也不能替代对卒中、心衰和基础心脏病的评估。</p>
+<h2 id="交互示意:把三处观察点分开看"><a class="header-anchor" href="#交互示意:把三处观察点分开看">¶</a>交互示意:把三处观察点分开看</h2>
+<p>下面的图是教学示意,不是任何患者原始心电图的逐点重建。点击按钮后,可以分别突出 P 波、R-R 间期和 QRS 波群。</p>
+<div class="ecg-demo" data-ecg-demo>
+<style>
+.ecg-demo{--ink:#1c1917;--muted:#78716c;--paper:#faf8f5;--grid:rgba(210,190,174,.42);--red:#dc2626;--blue:#2563eb;--green:#15803d;margin:2rem 0;padding:1rem;background:var(--paper);border:2px solid var(--ink);box-shadow:5px 5px 0 var(--ink);color:var(--ink);overflow:hidden}.ecg-demo *{box-sizing:border-box}.ecg-demo h3{margin:0;font-size:1rem}.ecg-demo p{margin:.35rem 0 0;color:var(--muted);font-size:.8rem;line-height:1.65}.ecg-demo-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.75rem;border-bottom:1px solid #d6d3d1;padding-bottom:.7rem}.ecg-demo-badge{padding:.2rem .45rem;border:1px solid var(--red);color:var(--red);font:700 .7rem/1.2 monospace;transform:rotate(-1deg)}.ecg-demo-controls{display:flex;flex-wrap:wrap;gap:.45rem;margin:.8rem 0}.ecg-demo button{cursor:pointer;padding:.38rem .58rem;border:1px solid #a8a29e;background:#fff;color:var(--ink);font:700 .72rem/1.2 monospace}.ecg-demo button:hover,.ecg-demo button[data-active=true]{border-color:var(--ink);background:var(--ink);color:#fff}.ecg-demo-canvas{overflow-x:auto;padding:.55rem;border:1px solid #78716c;background-color:#fffdfb;background-image:linear-gradient(to right,var(--grid) 1px,transparent 1px),linear-gradient(to bottom,var(--grid) 1px,transparent 1px);background-size:10px 10px}.ecg-demo-canvas svg{display:block;width:100%;min-width:620px;height:auto}.ecg-demo-note{margin-top:.7rem;padding:.65rem .75rem;border-left:4px solid var(--blue);background:#eff6ff;color:#1e3a8a;font-size:.82rem;line-height:1.7}.ecg-demo-legend{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin-top:.75rem;font:.7rem/1.5 monospace}.ecg-demo-legend span{padding:.35rem;background:#fff;border:1px solid #d6d3d1}.ecg-demo .layer{transition:opacity .22s ease}@media(max-width:640px){.ecg-demo-head{display:block}.ecg-demo-badge{display:inline-block;margin-top:.55rem}.ecg-demo-legend{grid-template-columns:1fr}}
+</style>
+<div class="ecg-demo-head"><div><h3>交互示意:窦性心律与房颤的三个观察点</h3><p>教学示意|不代表任何患者的原始心电图</p></div><span class="ecg-demo-badge">ECG SKETCH</span></div>
+<div class="ecg-demo-controls" role="group" aria-label="选择心电图观察点"><button type="button" data-focus="all" data-active="true">总览</button><button type="button" data-focus="pwave">P 波 / f 波</button><button type="button" data-focus="rr">R-R 间期</button><button type="button" data-focus="qrs">QRS 波群</button></div>
+<div class="ecg-demo-canvas"><svg viewBox="0 0 760 250" role="img" aria-label="窦性心律与房颤心电图示意"><text x="10" y="20" fill="#15803d" font-size="14" font-family="monospace" font-weight="700">窦性心律</text><text x="10" y="137" fill="#dc2626" font-size="14" font-family="monospace" font-weight="700">房颤示意</text><path d="M90 55 Q102 43 114 55 L126 55 L130 22 L136 82 L142 50 L148 55 Q160 43 172 55 L205 55 Q217 43 229 55 L241 55 L245 22 L251 82 L257 50 L263 55 Q275 43 287 55 L320 55 Q332 43 344 55 L356 55 L360 22 L366 82 L372 50 L378 55 Q390 43 402 55 L435 55 Q447 43 459 55 L471 55 L475 22 L481 82 L487 50 L493 55 Q505 43 517 55" fill="none" stroke="#15803d" stroke-width="2.4" stroke-linecap="round"/><text x="91" y="98" fill="#15803d" font-size="11" font-family="monospace">P 波规则出现</text><line x1="130" y1="32" x2="245" y2="32" stroke="#15803d" stroke-dasharray="3 3"/><line x1="245" y1="32" x2="360" y2="32" stroke="#15803d" stroke-dasharray="3 3"/><text x="300" y="28" fill="#15803d" font-size="10" font-family="monospace">R-R 间期规则</text><path d="M90 174 Q100 169 108 177 T124 172 T140 176 T155 171 L168 175 L172 142 L178 207 L184 168 L190 175 Q202 170 214 178 T232 171 T250 177 T268 170 T286 176 L300 175 L304 142 L310 207 L316 168 L322 175 Q333 169 344 178 T360 171 T377 177 T396 170 T415 176 T434 171 L448 175 L452 142 L458 207 L464 168 L470 175 Q483 170 498 178 T518 171 T536 177 T553 170 T570 176 L585 175 L589 142 L595 207 L601 168 L607 175 Q620 170 636 178 T655 171 T673 176" fill="none" stroke="#dc2626" stroke-width="2.4" stroke-linecap="round"/><rect class="layer" data-layer="pwave" x="195" y="161" width="105" height="27" fill="#fee2e2" stroke="#dc2626" stroke-dasharray="3 2"/><text class="layer" data-layer="pwave" x="247" y="205" text-anchor="middle" fill="#dc2626" font-size="10" font-family="monospace" font-weight="700">P 波消失,基线细小波动</text><line class="layer" data-layer="rr" x1="172" y1="130" x2="304" y2="130" stroke="#b45309" stroke-dasharray="3 3"/><line class="layer" data-layer="rr" x1="304" y1="130" x2="452" y2="130" stroke="#2563eb" stroke-dasharray="3 3"/><text class="layer" data-layer="rr" x="365" y="125" text-anchor="middle" fill="#2563eb" font-size="10" font-family="monospace" font-weight="700">R-R 间期长短不一</text><rect class="layer" data-layer="qrs" x="448" y="139" width="28" height="74" fill="#dcfce7" stroke="#15803d"/><text class="layer" data-layer="qrs" x="465" y="229" text-anchor="middle" fill="#15803d" font-size="10" font-family="monospace" font-weight="700">QRS</text></svg></div>
+<div class="ecg-demo-note" data-explain>总览:房颤示意中可以同时观察 P 波缺失、R-R 间期不规则和 QRS 波群形态。三者需要结合判断。</div><div class="ecg-demo-legend"><span style="color:#dc2626">红色:房颤示意</span><span style="color:#15803d">绿色:窦性心律或相对窄的 QRS</span><span style="color:#2563eb">蓝色:节律间期标注</span></div>
+<script>
+(function(){var root=document.querySelector('[data-ecg-demo]');if(!root)return;var explain=root.querySelector('[data-explain]');var texts={all:'总览:房颤示意中可以同时观察 P 波缺失、R-R 间期不规则和 QRS 波群形态。三者需要结合判断。',pwave:'P 波 / f 波:窦性心律通常有规则 P 波;房颤时找不到持续、规则的 P 波,基线可能出现细小而不规则的波动。',rr:'R-R 间期:房颤常表现为心室节律绝对不规则。仅有一次间期变化,不能单独完成房颤诊断。',qrs:'QRS 波群:图中绿色框只是标出相对窄的 QRS。窄 QRS 不等于整体风险低,也不能单独排除其他心律问题。'};var layers={pwave:root.querySelectorAll('[data-layer=pwave]'),rr:root.querySelectorAll('[data-layer=rr]'),qrs:root.querySelectorAll('[data-layer=qrs]')};function focus(mode){Object.keys(layers).forEach(function(key){layers[key].forEach(function(node){node.style.opacity=mode==='all'||mode===key?'1':'.12';});});root.querySelectorAll('[data-focus]').forEach(function(button){button.dataset.active=button.dataset.focus===mode?'true':'false';});explain.textContent=texts[mode];}root.querySelectorAll('[data-focus]').forEach(function(button){button.addEventListener('click',function(){focus(button.dataset.focus);});});focus('all');}());
+</script>
+</div>
+<h2 id="房颤和房扑不能混为一谈"><a class="header-anchor" href="#房颤和房扑不能混为一谈">¶</a>房颤和房扑不能混为一谈</h2>
+<p>房扑也可能造成心房活动异常和心室节律不齐,但其心房电活动常呈现较规则的锯齿样扑动波,尤其在下壁导联中更容易观察到。房颤的基线活动通常更加无序,R-R 间期也更不规则。不过,真实心电图可能受到心率、房室传导比例、药物、导联质量和合并心律失常影响,不能只凭一小段波形截图下结论。</p>
+<h2 id="手表提示“可能房颤”,下一步做什么"><a class="header-anchor" href="#手表提示“可能房颤”,下一步做什么">¶</a>手表提示“可能房颤”,下一步做什么</h2>
+<p>智能手表和手环可以帮助发现异常节律,但“设备提示”与“临床确诊”不是同一件事。Apple Heart Study 纳入 419,297 名参与者;研究结果显示,设备提示具有筛查价值,但提示本身不等于确诊<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。</p>
+<p>具有单导联心电图功能的设备,能够提供比单纯脉搏波更接近心电信号的记录。研究显示,单导联设备在部分心律识别任务中有帮助,但对不同类型的室上性心动过速,判读准确度仍低于标准十二导联心电图<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>。</p>
+<p>如果设备反复提示可能存在房颤,应保存原始记录,记录发生时间、持续时间和伴随症状,并到心内科接受标准心电图或动态心电图评估。不要依据手表提示自行开始抗凝,也不要因为一次“未发现房颤”就认为以后不会发生房颤。</p>
+<h2 id="房颤心电图之后,还要评估什么"><a class="header-anchor" href="#房颤心电图之后,还要评估什么">¶</a>房颤心电图之后,还要评估什么</h2>
+<p>心电图回答的是“这段时间有没有记录到怎样的心律”。它不能单独回答患者长期卒中风险、出血风险、心脏结构和诱发因素。</p>
+<p>确诊或高度怀疑房颤后,医生还需要结合年龄、既往卒中或短暂性脑缺血发作、高血压、糖尿病、心力衰竭、血管疾病、肾功能、贫血、甲状腺功能和用药情况,判断后续检查与治疗方向。抗凝、控制心率、节律控制和危险因素管理需要放在同一套决策中,不能只盯着心率数字。</p>
+<p>如果同时出现单侧肢体无力、口角歪斜、言语含糊、突发视物异常、持续胸痛、晕厥或严重呼吸困难,应立即急诊处理。即使症状很快缓解,也不能排除短暂性脑缺血发作或其他急症。</p>
+<h2 id="结语"><a class="header-anchor" href="#结语">¶</a>结语</h2>
+<p>房颤心电图的识别可以从三个问题开始:<strong>有没有规则 P 波,R-R 间期是否绝对不规则,QRS 波群是否增宽</strong>。最有价值的判断来自这些特征的组合,而不是某一个数字或某一个设备提示。</p>
+<p>心电图确认的是当时记录到的电活动。患者是否需要抗凝、控制心率、恢复节律或进一步检查,还要结合卒中风险、出血风险、心脏结构和基础疾病综合决定。</p>
+<hr>
+<h2 id="参考文献"><a class="header-anchor" href="#参考文献">¶</a>参考文献</h2>
+<hr class="footnotes-sep">
+<section class="footnotes">
+<ol class="footnotes-list">
+<li id="fn1" class="footnote-item"><p>Van Gelder IC, et al. 2024 ESC Guidelines for the management of atrial fibrillation developed in collaboration with the EACTS. <em>European Heart Journal</em>. 2024;45(36):3314-3414. PMID: <a href="https://pubmed.ncbi.nlm.nih.gov/39210723/">39210723</a>. DOI: <a href="https://doi.org/10.1093/eurheartj/ehae176">10.1093/eurheartj/ehae176</a>. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn2" class="footnote-item"><p>Perez MV, et al. Large-Scale Assessment of a Smartwatch to Identify Atrial Fibrillation. <em>New England Journal of Medicine</em>. 2019;381:1909-1917. PMID: <a href="https://pubmed.ncbi.nlm.nih.gov/31722151/">31722151</a>. DOI: <a href="https://doi.org/10.1056/NEJMoa1901183">10.1056/NEJMoa1901183</a>. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
+</li>
+<li id="fn3" class="footnote-item"><p>Vukadinovic D, et al. Diagnostic accuracy of Apple Watch Series 6 recorded single-lead ECGs for identifying supraventricular tachyarrhythmias: a comparative analysis with invasive electrophysiological study. <em>Europace</em>. 2024. PMID: <a href="https://pubmed.ncbi.nlm.nih.gov/37985539/">37985539</a>. <a href="#fnref3" class="footnote-backref">↩︎</a></p>
+</li>
+</ol>
+</section>
+]]></content>
+ <tags>
+ <tag>Medicine</tag>
+ </tags>
+ </entry>
+ <entry>
<title>替米沙坦</title>
<url>/2023/03/13/%E6%9B%BF%E7%B1%B3%E6%B2%99%E5%9D%A6/</url>
<content><![CDATA[<h2 id="名称"><a class="header-anchor" href="#名称">¶</a>名称</h2>
diff --git a/tags/Medicine/index.html b/tags/Medicine/index.html
index 20a95949..8d6d94a2 100644
--- a/tags/Medicine/index.html
+++ b/tags/Medicine/index.html
@@ -171,6 +171,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2026/08/20/%E6%88%BF%E9%A2%A4%E5%BF%83%E7%94%B5%E5%9B%BE%E8%A7%A3%E6%9E%90/">
+
+ 房颤心电图解析:从 P 波消失到不规则心室节律
+
+ </a>
+ </div>
+
+ <span class="post-date">Aug 20, 2026</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2026/08/18/%E6%88%BF%E9%A2%A4%E4%B8%8E%E8%A1%80%E6%A0%93%E6%A0%93%E5%A1%9E%EF%BC%9A%E4%BB%8E%E5%B7%A6%E5%BF%83%E8%80%B3%E8%A1%80%E6%B5%81%E6%B7%A4%E6%BB%9E%E5%88%B0%E7%BC%BA%E8%A1%80%E6%80%A7%E5%8D%92%E4%B8%AD/">
房颤与血栓栓塞:从左心耳血流淤滞到缺血性卒中
@@ -328,24 +346,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2025/11/29/FDA-%E4%BB%BF%E5%88%B6%E8%8D%AF%E6%B5%81%E7%A8%8B/">
-
- FDA 仿制药流程
-
- </a>
- </div>
-
- <span class="post-date">Nov 29, 2025</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Medicine/page/2/index.html b/tags/Medicine/page/2/index.html
index 02b5845a..4de337f6 100644
--- a/tags/Medicine/page/2/index.html
+++ b/tags/Medicine/page/2/index.html
@@ -171,6 +171,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2025/11/29/FDA-%E4%BB%BF%E5%88%B6%E8%8D%AF%E6%B5%81%E7%A8%8B/">
+
+ FDA 仿制药流程
+
+ </a>
+ </div>
+
+ <span class="post-date">Nov 29, 2025</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2025/10/29/%E5%BA%93%E6%AC%A3%E7%BB%BC%E5%90%88%E5%BE%81/">
库欣综合征
@@ -328,24 +346,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
-
- 肩周炎和肩袖损伤的区别
-
- </a>
- </div>
-
- <span class="post-date">Sep 15, 2024</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Medicine/page/3/index.html b/tags/Medicine/page/3/index.html
index 33c0dd41..d06e2326 100644
--- a/tags/Medicine/page/3/index.html
+++ b/tags/Medicine/page/3/index.html
@@ -171,6 +171,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2024/09/15/%E8%82%A9%E5%91%A8%E7%82%8E%E5%92%8C%E8%82%A9%E8%A2%96%E6%8D%9F%E4%BC%A4%E7%9A%84%E5%8C%BA%E5%88%AB/">
+
+ 肩周炎和肩袖损伤的区别
+
+ </a>
+ </div>
+
+ <span class="post-date">Sep 15, 2024</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2024/09/01/%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E6%B0%B4%E5%92%8C%E8%97%BF%E9%A6%99%E6%AD%A3%E6%B0%94%E5%8F%A3%E6%9C%8D%E6%B6%B2%E7%9A%84%E5%8C%BA%E5%88%AB/">
藿香正气水和藿香正气口服液的区别
@@ -328,24 +346,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/">
-
- Radiographic Absence of the Left Humeral Head
-
- </a>
- </div>
-
- <span class="post-date">Oct 25, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Medicine/page/4/index.html b/tags/Medicine/page/4/index.html
index cbb51060..adc37ff9 100644
--- a/tags/Medicine/page/4/index.html
+++ b/tags/Medicine/page/4/index.html
@@ -171,6 +171,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/10/25/Radiographic-Absence-of-the-Left-Humeral-Head/">
+
+ Radiographic Absence of the Left Humeral Head
+
+ </a>
+ </div>
+
+ <span class="post-date">Oct 25, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/10/25/%E8%82%BA%E7%82%8E%E6%94%AF%E5%8E%9F%E4%BD%93%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/">
肺炎支原体注意事项
@@ -326,24 +344,6 @@
</div>
-
-
-
-
-
- <div class="post-list-item">
- <div class="post-title">
- <a href="/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/">
-
- 奥司他韦
-
- </a>
- </div>
-
- <span class="post-date">Mar 5, 2023</span>
- </div>
-
-
<div id="paginator">
<div class=paginator>
diff --git a/tags/Medicine/page/5/index.html b/tags/Medicine/page/5/index.html
index 4249adfd..61717831 100644
--- a/tags/Medicine/page/5/index.html
+++ b/tags/Medicine/page/5/index.html
@@ -171,6 +171,24 @@
<div class="post-list-item">
<div class="post-title">
+ <a href="/2023/03/05/%E5%A5%A5%E5%8F%B8%E4%BB%96%E9%9F%A6/">
+
+ 奥司他韦
+
+ </a>
+ </div>
+
+ <span class="post-date">Mar 5, 2023</span>
+ </div>
+
+
+
+
+
+
+
+ <div class="post-list-item">
+ <div class="post-title">
<a href="/2023/03/04/%E9%87%91%E5%8C%AE%E8%A6%81%E7%95%A5/">
金匮要略