Files
AIclinicalresearch/docs/03-业务模块/AIA-AI智能问答/04-开发计划/编辑器选型深度评估与落地建议.md
HaHafeng 4d7d97ca19 feat(aia): Protocol Agent streaming + editable state panel + protocol generation plan
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
2026-01-24 23:06:33 +08:00

6.1 KiB
Raw Permalink Blame History

临床研究方案编辑器选型评估与落地建议

评估对象: BlockNote vs. Tiptap vs. Others

业务场景: AI 驱动的一键生成临床研究方案 (Protocol)

技术栈: React 19, TypeScript, Ant Design X

1. 为什么 BlockNote (Tiptap Wrapper) 是最佳选择?

在 "AI + 文档编辑器" 领域,目前业界的主流标准其实就是 Tiptap

  • Vercel AI SDK 的官方示例使用的是 Tiptap (Novel)。
  • Notion 风格的开源实现大多基于 Tiptap。

BlockNote 的核心优势(针对你们的项目)

  1. 结构化数据 (JSON): BlockNote 默认保存为 JSON Blocks。这对于后端解析、存储、甚至未来做 "结构化数据提取"(比如从方案中提取入排标准存入数据库)非常有利。
    • 对比: 纯 Markdown 编辑器Milkdown在处理复杂嵌套结构时解析成本较高。
  2. Slash Command (/命令): 开箱即用的 "/" 菜单,非常适合集成 "AI 续写"、"插入统计公式"、"插入 CRF 表格" 等医疗特有指令。
  3. React 19 兼容性: 它是专为 React 设计的,集成到你们现在的 frontend-v2 没有任何阻碍。

2. 医疗科研场景的特殊挑战 (Risk Assessment)

虽然 BlockNote 很棒,但在临床研究方案这个垂直场景下,有两个潜在的大坑,你需要提前规划:

🚨 挑战 A复杂的医学表格 (Schedule of Events)

临床方案中必须包含 "访视排期表" (Schedule of Events),这是一个极其复杂的二维表格(行是检查项目,列是访视时间点,中间是 X

  • BlockNote 现状: 表格支持相对基础。
  • Tiptap 能力: Tiptap 拥有非常强大的 Table 扩展(支持合并单元格、列宽调整)。
  • 建议: 如果 BlockNote 的表格无法满足需求,你需要利用它 "基于 Tiptap" 的特性,混入 Tiptap 原生的 Table 插件,或者开发一个自定义的 React Component Block 来渲染复杂的访视表。

🚨 挑战 B参考文献管理 (Citations)

研究方案必须引用文献(如 [1], [2]),且文末要有参考文献列表。

  • 现状: 通用编辑器通常不自带引用管理。
  • 建议: 这需要自定义开发。利用 BlockNote 的 Inline Content 扩展能力,创建一个 Citation 节点。点击 [1] 时,侧边栏(利用 Ant Design X显示文献详情从 PKB 知识库获取)。

3. 推荐的 AI 集成架构 (Streaming Architecture)

不要只把编辑器当文本框。在 React 19 + AI 场景下,建议采用以下模式:

3.1 影子文档模式 (Shadow Document)

当 AI 在生成方案时,不要直接操作用户的编辑器实例(会导致光标跳动、冲突)。

  • 方案: 使用一个不可见的 "Shadow Editor" 接收流式数据,或者在当前编辑器中插入一个 "Ghost Block"(幽灵块,灰色文字),流式结束后转为正式内容。

3.2 交互式 AI 块 (Interactive AI Blocks)

利用 BlockNote 的自定义 Block 能力,不仅仅生成文本,而是生成交互组件

  • 场景: AI 觉得样本量太小,不仅生成文字建议,还生成一个 "样本量重算按钮" 插入到文档中。点击按钮,弹窗调用你们的 SSA (统计分析) 模块。

4. 最终选型结论与 Roadmap

🏆 最终推荐BlockNote (Phase 1) -> Tiptap Custom (Phase 2)

这个路线是完全可行的,因为 BlockNote 就是 Tiptap 的一层优美的皮肤。

阶段 技术选型 关键任务
Phase 1 (快速上线) BlockNote (标准版) 1. 快速实现文档读写 2. 实现 /ai 命令调用你们的 Protocol Agent 3. 实现 Markdown/Word 导出
Phase 2 (专业增强) BlockNote + 自定义 React Blocks 1. 开发 CitationBlock (关联 PKB 模块) 2. 开发 ScheduleTableBlock (复杂表格) 3. 开发 ReviewComment (批注功能,复用 RVW 模块逻辑)
Phase 3 (极致定制) Tiptap Headless (如果 BlockNote 限制太大) 如果 BlockNote 的交互逻辑(如拖拽)严重干扰了医学文档的严谨性,此时可以剥离 BlockNote UI回退到 Tiptap 核心重写 UI数据模型无需迁移

💡 另外一个强有力的竞争者Novel (novel.sh)

  • 简介: Novel 是一个开源的、基于 Tiptap 的、类似 Notion 的编辑器,专门为 AI 写作设计。
  • 优势: 它已经把 "AI 自动补全" (Vercel AI SDK) 集成得非常好了。
  • 建议: 你们可以看一眼 Novel 的源码。如果觉得 BlockNote 封装太深,可以直接 Fork Novel 进行修改。Novel 的代码结构可能更适合做深度定制。

5. 代码落地示例 (React 19 + BlockNote + AI Stream)

// components/ProtocolEditor/index.tsx
import { useCreateBlockNote } from "@blocknote/react";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";

export default function ProtocolEditor({ aiStreamContent }) {
// 1. 初始化编辑器
const editor = useCreateBlockNote({
initialContent: [
{ type: "heading", content: "1. 研究背景" },
{ type: "paragraph", content: "在此输入背景..." }
],
});

// 2. 监听 AI 流式输出 (Hooks)
useEffect(() => {
if (aiStreamContent) {
// 实时将 AI 的内容插入到当前光标位置或指定 Block
editor.insertBlocks(
[{ type: "paragraph", content: aiStreamContent }],
editor.getTextCursorPosition().block,
"after"
);
}
}, [aiStreamContent]);

// 3. 自定义渲染 (集成 Ant Design X 风格)
return (
<div className="protocol-editor-container bg-white min-h-screen">
<BlockNoteView
editor={editor}
theme="light"
// 可以在这里覆盖默认的 Slash Menu集成你们的 Protocol Agent
slashMenu={false}
>
{/* 自定义 Slash Menu 组件 */}
<MyCustomSlashMenu editor={editor} />
</BlockNoteView>
</div>
);
}