知行札记
DocFlow 实现与复用调查

DocFlow 功能与接线盘点

按编辑器、协同、AI、基础设施、导出与工程检查所查快照的接线范围。

本页整理自 2026-10-04 的 DocFlow 静态调查材料。原材料没有提供仓库 URL、分支或提交哈希;正文中的路径、行号、计数与依赖版本均指向该未锚定快照。本轮整理读取了归档报告,未取得原工作副本、启动产品或验证外部后端。下文的“复核”指原材料记载的复核,前端路径存在与运行可用性分别判断。

功能全景

实现程度图例(判定口径:依赖外部后端本身不影响判定——整个产品的后端都在仓库外,前端有效入口及处理路径完整即计 ✅,不据此判断外部后端或运行效果;⚠️ 仅表示前端交付的是功能子集或混合真实/假数据):

  • ✅ 材料记录了前端实现与接线,运行可用性未验证(带"复核"者表示该结论经逐条代码原材料复核;个别功能的子项例外时在说明列以 🚫 单独标出)
  • ⚠️ 部分实现:仅功能子集可用,或同一功能内混合真实实现与假数据/占位
  • 🚫 死代码 / 未接线:代码已写好,但所查快照的构建配置下不可达或无效果(未注册、无调用方、入口被注释,或仅为无绑定的装饰 UI)
  • 🔶 演示级实现
  • ❌ 仅依赖声明 / 仅文档宣称,无实现

编辑器核心(/docs/[room])

