Day 2 Development (2026-01-24): Backend Enhancements: - Implement SSE streaming in ProtocolAgentController using createStreamingService - Add data condensation via LLM in ProtocolOrchestrator.handleProtocolSync - Support stage editing without resetting progress - Add explicit JSON output format for each stage in system prompt - Create independent seed script for Protocol Agent (seed-protocol-agent.ts) Frontend Improvements: - Integrate useAIStream hook for typewriter effect in ChatArea - Add MarkdownContent component for basic Markdown rendering - Implement StageEditModal for editing stage data (scientific question, PICO, etc.) - Add edit button to StageCard (visible on hover) - Fix routing paths from /aia to /ai-qa - Enhance CSS with full-screen layout and Markdown styles New Documentation: - One-click protocol generation development plan (v1.1) - Editor selection evaluation (Novel vs BlockNote vs Tiptap) - Novel fork strategy for AI-native editing Technical Decisions: - Choose Novel (Fork) as protocol editor for AI-first design - Two-stage progressive generation: summary in chat, full protocol in editor - 10-day development plan for protocol generation feature Code Stats: - Backend: 3 files modified, 1 new file - Frontend: 9 files modified, 2 new files - Docs: 3 new files Status: Streaming and editable features working, protocol generation pending
7.4 KiB
深度选型报告:Novel vs. BlockNote
评估对象: Novel (Fork源码方案) vs. BlockNote (npm包方案)
业务场景: AI 驱动的临床研究方案生成编辑器
核心结论: 推荐 Novel (Fork)。虽然初期成本略高,但在 AI 集成和 UI 定制上拥有绝对的主动权。
1. 核心架构对比 (The Architecture)
两者底层都是 Tiptap (ProseMirror),但封装哲学完全不同。
| 维度 | BlockNote | Novel |
|---|---|---|
| 封装程度 | 极高。它试图隐藏 Tiptap 的复杂性,创造了一套自己的 Schema (BlockNote Schema)。 | 中等。它本质上只是 Tiptap 的一个 React Wrapper,直接暴露 Tiptap 的配置。 |
| 数据结构 | 自定义 JSON Blocks。它把 Tiptap 的 Document 转换成了自己的 Block 数组。 | 标准 Tiptap JSON。完全遵循 ProseMirror 标准结构。 |
| UI 耦合度 | 高。Slash Menu 和 Side Menu 是硬编码在库里的,很难改样式。 | 低 (Fork后)。所有 UI 组件(Menu, Bubble)都是 React 代码,你可以随意魔改。 |
| React 亲和度 | ⭐⭐⭐⭐⭐ (专为 React 设计) | ⭐⭐⭐⭐⭐ (专为 React/Next.js 设计) |
🧐 分析:
- 如果您只是想做一个简单的笔记应用,BlockNote 完胜。
- 但您要做的是 "AI Protocol Editor",需要插入复杂的 "样本量计算器按钮"、"引用卡片"。BlockNote 的自定义 Schema 可能会成为绊脚石,而 Novel 直接操作 Tiptap,灵活性无限。
2. AI 集成维度 (The AI Factor)
这是您最关心的部分:如何与你们自研的 StreamingService 对接。
BlockNote 的表现
- 现状: 它没有内置 AI 自动补全逻辑。
- 实现路径: 您需要自己监听后端流式数据,然后手动调用 editor.insertBlocks()。
- 痛点: 处理“流式打字机效果”时,BlockNote 的 Block 更新机制可能会导致光标跳动或性能问题。
Novel 的表现
- 现状: 它是为 AI 而生的。它内置了 useCompletion (Vercel SDK) 的完整逻辑。
- 优势: 它已经处理好了 "AI 生成时的 Ghost Text (幽灵文字)"、"生成后的 Markdown 解析"、"生成中的光标锁定" 等细节。
- 实现路径 (Fork): 您只需要把 useCompletion 替换为你们的 useAIStream,剩下的 UI 交互(如 /ai 唤起生成框)都是现成的。
🏆 胜出者: Novel。它在 AI 交互体验上已经帮您踩平了坑。
3. 医疗特性扩展性 (Medical Features)
场景 A:访视排期表 (复杂表格)
- BlockNote: 对表格支持较弱,很难实现合并单元格。
- Novel: 可以直接引入 @tiptap/extension-table。虽然 Novel 默认表格也不强,但您可以直接修改源码,引入更强的表格插件。
场景 B:文献引用 (Citation)
- BlockNote: 需要学习它的 Custom Schema API 来定义一个 Inline Content。文档相对较少。
- Novel: 直接写一个标准的 Tiptap NodeView (React 组件)。网上的 Tiptap 教程都能用。
场景 C:导出 Word
- BlockNote: 它的 JSON 结构是非标准的,您需要先转成 Markdown/HTML,再转 Word。
- Novel: 它的 JSON 是 Tiptap 标准的。社区里有现成的 tiptap-to-docx 转换库,或者直接用 pandoc。
🏆 胜出者: Novel。标准的 Tiptap 生态远比 BlockNote 的私有生态强大。
4. 潜在风险与成本 (The "Gotchas")
🔴 Novel (Fork) 的风险
- 代码维护成本: 您 Copy 了几千行代码进项目,以后 Novel 官方更新了,您得手动同步(或者不仅同步,直接断开维护)。
- 样式污染: Novel 使用 Tailwind CSS,类名可能会与您的 Ant Design 冲突。需要小心处理 CSS 作用域。
- 学习曲线: 您的团队需要懂一点 Tiptap 的底层原理(Node, Mark, Extension)。
🔴 BlockNote 的风险
- 天花板效应: 开发到第 2 个月,产品经理说“我要在编辑器里画一个甘特图”,BlockNote 可能直接做不到。
- 黑盒: 作为一个 npm 包,如果它有 Bug,您只能等官方修,或者发 Patch。
5. 最终决策建议
如果您满足以下条件,请坚决选择 Novel (Fork):
- 您的团队有能力读懂并修改 React 源码。
- 您不仅需要“写文字”,还需要在文档里插入“交互式组件”(如计算器、图表)。
- 您对 UI 的精细度要求很高(必须符合 Ant Design X 风格)。
如果您满足以下条件,才退而求其次选择 BlockNote:
- 您的团队只有 1 个前端,且不熟悉富文本原理。
- 您只需要一个“能打字的 Notion”,不需要太复杂的 AI 交互。
🚀 您的选择确认
您之前的 Phase 1 (Fork Novel) 计划是非常明智的。
不要纠结了,Fork Novel 是正确的路。 BlockNote 看起来简单,但在深度 AI 集成场景下,它是**“先甜后苦”;而 Novel 是“先苦后甜”**,一旦您掌握了源码,天空才是极限。
鉴于 Novel 的代码质量很高(基于 Tiptap + React),完全放弃它太可惜。
我的最终建议是:不要作为 npm 包引入 Novel,而是将其源码 Copy 到项目中作为起点 (Fork & Own)。
这样既利用了它现成的 UI (Slash Menu, Drag Handle),又拥有了 100% 的控制权,可以随意修改 AI 逻辑和组件。
🗺️ 推荐落地路线图 (Phase 1-3) 这个路线图将确保你们在 Phase 1 快速上线,同时为 Phase 2 的医疗特性预留空间。
Phase 1: Fork Novel + 对接你们的 StreamingService (快速上线) 目标:3天内 跑通“编辑器 + AI 流式生成”。
Action 1: 源码引入
不要 npm install novel。
去 GitHub 把 novel/packages/core/src 下的核心代码复制到 frontend-v2/src/shared/components/Editor。
Action 2: 剥离 Vercel SDK,对接自研后端
找到 useCompletion 或 AI 调用的 hook。
替换为 你们现有的 useAIStream Hook (来自 shared/components/Chat/hooks/useAIStream.ts)。
修改 API 路径:指向 /api/v1/aia/protocol-agent/generate。
Action 3: 保留核心交互
保留 Slash 命令 (/) 和 拖拽手柄 (DragHandle)。这些是 Notion 体验的灵魂,自己写很费劲。
交付物:一个长得像 Notion、实际上调用的你们 Fastify 后端的编辑器。支持 Markdown 导出。
Phase 2: 医疗特性增强 (差异化竞争) 目标:解决“表格”和“引用”这两个痛点。
Action 1: 集成 Tiptap Table 扩展
Novel 默认可能对表格支持较弱。
引入 @tiptap/extension-table,并定制渲染组件,支持合并单元格(访视排期表刚需)。
Action 2: 开发 CitationBlock (对接 PKB)
这是 Novel 没有的功能。
基于 Tiptap 的 NodeView,开发一个 React 组件:。
点击时,右侧弹窗显示 PKB 中的文献详情。
Action 3: 导出 Word
使用 docx.js 或 pandoc (后端服务),将 Tiptap JSON 转换为 .docx。注意:表格的转换是难点,需预留时间调试。
Phase 3: 如需更深定制 (兜底方案) 如果发现 Fork 来的代码太乱,难以维护。
回退策略:此时你们已经熟悉了 Tiptap 的 API。可以丢弃 Novel 的 UI 代码,仅保留 Tiptap 核心,用 Ant Design X 重写工具栏。数据模型 (JSON) 是完全兼容的,用户数据不会丢。