写了一年,我想把这款电子病历文档编辑器开源出来,希望你愿意点个 ⭐
一款从零手写的 Canvas 编辑器,前端 React + 后端 Spring Boot,把"医疗文书怎么写才对"这件事,认真做了一遍。
一、先说为什么
去年我开始做 EMR 文档编辑器引擎(EMR Document Engine),起因其实挺朴素:
做医疗系统的同行都知道,病历编辑器是整个 HIS / 电子病历系统的"咽喉"。上面顶着医生一天的工作效率,下面压着病历质量、合规审计、科研数据化。但行业里能用的开源方案寥寥无几——要么是 Quill、Slate、Tiptap 这类通用富文本魔改,要么是商业产品闭源收费,要找到一款从医疗场景出发、自带质控规则、纸张级排版、可长期维护的开源编辑器,几乎不可能。
于是我决定自己写。
从 ModelD 文档模型、到 LayoutEngine 排版、到三层 Canvas 渲染、到 20 多条医疗质控规则、再到 25 条医学缩写自动更正——逐行敲代码,敲了一年。
今天,它已经是一个能在线预览、能写进真实生产流程的系统。我想把它正式开源出来,邀请更多的同行一起来打磨。
如果你对编辑器内核、富文本、Canvas 渲染、可视化排版、医疗信息化中的某一个方向感兴趣,欢迎 Star、Fork、提 Issue、提 PR。这是给愿意在开源里长期投入的开发者的一份邀请。
二、这是一款怎样的编辑器
简单来说,它不是一个"在 contenteditable 上贴 toolbar"的玩具,而是一套面向电子病历场景、纸张级排版、可扩展的文档编辑器内核。
它能做什么:
📝 像 Word 一样顺手——字体、字号、加粗、斜体、下划线、删除线、上标/下标、文字颜色、文字高亮、清除格式、格式刷,一个不少 📐 段落级精细控制——左/中/右/两端对齐、有序/无序列表(支持 CJK / 罗马数字编号)、多级标题、缩进、行距 🧩 复杂结构元素——表格(合并/拆分/表头重复/跨页断表)、图片、脚注、书签、交叉引用、域代码(页码/总页数/作者等 8 种)、分节符、分隔线 🏥 医疗专用控件——7 种结构化录入控件(文本/文本域/数字/下拉/日期/复选/单选),关键字段不再"随手敲" 🧠 医疗智能——25 条医学缩写自动更正(i.v.g.t.t. → 静脉滴注)、智能中文标点配对 🔍 查找替换——支持正则、大小写敏感、全词匹配 📊 可视化能力——Canvas 图表(柱/线/饼/雷达/散点)、条码(Code128B + QR) 🎨 纸张级排版——A4 页面、页眉页脚、页码、水印、孤行寡行控制、所见即所得 💬 批注协作——添加/回复/解决批注,黄色高亮标记 🧾 多格式导出——JSON / TXT / HTML 已可用,PDF / DOCX 正在路上 🌐 多语言——i18n 框架已接入
更值得一提的是,它不是一个孤零零的前端 demo——前后端一体,后端用 Spring Boot 3 + MyBatis-Plus + Spring Security + WebSocket 提供文档服务、用户权限、审计日志、自动保存、版本回溯。
👉 在线体验:http://139.196.151.15/
三、作为开源项目,它"硬核"在哪里
如果只是"功能多",并不稀奇。这一年里,我觉得它真正有意思的地方,是底层架构的反复打磨。
1. 自研 Canvas 编辑器内核(不基于任何富文本框架)
整个编辑器没有依赖 Quill / ProseMirror / Slate / Tiptap 任何一个第三方富文本框架——所有能力都是手写的:
三层 Canvas 架构: static(页面背景、水印、阴影) /content(文本、表格、图片) /interact(光标、选区、IME 预览),配合 rAF 重排与脏区裁剪,几十页病历也能丝滑滚动排版-渲染分离: DocumentModel排版无关,分页与版式由LayoutEngine全权负责;LineBreaker(UAX#14 参考)+PageBreaker(含孤行寡行控制)+IncrementalLayout(段落级缓存)粒子化渲染: TextParticle/TableParticle/ListParticle/ImageParticle/LaTeXParticle/CommentParticle/ChartParticle/BarcodeParticle……每种元素独立渲染,通过ParticleRegistry调度,方便扩展多语言字体系统: FontManager+FontFallback(缺字降级链) +ScriptResolver(Unicode 脚本检测),中英文混排不串字虚拟滚动: VirtualViewport根据 scrollY 计算可见页范围,仅渲染可见页,长文档零压力
这意味着:你可以把这个内核拆出来,单独用于任何"纸张级排版 + 文档编辑"的场景,不必局限于医疗。
2. 完整的 Command 模式与 Undo/Redo
编辑器内核有10 种 Command 类型(插入/删除/拆分合并段/格式化/清除/格式刷/段落样式/插入节点/状态变更),全部支持:
✅ Undo / Redo(Ctrl+Z / Ctrl+Y) ✅ 500ms 自动合并——连续输入/删除自动合并成一个不可分割的操作 ✅ 栈深度限制 + 跨命令级联撤销 ✅ 任何编辑操作都走 Command,不会出现"绕过撤销栈的偷偷修改"
这是很多"看起来能编辑"的项目没做到的——而它决定了病历在多人协作、长时间编辑下的可靠性。
3. 插件系统 + 扩展点
编辑器内置 PluginManager,提供 IPlugin / PluginContext / ExtensionPoint / ToolbarAction 一套完整接口,编辑器本身就是可扩展的:
想给工具栏加按钮?挂一个 ToolbarAction 想拦截某些操作?注册一个 ExtensionPoint 想加入自定义元素?注册到 ParticleRegistry
启动时已自带 emr.demo 示例插件。这个设计参考了 ProseMirror 的 plugin 思路,但更轻量、更适合病历这种"业务规则密集"的场景。
4. 医疗质控引擎(QCEngine)
病历质量不是"事后检查"出来的,而是"书写时"就该有保障的。系统内置20+ 条质控规则,对病历内容实时评分、分级,问题在书写阶段就被提示,而不是等到归档后才被退回。
5. 错误恢复 + 自动保存 + 乐观锁
医疗文书不是普通文档——丢一行可能就是医疗事故。编辑器有三道保险:
ErrorRecovery—— safeRenderParticle/safeRenderPage/safeLoadDocument,一次异常不会拖垮整份病历AutoSaveManager—— IndexedDB 存储,3 秒防抖,保留最近 3 个版本,崩溃可恢复 文档乐观锁插件 —— 多人同时编辑时,基于版本号检测冲突,避免相互覆盖
6. Yjs + y-websocket 已就位(协同编辑预留)
虽然协同编辑本身还在路上,但 yjs 和 y-websocket 已经作为依赖装好,CommandContext 也预留了 collab 模式入口。这等于告诉你:项目的下一步往哪走,架构上已经留好了位置。
四、技术栈一览
前端:React 18 · TypeScript (strict) · Vite · Tailwind CSS · Zustand · Radix UI · Lucide · Axios · HTML5 Canvas(自研渲染器) · KaTeX · Yjs
后端:Java 17 · Spring Boot 3.x · MyBatis-Plus · Spring Security · JWT · WebSocket · Redis · Springdoc OpenAPI · MySQL 8.0(测试 H2)
工程化:Vitest(213 个单元测试) · Docker + docker-compose · Nginx · Conventional Commits · Gitee 托管
文档完备:output/ 下放了 5 份正式文档(调研、PRD、架构、UI/UX、技术规格),knowledge/ 下放了一份完整的编辑器功能清单(基于代码逐项盘点,含 170 项功能与已知边界)
五、为什么希望你来 ⭐
我把它开源出来,初心很简单:让医疗信息化少一些重复造轮子。
但我知道,一款开源编辑器能不能走得远,不取决于我一个人敲多少行代码,而取决于有多少人愿意停下来看它一眼、提一个 Issue、补一行测试。
所以——
如果你做医疗信息化,被病历编辑器折磨过,这个项目值得你花 5 分钟看个 demo: 如果你对编辑器内核、富文本、Canvas 渲染、可视化排版感兴趣,源代码值得你点个 ⭐: 如果你愿意参与建设,PR / Issue / 文档修订,每一份都弥足珍贵——你可以在 README 末尾看到完整的贡献流程
一颗 ⭐ 不多,但它是开源世界给作者最重要的回馈——它告诉我:这个方向有人在乎,值得继续走下去。
六、Roadmap(不画大饼,只说已经在做的)
为了不让你失望,下面这些是真实在推进的事:
PDF 导出、协同编辑一旦完成,会单独发文同步。
七、写在最后
做开源最难的,不是写代码,是一个人能走多远。
我一个人写了一年,把"自研 Canvas 编辑器内核 + 完整医疗业务闭环 + 200+ 测试 + 完整文档"这套东西交了出来。但一款真正能在医院里跑起来的电子病历编辑器,还需要:
更多同行来 review 内核设计 更多有医疗背景的朋友来补充质控规则 更多前端工程师来打磨交互细节 更多贡献者把它翻译成更多语言
如果上面的某一件事正好是你擅长的,或者你正在找一款"可以长期投入"的开源项目——
👉仓库地址:https://gitee.com/wangwang_1_1665527118/emrdocument-engine👉在线预览:http://139.196.151.15/
期待你的 ⭐。更期待你的 PR ❤️。
让病历不再只是负担,让好的工具成就更好的医疗。
夜雨聆风