功能程度说明与证据
块式文档结构✅ 复核Document(content 'block+',extensions/Document/Document.ts:4)+ Heading 1-6 + 段落 + TrailingNode
列表(有序/无序/任务)✅ 复核TaskItem 嵌套 extension-kit.ts:80-82;slash 菜单 SlashCommand/groups.ts:3-195
折叠块 Details✅ 复核Details.configure({ persist: true }),extension-kit.ts:106-113
引用 / 水平线✅ 复核slash Style 组(groups.ts:3-195)
代码块✅CodeBlockLowlight 二次封装:lowlight common(约 40 语言)、``` 输入规则带语言别名(js→javascript 等)、语言下拉/复制/折叠/换行、theme 属性(CodeBlock/CodeBlock.ts:12,61-97,266-271、CodeBlockComponent.tsx:243,320);Mod-/ 按语言切换注释、Tab/Shift-Tab 两空格缩进(CodeBlock.ts:104-243)、Mod+A 仅选代码(SelectOnlyCode.ts:16-24)
表格✅ 复核官方 TableKit,resizable: true(extension-kit.ts:318-322)
图片体系✅ 复核三节点:ImageUpload 占位上传块 / ImageBlock(宽、对齐、alt)/ 表格内缩略 TableImage;拖放粘贴统一走 FileHandler,先插 base64 预览再上传后按 src 回查替换为服务器 URL(图片节点与上传)
数学公式✅ 复核官方 Mathematics(KaTeX,自定义 \R \N \Z \Q \C 宏)+ 自研 MathLiveExtension(Ctrl/Cmd+M 弹 MathLive 可视化编辑器,插 inlineMath)+ mathMigration 匿名扩展把旧 $...$ 文本防抖迁移为数学节点(extension-kit.ts:342-370、MathLiveEditor/MathLiveExtension.ts:69-74)
YouTube 视频✅ 复核官方 Youtube.extend + openYoutubeDialog 命令与对话框(Youtube/Youtube.ts:45,49-83)
目录 TOC✅双实现:可插入正文的 tableOfContentsNode 原子节点(读官方 TableOfContents storage,TableOfContentsNode.tsx:85-121)+ 页面悬浮 FloatingToc(rAF 节流高亮,docs/_components/FloatingToc/index.tsx:24-44)
emoji✅ 复核官方 Emoji 扩展 + 自研 emojiSuggestion 建议(extensions/index.ts:50、extension-kit.ts:309-312)
@Mention✅自研 inline 原子节点(char '@'),候选来自好友接口带时间缓存、失败返回空数组(Mention/mention.ts:39,79-85,170-194、suggestion.tsx:60-96)
slash 命令菜单✅自研:基于 @tiptap/suggestion,char '/'、startOfLine、仅根深度段落触发;Style/Insert 分组 + 别名过滤(h1/img/hr/todo 等);ReactRenderer 渲染 Popover、滚动重定位、键盘导航(SlashCommand.ts:16-36,53-93,94-246、groups.ts:3-195)
文本气泡菜单✅ 复核自研 CustomBubbleMenu(floating-ui computePosition + flip/shift/autoUpdate,TextMenu/BubbleMenu.tsx:2,121-141,170-203);功能:块类型切换、字体/字号、B/I/U/S/行内代码/代码块、链接、多色高亮、文字颜色、上下标、四种对齐(TextMenu.tsx:88-247)
Link / ImageBlock 气泡菜单✅ 复核用官方 BubbleMenu(@tiptap/react/menus);ImageBlockMenu 提供对齐 + 宽度滑杆(LinkMenu.tsx:3、ImageBlockMenu/index.tsx:1,15-38)
块拖拽排序✅ 复核编辑器内:官方 drag-handle-react 的 DragHandle 包住 ContentItemMenu(+ 添加块 / AI 续写 / GripVertical 弹出清除格式/复制/复制块/删除,ContentItemMenu.tsx:1,37-90);侧栏组件库:原生 HTML5 DnD(dataTransfer 'application/x-block-type')+ 自研 DragHandler 插件策略工厂(DragHandler.ts:34-96,258-269、BlocksTab.tsx:204-207);dnd-kit 仅用于侧栏文件树排序(块拖拽机制)
搜索替换✅自研 SearchAndReplace 扩展(decoration 高亮 + storage)+ SearchPanel(大小写开关、上一处/下一处、替换/全部替换),Ctrl/Cmd+F 打开(SearchAndReplace.ts:44-60、SearchPanel.tsx:20-35、page.tsx:119-147,210-223)
粘贴增强✅MarkdownPaste(micromark-gfm/mdast 解析 Markdown 纯文本粘贴为 PM 节点 + clipboardTextSerializer 反向输出 Markdown)+ JsonPaste(监听剪贴板 text/json 整体替换文档)(Markdown 转换;page.tsx:168-204 copy 时写入 text/json 与 docflow-reference)
AI 建议 diff mark✅ 复核AgentSuggestion(added 绿 / deleted 红),accept/reject 命令按 suggestionId 批量处理(建议接受与拒绝)
评论(Comment)🚫mark 与 Mod-Shift-m 快捷键已实现(Comment/Comment.ts:217)但未注册进 ExtensionKit,编辑器内不生效;与 HTTP 权限等级 COMMENT 的关系见 协同权限边界 注记
图注(Figure/Figcaption)🚫Figure 节点已实现但未注册;仅注册的 Figcaption 缺少父容器,图注结构无法形成(extensions/index.ts:43,59 仅导出;ExtensionKit 数组无二者)
B 站视频块🚫packages/bilibili/src/Bilibili.ts:77 有完整扩展实现,但 ExtensionKit 未注册;仅 styles/index.css:23 引入其样式、next.config.ts:13 加入 transpilePackages
甘特图❌仅 package.json:145 声明 frappe-gantt 依赖 + styles/index.css:18 引入其 CSS,全 src 无任何 Gantt 组件/扩展(grep -ri gantt 仅命中该 CSS)
流程图 / 音频块 / mermaid❌schema 无此类节点(grep audio/flowchart/gantt/mermaid 于扩展注册表无命中)
侧栏组件库部分块类型⚠️BlocksTab 展示 14 种块(BlocksTab.tsx:94-189),DragHandler 策略表只覆盖 10 种(DragHandler.ts:258-269);video/calendar 等走默认段落策略,audio/ai 生成的节点类型 schema 中不存在,点击插入处理器仍是 TODO console.log(BlocksTab.tsx:209-212)

实时协同

功能程度说明与证据
Yjs 文档协同✅ 复核客户端 HTTP 鉴权 → new Y.Doc() → y-indexeddb 本地恢复 → HocuspocusProvider 连 WS;房间名 = documentId;useCollaboration.ts:45-47,54-56,70-74、useDocumentPermission.ts:39,59-65
Tiptap 绑定✅ 复核Collaboration.configure({ document, field: 'content' }) + CollaborationCaret.configure({ provider, user }),仅在 IndexedDB+服务端均同步后条件加入(page.tsx:102-108;useCollaboration.ts:145)
多人光标 / 在线成员✅ 复核awareness setLocalStateField('user') + 'update' 遍历 getStates() 过滤自己 → DocumentHeader 头像列表(useCollaboration.ts:106-140、DocumentHeader/index.tsx:27-31,51-53)
只读权限✅服务端经 Hocuspocus stateless {type:'server:permission', readOnly} 下发权威只读标志(优先于 HTTP VIEW/COMMENT 兜底);editor.setEditable(!isReadOnly, false) 动态切换不重建实例(useCollaboration.ts:78-92、page.tsx:85-89,156-165);认证失败 toast "已使用本地缓存打开";权限等级全集与 COMMENT 等级在所查快照的构建配置下的实际效果见 协同权限边界 注记
本地持久化✅ 复核y-indexeddb,库名 tiptap-collaborative-<documentId>;注释明言"先加载本地快照以最小化 WS diff"(useCollaboration.ts:38,45-47)
离线编辑✅ 复核未配置 WS_URL 时 provider=null 且直接标 isServerSynced=true,以 IndexedDB 数据离线打开;重连增量同步;冲突处理完全依赖 Yjs CRDT,仓库无自定义冲突代码(grep conflict 仅命中 AI 建议 mark 的 schema excludes 检测,useDocumentEdit.ts:65-82)
历史版本(快照)✅ 复核useEditorHistory:自动快照默认 5 分钟、内容(state vector 哈希)变化才存、卸载时存;snapshotService 用 Y.snapshot/encodeSnapshot 存浏览器 IndexedDB 库 docflow-snapshots,每文档上限 50 份自动清理,恢复用 createDocFromSnapshot 重建后替换 content。纯本地实现,换设备无法取得本机历史快照(useEditorHistory.ts:155-204、services/snapshot/index.ts:11,94-130,149-194,247-254)
快照 UI✅HistoryPanel:创建(带描述)/恢复/删除/清空,含四个确认对话框组件(docs/_components/HistoryPanel/index.tsx:41-100)
workflow 画布协同🔶第二处独立协同:Y.Map nodes/edges 同步 ReactFlow、awareness 画布光标;但 URL 硬编码 wss://flow.codecrack.cn、房间固定 'flow-room'、用户名/颜色随机、无 IndexedDB、awareness 靠 setTimeout(100ms) 延迟初始化——演示级(canvas.tsx:44-73,131-146,152-193、cursors-layer.tsx:20-53)
Hocuspocus 服务端❌@hocuspocus/server 仅 package.json:52-53 声明(lockfile 实装 3.4.4),全仓库零 import;服务端在未开源的 api.codecrack.cn(基础设施调查)
y-webrtc(P2P)❌package.json 声明 ^10.3.0,零 import;实际传输层只有 HocuspocusProvider 的 WebSocket

AI 能力

功能程度说明与证据
编辑器 Agent 智能编辑✅ 复核AgentEditPanel:自然语言指令 + editor.getJSON() 全量文档 POST /api/v1/collaboration/agent/edit(timeout 120s),SSE 回 thinking/intent/anchor/proposal;按"理解意图→定位位置→生成内容"三步展示(services/collaboration/index.ts:89-130、useDocumentEdit.ts:281-284、page.tsx:36-39,324)。注:"LangGraph 三节点"系前端注释自述(index.ts:107),后端不在仓库无法从所查仓库直接核实
diff 式提案落地✅ 复核4 种操作(append_to_doc/insert_after/insert_before/replace),insertContentAt 注入 agentSuggestion mark(added 绿/deleted 红),逐条/批量接受拒绝(useDocumentEdit.ts:99-174,392-440、AgentSuggestion/index.ts:69-182)
独立 AI 聊天✅ 复核/chat-ai:前端组装 system(默认一句话"你是一个专业、礼貌、高效的 AI 助理。",constants.ts:36)+ 全部历史 + 新消息,附 11 个采样参数(top_p/top_k/max_tokens/temperature/frequency_penalty/min_p/stop/n/enable_thinking/thinking_budget/enable_web_search)(useChat.ts:134-155)
流式输出✅ 复核OpenAI 兼容 chunk(delta.content + delta.reasoning_content 深度思考);自研 streamPost:fetch + getReader + TextDecoder 按行解析 data: JSON、跳过 [DONE](client.ts:1019-1238,1243-1279、type.ts:112-131);新会话 ID 从 Session-Id 响应头提取后 replaceState 换 URL(chat-ai/index.ts:220-227、chat-ai/[id]/page.tsx:31-38)
模型配置✅ 复核Model 列表从 /api/v1/chat/models 动态拉取;MaxTokens/Temperature/Top-P/Top-K/Frequency Penalty/Min-P/N/Stop/System Prompt 在 ConfigFields(ConfigFields.tsx:100-266);深度思考/联网搜索开关在聊天界面底部(ChatAIPanels.tsx:495-504,669,ConfigFields.tsx:7 注释自述移位);双模型并排对比(ModelConfigModal.tsx:108-142、ChatInterface.tsx:364-366)。请求不含任何用户 API Key——模型由后端统一代理
会话管理✅分页列表/加载更多/删除/改标题/详情 + 跨组件事件广播;新会话用 13 位时间戳临时 ID,初始消息经 sessionStorage 中转,后端返回真实 id 后 replaceState(useConversations.ts:105-215、chat-ai/[id]/page.tsx:46-62)
流式渲染节流✅双重优化:useChat 5ms 缓冲批量 flush(useChat.ts:158-253);useDocumentEdit ref 累积 + setTimeout(0) 合并渲染(useDocumentEdit.ts:201-231)
知识库⚠️仅管理 UI:创建/列表/删除/上传文件/添加 URL 到 /api/v1/ai/knowledge*(KnowledgeDocumentList.tsx:50,90,126、CreateKnowledgeDialog.tsx:91);且 AiApi 与 KnowledgeApi 重复封装同组端点、两个页面混用。计 ⚠️ 而非 ✅ 的原因:前端交付的只是管理子集,核心消费场景(检索问答)在前端零消费方(见下 RAG 行)——图例按前端接线范围计;外部后端依赖单独说明
RAG 检索增强❌前端零实现:无 embedding/向量库/检索代码;带 useKnowledgeBase/knowledgeIds 的问答 API(AiApi.Question)无调用方;README.md:91 "续写用 RAG 检索相关段落"在前端无对应物(后端不在仓库,无法核实)
编辑器内头脑风暴/润色/续写❌README.md:15 重点宣传;服务层 ChatAiApi.Brainstorm/Polish/Autocomplete 与 AiApi.ContinueWriting 定义齐全但全库零调用方,仅遗留 styles/partials/ai-brainstorm.css:1-9
用户 API Key 设置🚫设置页 UI 可交互、能把 siliconflow/minimax 两个 provider 的 key 写入 localStorage 键 docflow_api_keys(api-key-settings.tsx:53-58,83-98);但无任何代码读取该键或把 key 附加到 AI 请求——"用自配 key 调 AI"的功能目标未达成,属无绑定的装饰 UI
AI 播客✅独立功能:上传简历(PDF/MD/DOC/DOCX)生成面试播客,3 种面试官人设 × 8 个 MiniMax TTS 音色(UploadResumeCard.tsx:58、services/podcast/index.ts:15-55)
孤儿 AI 接口🚫StreamAgent / TextToImage / GeneratePodcastAsync 等仅类型与方法定义,无 UI 消费;request.sse 通道仅被这三个无调用方的接口使用
@azure/core-sse 的 sseStream🚫依赖已装、client.ts:902-1008 实现完整,但全库无调用方——实际生效的流式只有 streamPost 一条通道

后端与基础设施(前端侧可见部分)

功能程度说明与证据
业务后端❌仓库内不存在(仓库外依赖 证据链);真实后端为未开源 api.codecrack.cn
Next.js 服务端能力✅ 复核几乎为零:src/app/api 仅 health 一个静态 route;AGENTS.md:15 明文 "no API routes";README.md:25 声称的 Server Actions 不属实——全仓库无一处 'use server'
路由守卫✅src/proxy.ts:113-130 按 auth_token cookie 做存在性/过期的服务端守卫与重定向,matcher 仅覆盖 /docs、/dashboard、/chat-ai、/rooms;与 WS 协同无关
登录鉴权✅ 复核GitHub OAuth(跳 ${SERVER_URL}/api/v1/auth/github + code 回调)+ 邮箱验证码/密码双通道;token 存 auth_token/refresh_token cookie;401 时自动用 refresh_token + X-CSRF-Token 调 /api/v1/auth/refresh 并重放排队请求(client.ts:131-205,244-253,285-289);WS 连接携带 token: getAuthToken()(useCollaboration.ts:74)
文件上传✅ 复核完整分块协议,全走外部 API:check-file 哈希秒传 / chunk-info 断点续传 / chunk 分块 / complete-file 合并 / avatar 直传(services/upload/index.ts:16,21-31,38-50,64-101,122-150,187-206);视频转写下载 /api/v1/video/*、图片元数据 /api/v1/image/:hash
匿名行为分析✅fingerprintjs 生成 visitorId + UA 解析(OS/浏览器/分辨率/时区)+ 页面停留心跳,sendBeacon 上报 /api/v1/trace(useAnalysis.ts:2,20,99,114-133,171-175);与鉴权无关
Sentry✅三端接入:client 硬编码 DSN + replay + 采样 1(instrumentation-client.ts:7-29)、server 仅生产采样 0.1(sentry.server.config.ts:7-29)、edge config + onRequestError(instrumentation.ts:13、next.config.ts:83-88);请求层逐步 addBreadcrumb/captureException
Datadog🚫browser-logs 仅在 LiveKit 调试组件(rooms/_components/Debug.tsx:16-43),需 NEXT_PUBLIC_DATADOG_CLIENT_TOKEN/SITE 两个未配置的 env;且该 Debug 组件本身已被注释出页面(PageClientImpl.tsx:28,371)——代码不可达
Prometheus/Grafana、ELK、MinIO、RabbitMQ❌仅 README 文案(README.md:45-63),无代码/依赖/编排;logstash 一词连 README 都未出现

导入导出与周边功能

功能程度说明与证据
Markdown 粘贴导入✅ 复核手写实现(非官方 @tiptap/markdown):micromark-gfm + mdast → PM 节点;且两处高度重复的实现(Markdown 转换)
Markdown 复制序列化✅ 复核MarkdownPaste 重写 clipboardTextSerializer 反向输出 Markdown(MarkdownPaste.ts:38-40,395-611)
JSON 整文粘贴/复制✅copy 时写 text/json + docflow-reference(page.tsx:168-204);JsonPaste 监听 text/json 整体替换文档(JsonPaste.ts:12-34)
Word(.docx)导出✅ 复核tiptap-extension-export-docx 的源码 fork,18 个文件(17 converter + index)、convertNode 14 个 case,基于 docx@9.5.1;imageBlock 先归一化为 image;浏览器端 Blob 下载(Word 导出)
PDF 导出✅ 复核@zumer/snapdom DOM→canvas(过滤 BUTTON、jpeg 0.95)+ jspdf 按 A4 分页,60s 超时(document-export/pdf.ts:42,51-89)
复制到公众号✅ 复核juice CSS 内联后以 ClipboardItem 写 text/html + text/plain(document-actions.tsx:60-101)
导出入口✅ 复核文档页"操作"菜单:复制到公众号/导出PDF/导出Word/发布到博客(document-actions.tsx:143,165-177)
Word 导入❌mammoth 在 package.json:156 声明(lockfile 实解析 1.11.0),源代码零引用;知识库/播客上传仅把 .doc/.docx FormData 发给后端
xlsx 导出❌xlsx@0.18.5 仅用于文件图标颜色映射(utils/format/file-type.ts:19)
导出图片❌无此功能(仅有复制图片 blob 与 TableImage 缩略节点)
博客发布/展示✅公开博客:ISR(revalidate=3600)+ generateStaticParams(前 50 篇)+ OG/twitter/canonical;服务端拉数据 dangerouslySetInnerHTML 渲染;编辑器 getHTML 经 zod 校验后发布(blog/page.tsx:14,30、blog/[id]/page.tsx:161、use-blog-publish.ts:27-60)
LiveKit 音视频✅ 复核/rooms 完整度较高:后端 quick-create/join 签发 token → base64 进 URL ?c= 跳转;房间页 384 行实现 Room 配置(adaptiveStream/dynacast/singlePeerConnection/simulcast)、E2EE(worker + URL hash 密码)、GridLayout、头像 overlay、自动开摄像头麦克风、屏幕共享、录制指示、低功耗优化(周边交付链路)。但四个子项为 🚫 死代码:<Chat/> 被注释(PageClientImpl.tsx:369,仅剩 ChatToggle)、SettingsMenu/CameraSettings(BackgroundBlur)/MicrophoneSettings(useKrispNoiseFilter)未被任何页面渲染——krisp 降噪、背景虚化、设备菜单所查快照中未接线
dashboard/contacts⚠️列表渲染硬编码 MOCK_CONTACTS 假数据(ContactMemberList.tsx:8,28),但添加好友/好友请求走真实 API(AddContactDialog.tsx:18)
dashboard 其他⚠️knowledge/podcast/workflow(ReactFlow)/organizations 各有页面;messages 是 ComingSoonPage 占位(dashboard/messages/page.tsx:1-8)
深色模式🚫 复核tailwind 配置 + 约 50 个文件写 dark: 类 + useDarkMode hook 实现完整,但全仓库无任何组件引用该 hook、root layout 无主题初始化脚本;设置页"暗色主题"复选框(无绑定,settings/page.tsx:73-82)与 SettingsTab 主题下拉(本地 state,SettingsTab.tsx:19-35)都是不生效的装饰 UI
国际化❌无 i18n 依赖与 useTranslation,UI 文案硬编码中文;tinykeys 仅注册在被注释的 Debug 面板(Shift+D),实际未启用

工程化

项程度说明与证据
Monorepo 任务编排✅turbo.json:5-49 定义 build/dev/type-check/lint/test/clean;transformer 依赖 alert+bilibili 先构建
Git hooks⚠️husky 仅 pre-commit(跑 pnpm lint/format:ci/type-check);commitlint 配置存在但无 commit-msg hook 强制
测试❌全仓库无 .spec/.test 文件、无 playwright.config、无 test script;vitest/@vitest/* 与 @playwright/test 均为未使用的 devDependencies(package.json:224-229)
Docker✅四阶段构建(node:24-alpine、corepack pnpm@10.28.2、npmmirror 源、非 root、HEALTHCHECK 打 /api/health)、CMD next start(Dockerfile:1-91,107)
docker-compose✅仅 1 个前端服务 ghcr.io/xun082/docflow:latest,无数据库/后端/监控编排
CI✅build(推多 arch 镜像)/ deploy(定时 SSH 拉镜像)/ lint / preview 四个 workflow

最后更新于

本页目录