# 输入效率包技术方案:富文本粘贴转 Markdown 与截图轻标注 > 对应提案:[docs/proposals/2026-11-10-rich-paste-annotate.md](../proposals/2026-11-10-rich-paste-annotate.md)(批次 28)。零后端改动、零迁移;改动面收敛在 desktop 的粘贴分流与附件缩略卡两处,默认行为与现状逐字节一致。 ## 1. 需求背景 聊天输入框的粘贴链路(`ChatInput.vue:593-698`,TipTap `editorProps.handlePaste`)当前按以下顺序分流: 1. **文件/图片分支**(:595-634):clipboard items 含 image/ 或 kind==='file' 时入待发列表;图文混排(网页/Office「文字+截图」)时 `text/plain` 手动按行插入段落,返回 true。 2. **超长文本文件化**(:636-654):`planPastedText`(阈值 2000 字符,`components/chat/pasted-text-file.ts`)命中的纯文本静默转 `.txt` 待发附件。 3. **快捷命令标记**(:655-695):`@{…}@` / `${…}$` / `#{…}#` 转编辑器节点。 4. **兜底**(:696-697):返回 false 交给 TipTap 默认粘贴——注释明说「strips formatting by default」。 全链路**从不读取 `text/html`**(grep 全文件零命中)。三类高频来源因此受损:Word/网页/飞书文档粘贴丢全部结构;Excel 区域粘贴成制表符乱流;截图只能发原图,无法圈重点或打码。拖拽通道已由批次 24 落地(`handleDropFiles` / `handleRefDrop`),粘贴通道是输入面最后一块半成品。 ## 2. 需求描述 | # | 用户故事 | 判定 | |---|---|---| | 1 | 从 Word / 网页 / 飞书文档复制带标题、列表、粗斜体、链接、行内代码、代码块的段落粘贴 | 产物为等义 Markdown 源文本(输入框即所见,发送后由 MarkdownContent 正常渲染) | | 2 | 从 Excel 复制一片区域粘贴 | 产出 Markdown 表格;合并单元格按左上值展开、行对齐保序 | | 3 | 粘贴或添加一张图片,点击缩略卡上的「标注」 | 全屏 canvas 编辑器:画笔 / 矩形 / 箭头 / 文字 / 马赛克 / 撤销;确认后替换该附件,原图保留可反复重标 | | 4 | 粘贴超长文本(≥2000 字符)、含快捷命令标记的文本 | 行为与今天完全一致(文件化 / 标记节点),新逻辑不得接管 | ## 3. 技术选型与决策 | 决策点 | 定案 | 理由 | |---|---|---| | HTML→Markdown 库 | **turndown + turndown-plugin-gfm**(MIT,约 30KB+4KB),新增两个运行时依赖与对应 `@types/*` | 仓库现状无 HTML→MD 能力;turndown 规则可白名单化、产物即 GFM 源文本;备选 rehype-in-markdown 链路重(统一 sanitizer+remark 全家桶)对本需求过重 | | 加载方式 | **动态 import + ChatInput setup 预热**:`utils/html-to-markdown.ts` 模块级单例持有 converter(`let converter: TurndownService \| null`),`ensureHtmlConverter()` 在 ChatInput `setup` 里 fire-and-forget 调用;`handlePaste` 是同步钩子,粘贴时 converter 未就绪则**回落现状纯文本行为** | TipTap handlePaste 必须同步返回 boolean;预热后首贴几乎必然就绪,未就绪的回落是无损降级;turndown 因此天然在按需 chunk(进 `scripts/check-main-chunk.mjs` 的 FORBIDDEN 门禁,见 §4.6) | | 转换产物的插入 | 复用 :626-631 的 ProseMirror 段落插入手法:Markdown 源文本按 `\n` 拆行建 paragraph 节点,`state.tr.replaceSelection` 分发。抽公共函数 `insertPlainParagraphs(view, text)`,文件分支(:624-632)与新分支共用 | 输入框是「纯文本 + 特殊节点」心智,Markdown 以源文本呈现与现契约一致;不得用 `insertContent(html)`——那会让 TipTap 解析 HTML 破坏格式语义 | | Excel 合并单元格 | 先 `DOMParser` 解析 ``,按 colspan/rowspan **重复左上值展开**成规整网格,再把规整后的表格 HTML 交给 turndown-gfm | turndown-gfm 对 colspan 会漏列错位;展开后每行单元格数一致,验收标准「行对齐保序」才可兑现 | | 图片元素处理 | 转换前剥离全部 ``(以及 `