3.被@的人会在IM中收到消息。这条消息来自发起人与被@的人之间的私聊。如果聊天的内容中包含了附件,则附件不会发送到IM,只会发送本文内容和表情。
四.艾特符模块实现
1.首先通过const selection = Window.getSelection()
2.const range = selection.getrangeAt(0)获取光标的位置,我使用的是create-pos插件准确获取光标的位置
3.然后监听键盘事件,阻止输入@的默认行为,并且创建一个SPAN标签,内容为@,然后到光标处
4.创建两个新的span标签,把@+选中的内容让放到其中一个新建的span标签中,另外一个span标签插入空格。
5.创建一个fragment片段,把第四步中两个span标签一次插入fragment中
6.最后使用Range对象中的insertNode()方法插入富文本中
7.第6步完成之后,找到第4步创建并带有@的SPAN节点,然后移除8.删除时,首先找到包含@+内容的节点,然后把整个节点一起删除
appendEmoji(imgSrc) { // 堆代码 duidaima.com // 拿到dom获取光标 const editor = this.$refs.jsEditorElement; if (editor) { this.isFocus() console.log(editor.focus); this.selectEmoji(imgSrc); console.log('onChangeJsEditor') this.onChangeJsEditor('emoji') } this.visibleEmoj = false; }将文本框的光标位置移动到添加表情后的位置
selectEmoji(url) { const editor = this.$refs.jsEditorElement; if (editor) { editor.focus(); // 堆代码 duidaima.com // this.editorRange.selection.collapseToEnd(); // 删掉草稿start const editorRange = this.editorRange.range; console.log( "editorRange", editorRange, editorRange.startOffset, editorRange.endOffset ); if (!editorRange) { return; } const textNode = editorRange.endContainer; // 拿到末尾文本节点 const endOffset = editorRange.endOffset; // 光标位置 // 找出光标前的at符号位置 // const textNodeValue = textNode.nodeValue // const expRes = (/@([^@]*)$/).exec(textNodeValue) // if (expRes && expRes.length > 1) { // editorRange.setStart(textNode, expRes.index) editorRange.setEnd(textNode, endOffset); editorRange.deleteContents(); // 删除草稿end const dom = this.createInsterImgData(url); console.log(dom); console.log(this.editorRange.selection); console.log(this.editorRange.range); this.insertHtmlImgAtCaret( dom, this.editorRange.selection, this.editorRange.range ); // } } },将表情包以加装后img标签的形式累加到文本显示
createInsterImgData(url) { const btn = document.createElement("img"); btn.setAttribute("src", url); btn.setAttribute("class", "emo"); btn.setAttribute("style", "width: 26px;height:26px;"); return btn; },
this.insertCaret( `<a data-id="${some.member_id}" data-mid="${some.im_user_id}" class="userSetClass" data-name="${some.member_name}" contenteditable="false">@${some.member_name}</a> ` ); createInsterData(personArr) { const temp = []; for (const person of personArr) { const btn = document.createElement("a"); btn.dataset.id = person.member_id; btn.dataset.mid = person.im_user_id; btn.dataset.name = person.member_name || person.name; btn.contentEditable = false; btn.setAttribute("href", "javascript:void(0)"); if(this.allowSelectMembers.length === personArr.length) { btn.textContent = ` &${person.member_name} `; btn.setAttribute('style', 'display:none') btn.setAttribute("class", "userHiddenSetClass"); } else { btn.textContent = ` @${person.member_name} `; btn.setAttribute("class", "userSetClass"); } btn.addEventListener( "click", () => { return false; }, false ); btn.tabindex = "-1"; const bSpaceNode = document.createTextNode("\u200B"); // 不可见字符,为了放光标方便 temp.push(btn); temp.push(bSpaceNode); } // 堆代码 duidaima.com // 将所有添加进去@所有人 if(this.allowSelectMembers.length === personArr.length) { const btn = document.createElement("a"); btn.type = "link"; btn.textContent = ` @所有人 `; btn.contentEditable = false; btn.setAttribute("class", "userSetAllClass"); btn.setAttribute("href", "javascript:void(0)"); btn.tabindex = "-1"; const bSpaceNode = document.createTextNode("\u200B"); // 不可见字符,为了放光标方便 temp.push(btn); temp.push(bSpaceNode); } return temp; },二、输入@符号监听
onInputText(e) { this.onChangeJsEditor(e.target.innerHTML) console.log(e.target.innerHTML) // 这是输入了@,那就直接弹选人浮层 this.doToggleDialog(); console.log(this.editorRange); if (e.code === "Digit2" && e.shiftKey) { this.mockInput = false; console.log("输入@"); // 获取新的参与人alt列表 this.getAllNewMembers() } },三、发布评论前的数据转换
let collect = editor.getElementsByClassName("userSetClass"); console.log(collect, Array.from(collect).length); for (const child of collect) { atidsss.push(child.dataset.id); atnames.push(child.dataset.name); atmid.push(child.dataset.mid); } // @所有人 let AltAll = editor.getElementsByClassName("userSetAllClass") // if(AltAll.) if(AltAll && Array.from(AltAll).length > 0) { let userHiddenSetClass = editor.getElementsByClassName("userHiddenSetClass") for (const child of userHiddenSetClass) { atidsss.push(child.dataset.id); atnames.push(child.dataset.name); atmid.push(child.dataset.mid); } }其次,将带有img标签的html文本,通过正则表达式将其提取出图片名称,用于IM的消息推送格式
params.imText = params.imText.replace( /<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function (match, capture) { console.log(capture); let name = that.getLastFileName(capture) if(name) { return `[${name}]` } return '' } );最后就是整理数据,将后端定义好的数据格式传递给他们
let params = { task_id: this.activeTaskItemDetailID, text: this.$refs.jsEditorElement.innerHTML, imText: this.$refs.jsEditorElement.innerHTML, images: this.imgList, users: atidsss ? atidsss.filter((v) => v) : [], attachment: this.fileList, };完结 如果您还有力气,麻烦点个小指头,支持下感谢!