news 2026/4/23 17:21:55

深度定制:在富文本编辑器中封装实用的 AI 写作助手功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深度定制:在富文本编辑器中封装实用的 AI 写作助手功能

最近在开发一个多模态AI项目,里面有一个AI写作功能,就是将AI写作辅助功能集成到富文本编辑器中,该功能的交互方式方式灵活多变,需要思考清楚不同的使用场景和提升用户体验,这是实现该功能的难点。本文将深入探讨如何基于 Vue 3.5 和wangEditor富文本编辑器,实现一套高度定制化的流式 AI 写作助手。不仅会展示如何定义和注册一个专用的 AI 工具栏菜单,更会详细解析如何实现全局快捷键唤醒选中文本高亮标记流式请求处理以及打字机效果等核心功能,最终打造出无缝、高效的 AI 辅助写作体验。

1. AI 写作助手的核心需求与技术选型

我们的目标是提供一个非侵入式、随用随取的 AI 助手,它能够根据用户的输入或选中的文本,执行续写、总结、润色和翻译等操作,并将结果以实时流式的方式展示给用户。

  • 富文本编辑器:选择了wangEditor,它提供灵活的模块注册机制和丰富的 API 接口,便于我们深度定制工具栏和内容操作。
  • 前端框架:采用Vue 3 (Composition API),配合<script setup>简化组件逻辑和状态管理。
  • AI 交互模式:采用**弹出式(Popup)**设计,在光标位置或编辑器中心出现,提供极佳的上下文感知体验。

2. 定制 AI 工具栏菜单 (definedMenu.js)

首先,我们需要在wangEditor的工具栏中添加一个“AI 工具”下拉菜单。这通过实现一个自定义的菜单类来完成。

核心代码解析
// definedMenu.jsimport{Boot}from'@wangeditor/editor'classMyselectAiBar{constructor(){this.title='AI 工具'this.tag='button'this.showDropPanel=true}// ... 其他方法(getValue, isActive, isDisabled, exec 保持默认)getPanelContentElem(){constul=document.createElement('ul')// ... 省略 ul 和 li 的创建和样式设置constitems=[{label:'AI 续写',value:'continue'},// ... 其他 AI 动作]items.forEach((item)=>{constli=document.createElement('li')li.textContent=item.label// 核心:点击并触发自定义全局事件li.addEventListener('click',(e)=>{constevent=newCustomEvent('askAiClick',{detail:{value:item.value,// continue, summary 等type:'toolbar',},})document.dispatchEvent(event)})ul.appendChild(li)})returnul}}// 注册配置constmyselectAiConf={key:'myselectAiBar',factory(){returnnewMyselectAiBar()}}functionregisterMenusOnce(){// 避免 Vite HMR 导致的重复注册if(globalThis.__aiMenusRegistered)returnconstmodule={menus:[myselectAiConf]}Boot.registerModule(module)globalThis.__aiMenusRegistered=true}exportclassAIToolManager{init(editor){registerMenusOnce()this.editor=editor}// ... destroy 方法}
设计思路
  1. 菜单类型:this.showDropPanel = true声明这是一个下拉面板菜单。
  2. 事件机制:菜单项的点击事件不直接操作编辑器,而是通过document.dispatchEvent(new CustomEvent('askAiClick', ...))触发一个自定义全局事件。这种解耦方式非常关键,它使得 AI 菜单的逻辑可以在主组件 (NoteEditor.vue) 中集中处理,避免了在编辑器模块内部处理复杂的 Vue 组件逻辑。
  3. 单次注册:使用globalThis.__aiMenusRegistered标记确保在 Vue 的热重载(HMR)机制下,编辑器模块只被注册一次。

3. 主编辑器组件 (NoteEditor.vue):集成与控制

NoteEditor.vue负责初始化编辑器、注册 AI 菜单、处理快捷键,以及管理 AI 弹窗的显示状态和位置。

3.1 菜单与事件集成

NoteEditor.vue中,我们首先将自定义菜单键myselectAiBar插入到工具栏配置中,并监听全局自定义事件。

// NoteEditor.vue <script setup> 部分// 工具栏配置consttoolbarConfig={// ...insertKeys:{index:0,// 插入到最前面keys:['myselectAiBar']}}// 监听 AI 菜单点击事件consthandleAskAiClick=async(e)=>{constdetail=e?.detail||{}constaction=detail.value||''// continue/summary | polish | translateconsteditor=editorRef.value// ... 检查内容是否为空,弹出 ElMessage 提示// 1. 显示AI弹窗showAIPopup()// 2. 调用子组件处理(传入 AI 动作和全文内容)if(aiPopupRef.value){// AI 菜单通常用于全文操作(如总结、续写),故传入全文constallContent=editor.getText()||''aiPopupRef.value.handleSubmit(action,allContent)}}onMounted(()=>{document.addEventListener('askAiClick',handleAskAiClick)// ... 监听其他事件})
3.2 快捷键与光标定位

