Browse Source

自定义聊天输入框

master
fangxin 2 years ago
parent
commit
1d9178b592
  1. 292
      im-web/src/components/chat/ChatBox.vue
  2. 604
      im-web/src/components/chat/ChatInput.vue
  3. 9
      im-web/src/components/chat/ChatMessageItem.vue

292
im-web/src/components/chat/ChatBox.vue

@ -36,7 +36,7 @@
</file-upload>
</div>
<div title="发送文件">
<file-upload :action="'/file/upload'" :maxSize="10 * 1024 * 1024"
<file-upload ref="fileUpload" :action="'/file/upload'" :maxSize="10 * 1024 * 1024"
@before="onFileBefore" @success="onFileSuccess" @fail="onFileFail">
<i class="el-icon-wallet"></i>
</file-upload>
@ -58,23 +58,25 @@
<div title="聊天记录" class="el-icon-chat-dot-round" @click="showHistoryBox()"></div>
</div>
<div class="send-content-area">
<div contenteditable="true" v-show="!sendImageUrl" ref="editBox" class="send-text-area"
:disabled="lockMessage" @paste.prevent="onEditorPaste"
@compositionstart="onEditorCompositionStart"
@compositionend="onEditorCompositionEnd" @input="onEditorInput"
:placeholder="placeholder" @blur="onEditBoxBlur()" @keyup.down="onKeyDown"
@keyup.up.prevent="onKeyUp" @keydown.enter.prevent="onKeyEnter">x
</div>
<div v-show="sendImageUrl" class="send-image-area">
<div class="send-image-box">
<img class="send-image" :src="sendImageUrl" />
<span class="send-image-close el-icon-close" title="删除"
@click="removeSendImage()"></span>
</div>
</div>
<!-- <div contenteditable="true" v-show="!sendImageUrl" ref="editBox" class="send-text-area"-->
<!-- :disabled="lockMessage" @paste.prevent="onEditorPaste"-->
<!-- @compositionstart="onEditorCompositionStart"-->
<!-- @compositionend="onEditorCompositionEnd" @input="onEditorInput"-->
<!-- :placeholder="placeholder" @blur="onEditBoxBlur()" @keydown.down="onKeyDown"-->
<!-- @keydown.up="onKeyUp" @keydown.enter.prevent="onKeyEnter($event)">x-->
<!-- </div>-->
<!-- <div v-show="sendImageUrl" class="send-image-area">-->
<!-- <div class="send-image-box">-->
<!-- <img class="send-image" :src="sendImageUrl" />-->
<!-- <span class="send-image-close el-icon-close" title="删除"-->
<!-- @click="removeSendImage()"></span>-->
<!-- </div>-->
<!-- </div>-->
<ChatInput :ownerId="group.ownerId" ref="chatInputEditor" :group-members="groupMembers"
@submit="sendMessage"/>
<div class="send-btn-area">
<el-button type="primary" size="small" @click="sendMessage()">发送</el-button>
<el-button type="primary" size="small" @click="notifySend()">发送</el-button>
</div>
</div>
</el-footer>
@ -86,8 +88,8 @@
</el-container>
</el-main>
<emotion ref="emoBox" @emotion="onEmotion"></Emotion>
<chat-at-box ref="atBox" :ownerId="group.ownerId" :members="groupMembers" :search-text="atSearchText"
@select="onAtSelect"></chat-at-box>
<!-- <chat-at-box ref="atBox" :ownerId="group.ownerId" :members="groupMembers" :search-text="atSearchText"-->
<!-- @select="onAtSelect"></chat-at-box>-->
<chat-record :visible="showRecord" @close="closeRecordBox" @send="onSendRecord"></chat-record>
<group-member-selector ref="rtcSel" :groupId="group.id" @complete="onInviteOk"></group-member-selector>
<rtc-group-join ref="rtcJoin" :groupId="group.id"></rtc-group-join>
@ -107,11 +109,13 @@
import ChatAtBox from "./ChatAtBox.vue"
import GroupMemberSelector from "../group/GroupMemberSelector.vue"
import RtcGroupJoin from "../rtc/RtcGroupJoin.vue"
import ChatInput from "./ChatInput";
export default {
name: "chatPrivate",
components: {
ChatInput,
ChatMessageItem,
FileUpload,
ChatGroupSide,
@ -154,7 +158,7 @@
},
closeRefBox() {
this.$refs.emoBox.close();
this.$refs.atBox.close();
// this.$refs.atBox.close();
},
onCall(type) {
if (type == this.$enums.MESSAGE_TYPE.ACT_RT_VOICE) {
@ -163,97 +167,6 @@
this.showPrivateVideo('video');
}
},
onKeyDown() {
console.log("onKeyDown")
if (this.$refs.atBox.show) {
this.$refs.atBox.moveDown()
}
},
onKeyUp() {
if (this.$refs.atBox.show) {
this.$refs.atBox.moveUp()
}
},
onKeyEnter() {
if (this.$refs.atBox.show) {
// ,
this.focusOffset += this.atSearchText.length;
this.$refs.atBox.select();
} else {
this.sendMessage();
}
},
onEditBoxBlur() {
let selection = window.getSelection()
// (emoji)
this.focusNode = selection.focusNode;
this.focusOffset = selection.focusOffset;
},
onEditorInput(e, e2, e3) {
// @
if (this.chat.type == "GROUP" && !this.zhLock) {
console.log("onEditorInput")
if (e.inputType === "deleteContentBackward" && !this.atSearchText) {
this.$refs.atBox.close();
}
if (e.data == '@') {
//
this.showAtBox(e);
} else if(this.$refs.atBox.show){
let selection = window.getSelection()
let range = selection.getRangeAt(0)
this.focusNode = selection.focusNode;
// @
let stIdx = this.focusNode.textContent.lastIndexOf('@');
this.atSearchText = this.focusNode.textContent.substring(stIdx + 1);
}
}
this.refreshPlaceHolder();
},
onEditorCompositionStart() {
this.zhLock = true;
},
onEditorCompositionEnd(e) {
this.zhLock = false;
this.onEditorInput(e);
},
showAtBox(e) {
this.atSearchText = "";
let selection = window.getSelection()
let range = selection.getRangeAt(0)
//
this.focusNode = selection.focusNode;
this.focusOffset = selection.focusOffset;
//
let pos = range.getBoundingClientRect();
this.$refs.atBox.open({
x: pos.x,
y: pos.y
})
},
onAtSelect(member) {
let range = window.getSelection().getRangeAt(0)
// @xx
range.setStart(this.focusNode, this.focusOffset - 1 - this.atSearchText.length)
range.setEnd(this.focusNode, this.focusOffset)
range.deleteContents()
//
let element = document.createElement('SPAN')
element.className = "at"
element.dataset.id = member.userId;
element.contentEditable = 'false'
element.innerText = `@${member.showNickName}`
range.insertNode(element)
//
range.collapse()
//
let textNode = document.createTextNode('\u00A0');
range.insertNode(textNode)
range.collapse()
this.atSearchText = "";
this.$refs.editBox.focus()
},
onSwitchReceipt() {
this.isReceipt = !this.isReceipt;
this.refreshPlaceHolder();
@ -281,38 +194,18 @@
} [c];
});
},
createAtUserIds() {
createAtUserIds(sendContent) {
let ids = [];
this.$refs.editBox.childNodes.forEach((node) => {
let tempEl = document.createElement('div');
tempEl.innerHTML = sendContent;
tempEl.childNodes.forEach((node) => {
if (node.nodeName == "SPAN") {
ids.push(node.dataset.id);
}
})
return ids;
},
onEditorPaste(e) {
let txt = e.clipboardData.getData('Text')
if (typeof(txt) == 'string') {
let range = window.getSelection().getRangeAt(0)
let textNode = document.createTextNode(txt);
range.insertNode(textNode)
range.collapse();
}
let items = (e.clipboardData || window.clipboardData).items
if (items.length) {
for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
let file = items[i].getAsFile();
this.sendImageFile = file;
this.sendImageUrl = URL.createObjectURL(file);
}
}
}
},
removeSendImage() {
this.sendImageUrl = "";
this.sendImageFile = null;
},
onImageSuccess(data, file) {
let msgInfo = JSON.parse(JSON.stringify(file.msgInfo));
msgInfo.content = JSON.stringify(data);
@ -321,11 +214,10 @@
url: this.messageAction,
method: 'post',
data: msgInfo
}).then((m) => {
}).then((id) => {
msgInfo.loadStatus = 'ok';
msgInfo.id = m.id;
msgInfo.id = id;
this.isReceipt = false;
this.refreshPlaceHolder();
this.$store.commit("insertMessage", msgInfo);
})
},
@ -446,19 +338,20 @@
},
onEmotion(emoText) {
//
this.$refs.editBox.focus();
let range = window.getSelection().getRangeAt(0);
//
range.setStart(this.focusNode, this.focusOffset)
let element = document.createElement('IMG')
element.className = "emo"
element.dataset.code = emoText;
element.contentEditable = 'true'
element.setAttribute("src", this.$emo.textToUrl(emoText));
//
range.insertNode(element)
//
range.collapse()
// this.$refs.editBox.focus();
// let range = window.getSelection().getRangeAt(0);
// //
// range.setStart(this.focusNode, this.focusOffset)
// let element = document.createElement('IMG')
// element.className = "emo"
// element.dataset.code = emoText;
// element.contentEditable = 'true'
// element.setAttribute("src", this.$emo.textToUrl(emoText));
// //
// range.insertNode(element)
// //
// range.collapse()
this.$refs.chatInputEditor.insertEmoji(emoText);
},
showRecordBox() {
@ -541,7 +434,7 @@
//
this.moveChatToTop();
//
this.$refs.editBox.focus();
this.$refs.chatInputEditor.focus();
//
this.scrollToBottom();
//
@ -558,18 +451,46 @@
msgInfo.recvId = targetId;
}
},
sendMessage() {
if (this.sendImageFile) {
this.sendImageMessage();
} else {
this.sendTextMessage();
}
//
this.readedMessage()
notifySend() {
this.$refs.chatInputEditor.submit();
},
sendImageMessage() {
let file = this.sendImageFile;
this.onImageBefore(this.sendImageFile);
sendMessage(fullList) {
// if (this.sendImageFile) {
// this.sendImageMessage();
// } else {
// this.sendTextMessage();
// }
// //
// this.readedMessage()
//
// console.log(arguments)
this.readedMessage();
let sendText = this.isReceipt ? "【回执消息】" : "";
let promiseList = [];
for (let i = 0; i < fullList.length; i++) {
let msg = fullList[i];
promiseList.push(new Promise(() => {
switch (msg.type) {
case "text":
this.sendTextMessage(sendText + msg.content);
break;
case "image":
this.sendImageMessage(msg.content.file);
break;
case "file":
console.log(msg)
this.sendFileMessage(msg.content.file);
break;
}
}))
}
Promise.all(promiseList);
// console.log(arguments)
this.$refs.chatInputEditor.clear();
},
sendImageMessage(file) {
this.onImageBefore(file);
let formData = new FormData()
formData.append('file', file)
this.$http.post("/image/upload", formData, {
@ -581,17 +502,13 @@
}).catch((res) => {
this.onImageSuccess(res, file);
})
this.sendImageFile = null;
this.sendImageUrl = "";
this.$nextTick(() => this.$refs.editBox.focus());
this.$nextTick(() => this.$refs.chatInputEditor.focus());
this.scrollToBottom();
},
sendTextMessage() {
let sendText = this.createSendText();
sendTextMessage(sendText) {
if (!sendText.trim()) {
return
}
this.$refs.editBox.cle
let msgInfo = {
content: sendText,
type: 0
@ -600,7 +517,7 @@
this.fillTargetId(msgInfo, this.chat.targetId);
// @
if (this.chat.type == "GROUP") {
msgInfo.atUserIds = this.createAtUserIds();
msgInfo.atUserIds = this.createAtUserIds(sendText);
msgInfo.receipt = this.isReceipt;
}
this.lockMessage = true;
@ -619,10 +536,16 @@
this.scrollToBottom();
this.resetEditor();
this.isReceipt = false;
this.refreshPlaceHolder();
});
},
sendFileMessage(file) {
let check = this.$refs.fileUpload.beforeUpload(file);
if (check) {
this.$refs.fileUpload.onFileUpload({file});
}
},
deleteMessage(msgInfo) {
this.$confirm('确认删除消息?', '删除消息', {
confirmButtonText: '确定',
@ -665,7 +588,8 @@
this.$http({
url: url,
method: 'put'
}).then(() => {})
}).then(() => {
})
},
loadReaded(fId) {
this.$http({
@ -725,11 +649,13 @@
}
},
resetEditor() {
this.sendImageUrl = "";
this.sendImageFile = null;
this.$nextTick(() => {
this.$refs.editBox.innerHTML = "";
this.$refs.editBox.focus();
// this.$refs.editBox.innerHTML = "";
// this.$refs.editBox.focus();
this.$refs.chatInputEditor.clear();
this.$refs.chatInputEditor.focus();
});
},
scrollToBottom() {
@ -829,6 +755,7 @@
position: relative;
width: 100%;
background: #f8f8f8;
border: #dddddd solid 1px;
.el-header {
padding: 3px;
@ -850,7 +777,7 @@
.im-chat-main {
padding: 0;
background-color: white;
background-color: #f8f8f8;
.im-chat-box {
> ul {
@ -877,7 +804,7 @@
box-sizing: border-box;
border-top: #ccc solid 1px;
padding: 2px;
background-color: #E8F2FF;
background-color: #f5f5f5;
> div {
font-size: 22px;
@ -897,6 +824,10 @@
background: #ddd;
}
}
> div:hover {
color: #949494;
}
}
.send-content-area {
@ -914,7 +845,8 @@
resize: none;
font-size: 16px;
color: black;
outline-color: rgba(83, 160, 231, 0.61);
//outline-color: rgba(83, 160, 231, 0.61);
outline: none;
text-align: left;
line-height: 30px;

604
im-web/src/components/chat/ChatInput.vue

@ -0,0 +1,604 @@
<template>
<div class="chat-input-area">
<div class="edit-chat-container" contenteditable="true"
@paste.prevent="onPaste"
@keydown="onKeydown"
@compositionstart="compositionFlag=true"
@compositionend="compositionFlag=false"
@input="onEditorInput"
@mousedown="onMousedown"
v-html="contentHtml"
ref="content"
@blur="onBlur"
:placeholder="'请输入消息'">
</div>
<chat-at-box @select="onAtSelect"
:search-text="atSearchText"
ref="atBox"
:ownerId="ownerId" :members="groupMembers"
></chat-at-box>
</div>
</template>
<script>
import ChatAtBox from "./ChatAtBox";
export default {
name: "ChatInput",
components: {ChatAtBox},
props: {
ownerId: {
type: Number,
},
groupMembers: {
type: Array,
},
},
data() {
const defaultContentHtml = '<div></div>';
return {
// contentList: [],
// content: null,
defaultContentHtml,
contentHtml: defaultContentHtml + '',
imageList: [],
fileList: [],
currentId: 0,
atSearchText: null,
compositionFlag: false,
history: [defaultContentHtml],
focusOffset: 0,
atIng: false,
blurRange: null
}
}, methods: {
onPaste(e) {
let txt = e.clipboardData.getData('Text')
let range = window.getSelection().getRangeAt(0)
if (range.startContainer !== range.endContainer || range.startOffset !== range.endOffset) {
document.execCommand('delete', false, null);
}
if (typeof (txt) == 'string') {
let textNode = document.createTextNode(txt);
range.insertNode(textNode)
// return;
}
let items = (e.clipboardData || window.clipboardData).items
if (items.length) {
for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
let file = items[i].getAsFile();
let imagePush = {
fileId: this.generateId(),
file: file,
url: URL.createObjectURL(file)
};
this.imageList[imagePush.fileId] = (imagePush);
let imageElement = document.createElement('img');
imageElement.className = 'chat-image no-text';
imageElement.src = imagePush.url;
imageElement.setAttribute("data-img-id", imagePush.fileId);
// imageElement.width = 200;
// imageElement.height = 100;
range.insertNode(imageElement);
} else {
let asFile = items[i].getAsFile();
if (!asFile) {
continue;
}
let filePush = {fileId: this.generateId(), file: asFile};
this.fileList[filePush.fileId] = (filePush)
let fileElement = this.createFile(filePush);
range.insertNode(fileElement);
// var text = document.createTextNode("\u00A0");
fileElement.insertAdjacentHTML('afterend','\u00A0');
// range.selectNodeContents(text);
// range.collapse();
}
}
}
range.collapse();
},
selectElement(element) {
let selection = window.getSelection();
setTimeout(() => {
let t1 = document.createRange();
t1.setStart(element, 0);
t1.setEnd(element, 0);
if (element.firstChild) {
t1.selectNodeContents(element.firstChild);
}
t1.collapse();
selection.removeAllRanges();
selection.addRange(t1);
element.focus();
})
},
onKeydown(e) {
if (e.keyCode === 13) {
e.preventDefault();
e.stopPropagation();
if (this.atIng) {
console.log('选中at的人')
this.$refs.atBox.select();
return;
}
if (e.shiftKey) {
let selection = window.getSelection();
let range = selection.getRangeAt(0);
let divElement = document.createElement('div');
let endContainer = range.endContainer;
let parentElement = endContainer.parentElement;
let newText = endContainer.textContent.substring(range.endOffset).trim();
endContainer.textContent = endContainer.textContent.substring(0, range.endOffset);
divElement.innerHTML = newText || '';
if (parentElement === this.$refs.content) {
// range.insertNode(divElement)
this.$refs.content.append(divElement);
} else {
parentElement.insertAdjacentElement('afterend', divElement);
}
// if (range.startContainer !== endContainer || range.startOffset !== range.endOffset) {
// console.log('delete range.', range.startContainer, range.startOffset, range.endContainer, range.endOffset)
// document.execCommand('delete', false, null);
// }
this.selectElement(divElement);
// return false;
} else {
if (this.compositionFlag) {
console.log('中文输入中')
return;
}
this.submit();
}
return;
}
if (e.keyCode === 90) {
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
e.stopPropagation();
if (this.history.length <= 1) {
return;
}
this.history.pop();
let last = this.history.pop();
// console.log('', last);
this.contentHtml = last;
if (this.history.length === 0) {
//
this.history.push(this.defaultContentHtml);
}
setTimeout(() => {
let t = this.$refs.content.lastElementChild.lastChild;
// t.focus();
let r = document.createRange();
r.setStart(t, t.textContent.length);
r.setEnd(t, t.textContent.length);
r.collapse();
// r.selectNodeContents(t.lastChild);
let selection = document.getSelection();
selection.removeAllRanges();
selection.addRange(r);
})
}
}
if (e.keyCode === 8) {
setTimeout(() => {
// console.log(this.$refs.content.innerHTML.trim())
let s = this.$refs.content.innerHTML.trim();
if (s === '' || s === '<br>') {
// dom
this.empty();
this.selectElement(this.$refs.content);
}
// this.
})
}
// console.log(e.keyCode)
if (this.atIng) {
console.log('atIng', e.keyCode)
e.preventDefault();
e.stopPropagation();
if (e.keyCode === 38) {
this.$refs.atBox.moveUp();
}
if (e.keyCode === 40) {
this.$refs.atBox.moveDown();
}
}
},
onAtSelect(member) {
this.atIng = false;
let range = window.getSelection().getRangeAt(0)
// @xx
range.setStart(this.blurRange.startContainer, this.focusOffset - 1 - this.atSearchText.length)
range.setEnd(this.blurRange.endContainer, this.focusOffset)
range.deleteContents()
//
let element = document.createElement('SPAN')
element.className = "chat-at-user";
element.dataset.id = member.userId;
element.contentEditable = 'false'
element.innerText = `@${member.aliasName}`
element.setAttribute("data-at-user-id", member.userId)
range.insertNode(element)
//
range.collapse()
//
let textNode = document.createTextNode('\u00A0');
range.insertNode(textNode)
range.selectNodeContents(textNode);
range.collapse()
this.atSearchText = "";
this.focus();
// this.selectElement(textNode);
// this.$refs.editBox.focus()
},
onEditorInput(e) {
// @
if (this.$props.groupMembers && !this.zhLock) {
if (e.data === '@') {
//
this.showAtBox(e);
} else {
let selection = window.getSelection()
// let range = selection.getRangeAt(0)
let focusNode = selection.focusNode;
// @
let stIdx = focusNode.textContent.lastIndexOf('@');
this.atSearchText = focusNode.textContent.substring(stIdx + 1);
}
}
},
onBlur(e) {
// setTimeout(() => {
// console.log(e)
// this.$refs.atBox.close();
// this.atIng = false;
// },100)
this.blurRange = window.getSelection().getRangeAt(0);
},
onMousedown() {
if (this.atIng) {
this.$refs.atBox.close();
this.atIng = false;
}
},
insertEmoji(emojiText) {
// let selection = window.getSelection();
// let range = selection.getRangeAt(0);
let emojiElement = document.createElement('img');
emojiElement.className = 'chat-emoji no-text';
emojiElement.setAttribute("data-emoji-code", emojiText);
emojiElement.src = this.$emo.textToUrl(emojiText);
let blurRange = this.blurRange;
if (blurRange.startContainer !== blurRange.endContainer || blurRange.startOffset !== blurRange.endOffset) {
blurRange.deleteContents();
}
blurRange.insertNode(emojiElement);
this.focus();
},
generateId() {
return this.currentId++;
},
createFile(filePush) {
let file = filePush.file;
let fileId = filePush.fileId;
let container = document.createElement('div');
container.className = 'chat-file-container no-text';
container.contentEditable = 'false';
container.setAttribute("data-file-id", fileId);
let left = document.createElement('div');
left.className = 'file-position-left';
container.appendChild(left);
let icon = document.createElement('div');
icon.className = 'file-icon';
icon.innerText = '?';
left.appendChild(icon);
let right = document.createElement('div');
right.className = 'file-position-right';
container.appendChild(right);
let fileName = document.createElement('div');
fileName.className = 'file-name';
fileName.innerText = file.name;
let fileSize = document.createElement('div');
fileSize.className = 'file-size';
fileSize.innerText = this.sizeConvert(file.size);
right.appendChild(fileName);
right.appendChild(fileSize);
return container;
},
sizeConvert(len) {
if (len < 1024) {
return len + 'B';
} else if (len < 1024 * 1024) {
return (len / 1024).toFixed(2) + 'KB';
} else if (len < 1024 * 1024 * 1024) {
return (len / 1024 / 1024).toFixed(2) + 'MB';
} else {
return (len / 1024 / 1024 / 1024).toFixed(2) + 'GB';
}
},
clear() {
this.empty();
this.imageList = [];
this.fileList = [];
},
empty() {
let emptyCount = Math.random() * 100 + 5;
let content = '';
for (let i = 0; i < emptyCount; i++) {
content += ' ';
}
this.contentHtml = this.defaultContentHtml + content;
},
showAtBox(e) {
this.atIng = true;
this.atSearchText = "";
let selection = window.getSelection()
let range = selection.getRangeAt(0)
//
// this.focusNode = selection.focusNode;
this.focusOffset = selection.focusOffset;
//
let pos = range.getBoundingClientRect();
this.$refs.atBox.open({
x: pos.x,
y: pos.y
})
},
submit() {
// console.log(this.content)
let nodes = this.$refs.content.childNodes;
let textList = [];
let imageList = [];
let fileList = [];
let fullList = [];
let tempText = '';
let each = (nodes) => {
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (!node) {
continue;
}
if (node.nodeType === 3) {
tempText += node.textContent;
continue;
}
let nodeName = node.nodeName.toLowerCase();
if (nodeName === 'script') {
continue;
}
let text = tempText.trim();
if (nodeName === 'img') {
let imgId = node.getAttribute('data-img-id');
if (imgId) {
if (text) {
fullList.push({
type: 'text',
content: text
})
}
fullList.push({
type: 'image',
content: this.imageList[imgId]
})
imageList.push(this.imageList[imgId]);
textList.push(text);
tempText = '';
} else {
let emojiCode = node.getAttribute('data-emoji-code');
tempText += emojiCode;
}
} else if (nodeName === 'div') {
let fileId = node.getAttribute('data-file-id');
//
if (fileId) {
if (text) {
fullList.push({
type: 'text',
content: text
})
}
fullList.push({
type: 'file',
content: this.fileList[fileId]
})
fileList.push(this.fileList[fileId]);
textList.push(text);
tempText = '';
} else {
tempText += '\n';
each(node.childNodes);
}
} else if (nodeName === 'span') {
let userId = node.getAttribute("data-at-user-id");
if (userId !== null && userId !== undefined) {
tempText += node.outerHTML;
}
} else {
console.warn('未处理的标签');
if (getComputedStyle(node).display === 'block') {
tempText += '\n';
} else {
tempText += ' ';
}
each(node.childNodes);
}
}
}
each(nodes)
let text = tempText.trim();
if (text !== '') {
fullList.push({
type: 'text',
content: text
})
textList.push(text);
}
// console.log(textList, imageList, fileList)
this.$emit('submit', fullList, textList, imageList, fileList);
},
focus() {
this.$refs.content.focus();
}
},
mounted() {
console.log(this.$props.groupMembers)
// this.$refs.content.firstElementChild.focus();
this.selectElement(this.$refs.content.firstElementChild);
setInterval(() => {
if (!this.$refs.content) {
return;
}
//
if (this.compositionFlag) {
return;
}
let last = this.history[this.history.length];
let newContent = this.$refs.content.innerHTML;
if (last !== newContent) {
this.history.push(newContent);
}
}, 1000);
}
}
</script>
<style lang="scss">
.chat-input-area {
width: 100%;
height: 100%;
position: relative;
.edit-chat-container {
//width: 100%;
//height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 1px solid #c3c3c3;
outline: none;
padding: 10px 0;
line-height: 30px;
font-size: 16px;
text-align: left;
> div {
padding-left: 10px;
}
> div:before {
content: "\00a0";
font-size: 14px;
}
.chat-image {
max-width: 200px;
max-height: 100px;
border: 1px solid #e6e6e6;
cursor: pointer;
//margin-left: 10px;
}
.chat-emoji {
width: 30px;
height: 30px;
vertical-align: top;
cursor: pointer;
}
.chat-file-container {
width: 200px;
//height: 100px;
padding: 5px 7px;
border: 1px solid #4cd964;
display: flex;
.file-position-left {
width: 30%;
flex: 1;
justify-content: center;
align-items: center;
.file-icon {
width: 30px;
height: 30px;
text-align: center;
justify-content: center;
align-items: center;
vertical-align: center;
border: 1px solid #e6e6e6;
}
}
.file-position-right {
width: 70%;
flex: 3;
.file-name {
font-size: 14px;
color: #333;
}
.file-size {
font-size: 12px;
color: #666;
}
}
}
.chat-at-user {
background-color: #4cd964;
padding: 2px 5px;
color: white;
//border: 1px solid #c3c3c3;
border-radius: 3px;
}
}
.edit-chat-container:empty:before {
content: '请输入消息(按Shift+Enter键换行)';
color: gray;
}
.edit-chat-container:focus:before {
content: none;
}
}
</style>

9
im-web/src/components/chat/ChatMessageItem.vue

@ -280,6 +280,7 @@
position: absolute;
left: -10px;
top: 13px;
z-index: -1;
width: 0;
height: 0;
border-style: solid dashed dashed;
@ -407,6 +408,14 @@
color: #329432;
}
}
.chat-at-user {
background-color: #4cd964;
padding: 2px 5px;
color: white;
//border: 1px solid #c3c3c3;
border-radius: 3px;
}
}
}

Loading…
Cancel
Save