
简介基于JavaScript与微信小程序开发的稳态血药浓度计算器源码包面向医疗信息化开发者、药学专业学生及小程序初学者解决药物治疗中稳态血药浓度快速计算的问题。用户输入给药剂量、用药间隔、清除速率等参数即可得到计算结果项目附带原理说明与公式文档。压缩包共22个文件涵盖8个JSON配置、5个JS逻辑、4个WXSS样式、3个WXML页面模板及说明文档包体仅1.02MB目录模块划分直观便于独立学习与二次开发。该小程序示例完整展示了微信小程序从配置、逻辑到界面的实现链路并涉及医疗数据展示与计算场景适合作为课程设计、毕业设计或医疗类应用开发的参考。目前已有346人学习代码结构简洁能够帮助开发者快速上手小程序医疗工具类项目。1. 把稳态血药浓度算明白一套能跑的微信小程序计算器临床药师最怕被问的问题之一是“上次吃半片这次吃一片浓度是不是就翻倍了”。答案不是。剂量翻倍稳态浓度不一定等比例翻倍因为稳态浓度同时受给药间隔、清除率和分布容积三个变量牵制口服药物还要乘一个生物利用度。手算容易错翻书找公式又慢这时候一个能装进口袋的计算器就有价值了。这套基于JavaScript实现的微信小程序源码把稳态血药浓度的平均稳态浓度、峰浓度、谷浓度计算封装成了可交互页面输入剂量、间隔、清除率等参数就能出结果。适合临床药学背景的开发者二次开发也适合想研究微信小程序表单、数据绑定和本地计算逻辑的前端工程师拿来当实例。2. 源码结构拆解23个文件在小程序里各管什么拿到upload.zip解压之后第一件事不是改代码而是先把目录结构读明白。这个小程序包含23个文件8个JSON配置、5个JavaScript脚本、4个WXSS样式、3个Markdown文档、3个WXML模板。文件数量不多但层级关系清晰完全符合微信小程序“页面 配置 工具”的标准组织方式。2.1 从顶层目录看小程序的工程骨架解压后的工程结构大致是这样的upload.zip ├── app.json # 全局配置页面注册、窗口样式 ├── app.js # 小程序入口逻辑 ├── app.wxss # 全局样式表 ├── project.config.json # 开发者工具项目配置 ├── project.private.config.json # 个人本地配置不提交版本库 ├── sitemap.json # 微信搜索索引配置 ├── package-lock.json # npm 依赖锁文件本项目未实际依赖第三方包 ├── pages │ ├── vdDescribe # 药物说明页 │ │ ├── vdDescribe.js │ │ ├── vdDescribe.json │ │ ├── vdDescribe.wxml │ │ └── vdDescribe.wxss │ ├── cssCalculator # 核心计算页 │ │ ├── cssCalculator.js │ │ ├── cssCalculator.json │ │ ├── cssCalculator.wxml │ │ └── cssCalculator.wxss │ └── principle # 原理文档页 │ ├── principle.js │ ├── principle.json │ ├── principle.wxml │ └── principle.wxss ├── utils │ └── util.js # 工具函数 ├── 稳态血药浓度计算公式.md # 公式参考文档 └── readme.txt # 使用说明每个页面都由.js、.wxml、.wxss、.json四个文件组成这是微信小程序页面的固定四件套。.json管页面配置.wxml管结构.wxss管样式.js管逻辑和数据绑定。把这三组页面拆开看vdDescribe是信息展示页cssCalculator是核心交互页principle是理论说明页三者构成了一条“先看原理、再算数据、后读说明”的完整路径。2.2 全局配置文件怎么读先看app.json这是小程序的全局配置入口决定哪些页面被注册、窗口长什么样。常见配置如下{ pages: [ pages/cssCalculator/cssCalculator, pages/principle/principle, pages/vdDescribe/vdDescribe ], window: { navigationBarBackgroundColor: #2b6cb0, navigationBarTitleText: 稳态血药浓度计算器, navigationBarTextStyle: white, backgroundColor: #f5f7fa }, sitemapLocation: sitemap.json }这里pages数组的第一项是启动页。我一般会把核心计算器页放在第一位这样用户打开小程序直接进入工具而不是先看说明文档。window里的导航栏样式配置统一了顶部栏外观navigationBarTitleText会直接显示在微信导航栏上。sitemap.json决定页面是否被微信索引医疗类工具通常建议关掉或配置为不允许索引避免暴露功能细节。2.3 project.config.json 和私有配置要注意什么project.config.json是开发者工具的项目配置包含 appid、项目名称、编译设置等。你自己导入源码后第一步就是把appid换成自己的测试号或正式号否则预览和上传都会报错。project.private.config.json是开发者本地私有配置通常包含个人的编译条件、场景值等默认不被 git 跟踪我见到不少团队把这个文件误提交到仓库导致队友导入项目时编译入口被改掉。如果你用 git 管理这个项目建议把project.private.config.json加进.gitignore。3. 从药代动力学公式到 JavaScript 实现这套小程序的核心不是页面而是后台那段计算逻辑。稳态血药浓度不是拍脑袋定的它来源于单室模型多次给药后的药代动力学推导。项目自带的稳态血药浓度计算公式.md文档已经把公式列清楚了落地成 JavaScript 需要先理解公式的含义和边界。3.1 三个关键浓度各是什么稳态血药浓度不是单一数值通常要算三个平均稳态浓度、稳态峰浓度、稳态谷浓度。连续等剂量等间隔给药后体内药量会在每个给药周期内反复波动但波动曲线不再整体上升达到动态平衡这就是稳态。平均稳态浓度公式为Css_avg (F × D) / (CL × τ)其中 F 为生物利用度D 为单次给药剂量CL 为药物清除率τ 为给药间隔。这个式子算出来的是整个给药周期内的平均浓度不是中位数也不是算术平均而是 AUC 除以给药间隔。峰浓度和谷浓度需要引入消除速率常数 ke 和分布容积 VdCss_max (F × D) / (Vd × (1 - e^(-ke×τ))) Css_min Css_max × e^(-ke×τ)其中 ke CL / Vd。稳态峰浓度出现在给药后吸收完成瞬间谷浓度出现在下次给药前。两个值之间的差值反映血药浓度波动幅度差值越大说明药物在体内浓度忽高忽低不良反应风险也越高。3.2 计算脚本的 JavaScript 实现cssCalculator.js中对应的核心计算函数通常长这样function calcSteadyState(params) { const { dose, // 单次给药剂量单位 mg interval, // 给药间隔单位 h clearance, // 清除率 CL单位 L/h volume, // 分布容积 Vd单位 L bioavail // 生物利用度 F范围 0~1 } params; // 参数校验分母为零时直接返回错误 if (!dose || dose 0) return { error: 剂量必须大于 0 }; if (!interval || interval 0) return { error: 给药间隔必须大于 0 }; if (!clearance || clearance 0) return { error: 清除率必须大于 0 }; if (!volume || volume 0) return { error: 分布容积必须大于 0 }; const F bioavail bioavail 0 bioavail 1 ? bioavail : 1; const ke clearance / volume; // 消除速率常数单位 1/h const term Math.exp(-ke * interval); // e^(-ke·τ)用于波动计算 const cssAvg (F * dose) / (clearance * interval); const cssMax (F * dose) / (volume * (1 - term)); const cssMin cssMax * term; // isFinite 防 NaN / Infinity 结果进入页面 if (!isFinite(cssAvg) || !isFinite(cssMax) || !isFinite(cssMin)) { return { error: 计算结果超出有效范围请检查参数 }; } return { cssAvg: cssAvg.toFixed(4), cssMax: cssMax.toFixed(4), cssMin: cssMin.toFixed(4) }; } module.exports { calcSteadyState };这段代码做了三层防护。第一层是数值校验剂量、间隔、清除率、分布容积任何一个为负或为零都直接返回错误对象避免分母为零。第二层是生物利用度兜底经口给药的 F 在 0 到 1 之间静脉给药 F 等于 1代码在用户不传该参数时默认按 1 处理即标准静脉给药场景。第三层是isFinite检查JavaScript 中Infinity和NaN都能通过 typeof 检查但在 UI 上显示会很难看这里统一拦截。Math.exp(-ke * interval)是这段计算里最容易出错的地方。ke的单位是 1/hinterval单位是小时两者相乘后指数项无量纲才能放进指数函数。如果用户输入的清除率单位是 mL/min 而不是 L/h算出来的 ke 会差 60 倍峰浓度结果完全不可信。所以输入端的单位标注要写清楚。3.3 参数单位与结果单位要统一单位换算是这个项目里最常见的坑。下表是我在这个场景下给出的单位和输入建议参数推荐单位输入示例备注剂量 Dmg250固体口服剂型按 mg注射液也可能用 mg给药间隔 τh24每 24 小时一次就是 qd清除率 CLL/h6.3若只知 mL/min需除以 60 再乘以 1000分布容积 VdL450地高辛这类药物 Vd 很大生物利用度 F无单位0~10.7片剂通常低于静脉注射计算结果中cssAvg、cssMax、cssMin单位统一为 mg/L。临床习惯上血药浓度常写作 μg/mL 或 ng/mL1 mg/L 1 μg/mL 1000 ng/mL页面展示时要在结果后明确标注单位否则药师会把 mg/L 和 ng/mL 搞混这是真实发生过的用药安全隐患。4. WXML 表单交互输入、校验与结果回显计算逻辑只解决了“算得对”的问题小程序能不能用取决于页面交互设计。这个项目把计算页放在pages/cssCalculator/下用户在页面上输入参数、点击按钮、看到结果整个过程涉及 WXML 结构、JS 事件绑定和 WXSS 样式三块内容。4.1 WXML 表单的数据绑定计算页的主体是一组输入框加一个计算按钮。WXML 核心片段如下view classform-group text classlabel单次剂量 (mg)/text input classinput typedigit placeholder例如250 value{{ dose }} bindinputonDoseInput / /view view classform-group text classlabel给药间隔 (h)/text input classinput typedigit placeholder例如24 value{{ interval }} bindinputonIntervalInput / /view button classcalc-btn bindtaphandleCalc计算稳态浓度/button view classresult-card wx:if{{ showResult }} text classresult-title计算结果/text text classresult-item平均稳态浓度{{ cssAvg }} mg/L/text text classresult-item稳态峰浓度{{ cssMax }} mg/L/text text classresult-item稳态谷浓度{{ cssMin }} mg/L/text /viewtypedigit是这里的一个细节。微信小程序的input组件里typenumber调起的是不带小数点的数字键盘而typedigit会调起带小数点的键盘。清除率、分布容积这类参数经常带小数用digit才合适。bindinput在值变化时触发对应处理函数value{{ dose }}让输入框的值与 data 同步形成受控组件。4.2 JS 端事件处理与校验逻辑对应的cssCalculator.js中的事件处理函数和数据定义如下Page({ data: { dose: , interval: , clearance: , volume: , bioavail: , cssAvg: , cssMax: , cssMin: , showResult: false }, onDoseInput(e) { this.setData({ dose: e.detail.value }); }, onIntervalInput(e) { this.setData({ interval: e.detail.value }); }, // 其他输入处理函数同理 handleCalc() { const { dose, interval, clearance, volume, bioavail } this.data; const result calcSteadyState({ dose: parseFloat(dose), interval: parseFloat(interval), clearance: parseFloat(clearance), volume: parseFloat(volume), bioavail: parseFloat(bioavail) || 1 }); if (result.error) { wx.showToast({ title: result.error, icon: none }); return; } this.setData({ cssAvg: result.cssAvg, cssMax: result.cssMax, cssMin: result.cssMin, showResult: true }); } });parseFloat这一步不能省。用户在输入框里输入的永远是字符串直接用字符串和数字比较或参与乘法运算JavaScript 会做隐式类型转换但遇到空字符串或非法字符时会得出NaN。parseFloat之后再传给计算函数配合上一章的参数校验能把绝大多数输入错误拦截在计算之前。计算完成后用setData更新页面数据showResult置为true触发结果区域的wx:if条件渲染。wx.showToast用来弹出错误提示icon: none表示不带图标的长文本提示适合展示“剂量必须大于 0”这类具体错误信息。4.3 WXSS 样式与适配细节计算器的页面样式不需要复杂的视觉效果关键是数字输入区域要醒目、结果要看得清。核心 WXSS 片段如下.form-group { display: flex; flex-direction: column; margin: 24rpx 32rpx; padding: 24rpx; background: #ffffff; border-radius: 16rpx; box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04); } .label { font-size: 28rpx; color: #2d3748; margin-bottom: 12rpx; } .input { height: 80rpx; padding: 0 24rpx; background: #f7fafc; border-radius: 12rpx; font-size: 32rpx; border: 2rpx solid #e2e8f0; } .calc-btn { margin: 40rpx 32rpx; background: #2b6cb0; color: #ffffff; border-radius: 16rpx; height: 88rpx; line-height: 88rpx; font-size: 32rpx; } .result-card { margin: 24rpx 32rpx; padding: 32rpx; background: #ebf8ff; border-radius: 16rpx; border-left: 8rpx solid #3182ce; } .result-title { font-size: 30rpx; font-weight: 600; color: #2c5282; display: block; margin-bottom: 16rpx; }这里统一使用rpx单位在不同宽度的屏幕上等比例缩放。每个输入组用白色卡片包裹视觉上区分于背景色。输入框的border不能省略浅色背景加浅色边框在小屏幕上的对比度不足容易让用户忽略可输入区域。结果卡片用了左边框高亮样式让计算出来的三个浓度值在页面上有视觉优先级。适配层面计算页底部内容在 iPhone 全面屏机型上可能被 Home Indicator 遮挡。常见的做法是在根容器加padding-bottom: env(safe-area-inset-bottom)这个环境变量由微信自动注入不需要手写媒体查询。5. 用真实药物参数验证计算器并向临床场景扩展代码写完了要能解释得通。我平时验证计算逻辑用的是一组地高辛公开药代动力学参数你也可以用这组数据在新导入的工程里做冒烟测试。地高辛维持剂量 0.25 mg给药间隔 24 小时口服生物利用度取 0.7正常肾功能患者清除率约 6 L/h分布容积约 450 L。先用公式手算一遍ke 6 / 450 0.0133 h^-1 e^(-ke×τ) e^(-0.32) ≈ 0.727 Css_avg (0.7 × 0.25) / (6 × 24) ≈ 0.001215 mg/L Css_max (0.7 × 0.25) / (450 × (1 - 0.727)) ≈ 0.001425 mg/L Css_min 0.001425 × 0.727 ≈ 0.001036 mg/L三个单位换算成 ng/mL 后分别是 1.215、1.425、1.036恰好落在 0.8~2.0 ng/mL 的治疗参考窗口内。如果你在开发者工具里输入这组参数页面输出的结果与上面手算值误差应该在 ±0.0001 以内。这个案例能同时验证公式实现、单位换算和页面回显三块逻辑。验证通过之后这个计算器还可以做两个方向的扩展。第一个方向是把给药方案调整内置进来。临床上用稳态谷浓度判断剂量是否合适如果谷浓度高于治疗窗上限先拉长给药间隔 τ而不是直接减剂量因为拉长间隔会同时降低峰浓度和谷浓度波动幅度收窄如果谷浓度偏低但峰浓度正常说明剂量足够但消除太快这时候缩短间隔补谷浓度更合理。计算器可以加一个“目标谷浓度反推给药间隔”的输入项用公式 τ (ln(Css_max) - ln(Css_min)) / ke 反算。第二个方向是引入肾功能折算清除率。很多药物如地高辛、万古霉素主要通过肾排泄肾功能不全患者按标准清除率算出来的稳态浓度会偏低实际浓度可能超标。常见做法是先用 Cockcroft-Gault 公式估算肌酐清除率CrCl ((140 - age) × weight) / (72 × Scr) # 男性 CrCl ((140 - age) × weight) / (72 × Scr) × 0.85 # 女性CrCl 单位是 mL/minScr 是血清肌酐mg/dL体重单位是 kg。算出 CrCl 后再按药物的肾排泄比例修正清除率 CL修正值喂给现有的calcSteadyState函数。前端只需要增加年龄、体重、性别、血清肌酐四个字段后端加一个calcCrCl函数即可。这样计算器从“已知清除率反推浓度”升级为“已知肾功能推稳态浓度”在临床场景里的实用价值高了一个量级。本文还有配套的精品资源点击获取