我们实现了按下Ctrl + Alt组合键来唤醒 AI 弹窗,并精确地将其定位到光标附近。

// NoteEditor.vue <script setup> 部分// 处理全局快捷键consthandleGlobalKeydown=(event)=>{// 检测Ctrl+Alt组合键if(event.ctrlKey&&event.altKey){event.preventDefault()consteditor=editorRef.valueif(editor&&editor.isFocused()){showAIPopup()// 编辑器内,显示弹窗}else{showAITip()// 编辑器外,显示提示}}}// 获取光标像素坐标(考虑页面滚动)constgetCaretPixelPosition=()=>{constselection=window.getSelection()if(!selection||selection.rangeCount===0)returnnullconstrect=selection.getRangeAt(0).getBoundingClientRect()// 关键:基于视口坐标加上滚动量,得到文档坐标return{x:rect.left+window.scrollX,y:rect.bottom+window.scrollY+10,// 略微向下偏移}}// 缓存光标位置:在编辑器聚焦且选择变化时记录像素坐标constupdateCaretPosition=()=>{// ... 省略逻辑constposition=getCaretPixelPosition()if(position)lastCaretPosition.value=position}
3.3 选中文本高亮与恢复

为了给用户清晰的视觉反馈,当用户选中一段文本唤出 AI 弹窗时,需要对该文本进行临时的高亮标记。

// NoteEditor.vue <script setup> 部分// 标记选中文本constmarkSelectedText=()=>{constselection=window.getSelection()if(!selection?.rangeCount||selection.getRangeAt(0).collapsed)returnconstrange=selection.getRangeAt(0)selectedRange.value=range.cloneRange()// 缓存原始范围// 创建高亮包装元素 (span)consthighlight=document.createElement('span')// ... 样式设置(背景色、边框等)try{// 提取选中内容并包装constcontents=range.extractContents()// 移除选中内容highlight.appendChild(contents)range.insertNode(highlight)// 插入包装后的内容boldWrapper.value=highlight selection.removeAllRanges()// 清除选择,避免干扰}catch(error){// ... 警告处理}}// 移除标记并恢复选中constunmarkSelectedText=()=>{if(!boldWrapper.value)returntry{conststrong=boldWrapper.valueconstparent=strong.parentNode// 将高亮元素的内容移回父节点while(strong.firstChild){parent.insertBefore(strong.firstChild,strong)}// 移除高亮元素parent.removeChild(strong)// 恢复选中状态 (如果需要)// ...// 清理引用boldWrapper.value=nullselectedRange.value=null}catch(error){// ... 警告处理}}

4. AI 弹窗组件 (AIWritingPopup.vue):流式交互实现

AIWritingPopup.vue是 AI 助手的核心交互界面,负责用户输入、动作选择、调用 AI API 以及展示流式结果。

4.1 动作选择与输入逻辑

弹窗在初始状态会显示快捷动作菜单(续写、总结等)。用户可以选择一个动作,或直接输入指令。

<div v-if="dropdownVisible" class="dropdown-menu"> <div v-for="action in quickActions" :key="action.value" class="dropdown-item" @click="handleActionSelect(action.value)"> {{ action.label }} </div> </div>
4.2 流式请求与打字机效果

为了提供更好的实时体验,AI 结果采用了流式传输,并配合打字机(Typewriter)效果模拟人打字的过程。

// AIWritingPopup.vue <script setup> 部分// 状态constaiResult=ref('')// 实时累积的 AI 完整结果constdisplayText=ref('')// 用于打字机效果显示的文本consttypewriterInterval=ref(null)// 定时器conststreamController=ref(null)// 流式请求的控制器// 打字机效果conststartTypewriter=()=>{// ... 确保 displayText 为空,重置 indextypewriterInterval.value=setInterval(()=>{constcurrentTargetText=aiResult.valueif(index<currentTargetText.length){// 实时追加字符displayText.value+=currentTargetText[index]index++}else{// 检查是否有新流式内容到达,若没有则停止if(aiResult.value.length>index){// 有新内容,继续}else{clearInterval(typewriterInterval.value)typewriterInterval.value=null}}},30)// 每 30ms 追加一个字符}// 核心:调用流式 APIconsthandleSubmit=async(externalAction=null,externalContent=null)=>{// ... 参数检查和状态重置 (isLoading = true)try{streamController.value=aiAssistStream(requestParams,{onMessage:(content)=>{// 1. 实时更新完整结果aiResult.value+=content// 2. 启动打字机if(!typewriterInterval.value){startTypewriter()}isLoading.value=false// 收到内容后隐藏加载动画},onError:(error)=>{// ... 错误处理isLoading.value=falsestopTypewriter()},onComplete:()=>{isLoading.value=falsedisplayText.value=aiResult.value// 确保完整显示stopTypewriter()}})}catch(error){// ... 异常处理}}// 中断 AI 处理consthandleInterrupt=()=>{if(streamController.value){streamController.value.close()// 调用控制器中断流streamController.value=null}// ... 清理状态}
4.3 结果插入与清理

