闽公网安备 35020302035485号
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,
};
完结 如果您还有力气,麻烦点个小指头,支持下感谢!