AI 结果生成后,用户可以选择“插入到编辑器”或“复制结果”。插入时,需要将纯文本内容通过NoteEditor.vue暴露的事件接口 (insert-text) 传回主组件。

// AIWritingPopup.vue <script setup> 部分consthandleInsertResult=()=>{constcontent=aiResult.value||displayText.valueif(content){// 移除HTML标签,只保留纯文本consttextContent=content.replace(/<[^>]*>/g,'')// 触发父组件的插入事件emit('insert-text',textContent)// ... 成功提示}handleClose()// 关闭弹窗}

5. 总结

通过上述定制化方案,我们成功地将 AI 写作能力深度集成到了富文本编辑器中。关键的设计点在于:

  1. 解耦:通过自定义全局事件(askAiClick) 解耦了wangEditor菜单和 Vue 组件的业务逻辑。
  2. 用户体验:实现了Ctrl + Alt快捷键唤醒光标定位,以及选中文本高亮,提供了强大的上下文感知能力。
  3. 实时性:结合流式 API 请求打字机效果,极大地优化了 AI 结果的等待体验。

这一整套实现方案不仅提升了写作效率,也为后续更复杂的 AI 功能集成奠定了坚实的基础。

从0到1打造一款具备Ai聊天,AI写作,文生图,语音合成,语音识别功能的多模态全栈项目,多模态AI项目开发 链接

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 13:41:39

跨境电商直播带货APP开发要点:多语言、多币种与物流链路设计

过去三年&#xff0c;跨境电商直播的增长速度有目共睹。无论是东南亚市场的爆发、还是中东与拉美市场的迅速扩张&#xff0c;“跨境直播本地履约”的模式正在成为卖家走出去的标配。而要支撑这一套增长逻辑&#xff0c;一个稳定、低延迟、可快速迭代的跨境电商直播带货APP&…

作者头像 李华
网站建设 2026/4/23 14:15:30

mysql与redis缓存一致性问题

先更新数据库&#xff0c;再删除redis 没有试探机制&#xff0c;如果redis删除失败&#xff0c;永久不一致并发问题&#xff1a;删除redis之前&#xff0c;其他线程读取到旧数据 先删除缓存&#xff0c;再更新数据库 没有试探机制&#xff0c;如果数据库更新失败&#xff0c;永…

作者头像 李华
网站建设 2026/4/23 14:11:30

vLLM源码编译与定制化构建:从入门到精通的技术实践指南

vLLM源码编译与定制化构建&#xff1a;从入门到精通的技术实践指南 【免费下载链接】vllm A high-throughput and memory-efficient inference and serving engine for LLMs 项目地址: https://gitcode.com/GitHub_Trending/vl/vllm 在大语言模型推理加速领域&#xff0…

作者头像 李华
网站建设 2026/4/23 14:38:13

投入1分,回报10分?深挖AI开发平台“吸金”的三大黄金场景!

引言&#xff1a; 企业投资的终极目标是回报。所有技术引入&#xff0c;ROI&#xff08;投资回报率&#xff09;是最关键的考量。那么&#xff0c;AI开发平台到底能在哪些场景下&#xff0c;为企业带来最直接、最可观的“真金白银”&#xff1f;本文将抛开概念&#xff0c;直击…

作者头像 李华
网站建设 2026/4/23 14:38:09

你的同行都在偷偷用的AI开发平台,到底强在哪里?三大高阶场景曝光。

引言&#xff1a; 在激烈的市场竞争中&#xff0c;保持技术领先是塑造品牌高端形象的关键。当你的同行还在讨论概念时&#xff0c;领先者早已利用AI开发平台在核心业务上构筑了难以逾越的护城河。本文将曝光那些“闷声发大财”的企业正在深耕的三大高阶应用场景&#xff0c;展现…

作者头像 李华