mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-24 18:30:28 +00:00
feat: 聊天支持联想表情
This commit is contained in:
parent
c2d05fb846
commit
05b05883fd
@ -1,5 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chat-input-box" :class="boxClass" v-clickoutside="hidePopover">
|
<div class="chat-input-box" :class="boxClass" v-clickoutside="hidePopover">
|
||||||
|
<!-- 快速表情 -->
|
||||||
|
<div class="chat-input-quick-emoji">
|
||||||
|
<EPopover
|
||||||
|
ref="emojiQuickRef"
|
||||||
|
v-model="emojiQuickShow"
|
||||||
|
:visibleArrow="false"
|
||||||
|
transition=""
|
||||||
|
placement="top-end"
|
||||||
|
popperClass="chat-quick-emoji-popover">
|
||||||
|
<div slot="reference"></div>
|
||||||
|
<ul class="chat-quick-emoji-wrapper">
|
||||||
|
<li v-for="emoji in emojiQuickItems" @click="onEmojiQuick(emoji)">
|
||||||
|
<img :title="emoji.item.name" :alt="emoji.item.name" :src="emoji.item.src"/>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</EPopover>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="chat-input-wrapper" @click.stop="focus">
|
<div class="chat-input-wrapper" @click.stop="focus">
|
||||||
<!-- 回复 -->
|
<!-- 回复 -->
|
||||||
<div v-if="replyData" class="chat-reply">
|
<div v-if="replyData" class="chat-reply">
|
||||||
@ -210,6 +228,9 @@ export default {
|
|||||||
|
|
||||||
showMore: false,
|
showMore: false,
|
||||||
showEmoji: false,
|
showEmoji: false,
|
||||||
|
emojiQuickTimer: null,
|
||||||
|
emojiQuickShow: false,
|
||||||
|
emojiQuickItems: [],
|
||||||
|
|
||||||
observer: null,
|
observer: null,
|
||||||
wrapperWidth: 0,
|
wrapperWidth: 0,
|
||||||
@ -432,6 +453,7 @@ export default {
|
|||||||
if (val) {
|
if (val) {
|
||||||
this.$emit('on-focus')
|
this.$emit('on-focus')
|
||||||
this.hidePopover()
|
this.hidePopover()
|
||||||
|
this.updateEmojiQuick(this.value)
|
||||||
if (this.isSpecVersion) {
|
if (this.isSpecVersion) {
|
||||||
// ios11.0-11.3 对scrollTop及scrolIntoView解释有bug
|
// ios11.0-11.3 对scrollTop及scrolIntoView解释有bug
|
||||||
// 直接执行会导致输入框滚到底部被遮挡
|
// 直接执行会导致输入框滚到底部被遮挡
|
||||||
@ -498,6 +520,17 @@ export default {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'esc': {
|
||||||
|
key: 27,
|
||||||
|
shiftKey: false,
|
||||||
|
handler: _ => {
|
||||||
|
if (this.emojiQuickShow) {
|
||||||
|
this.emojiQuickShow = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -590,6 +623,7 @@ export default {
|
|||||||
let html = this.$refs.editor.children[0].innerHTML
|
let html = this.$refs.editor.children[0].innerHTML
|
||||||
html = html.replace(/^(<p>\s*<\/p>)+|(<p>\s*<\/p>)+$/gi, '')
|
html = html.replace(/^(<p>\s*<\/p>)+|(<p>\s*<\/p>)+$/gi, '')
|
||||||
html = html.replace(/^(<p><br\/*><\/p>)+|(<p><br\/*><\/p>)+$/gi, '')
|
html = html.replace(/^(<p><br\/*><\/p>)+|(<p><br\/*><\/p>)+$/gi, '')
|
||||||
|
this.updateEmojiQuick(html)
|
||||||
this._content = html
|
this._content = html
|
||||||
this.$emit('input', this._content)
|
this.$emit('input', this._content)
|
||||||
this.$nextTick(_ => {
|
this.$nextTick(_ => {
|
||||||
@ -662,6 +696,41 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateEmojiQuick(text) {
|
||||||
|
if (!this.isFocus) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.emojiQuickTimer && clearTimeout(this.emojiQuickTimer)
|
||||||
|
this.emojiQuickTimer = setTimeout(_ => {
|
||||||
|
text = text.replace(/<[^>]+>/g, "")
|
||||||
|
if (text
|
||||||
|
&& text.indexOf(" ") === -1
|
||||||
|
&& text.length >= 1
|
||||||
|
&& text.length <= 8
|
||||||
|
&& $A.isArray(window.emoticonData)) {
|
||||||
|
// 显示快捷选择表情窗口
|
||||||
|
this.emojiQuickItems = [];
|
||||||
|
window.emoticonData.some(data => {
|
||||||
|
let item = data.list.find(({name}) => $A.strExists(name, text))
|
||||||
|
if (item) {
|
||||||
|
this.emojiQuickItems.push({data, item})
|
||||||
|
if (this.emojiQuickItems.length >= 3) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.emojiQuickItems.length > 0) {
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.emojiQuickShow = true
|
||||||
|
this.$refs.emojiQuickRef.updatePopper()
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.emojiQuickShow = false
|
||||||
|
}, 100)
|
||||||
|
},
|
||||||
|
|
||||||
setText(value) {
|
setText(value) {
|
||||||
if (this.quill) {
|
if (this.quill) {
|
||||||
this.quill.setText(value)
|
this.quill.setText(value)
|
||||||
@ -832,6 +901,19 @@ export default {
|
|||||||
reader.readAsDataURL(this.recordBlob);
|
reader.readAsDataURL(this.recordBlob);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onEmojiQuick({data, item}) {
|
||||||
|
const baseUrl = $A.apiUrl("../images/emoticon")
|
||||||
|
const emoji = {
|
||||||
|
asset: `images/emoticon/${data.path}/${item.path}`,
|
||||||
|
name: item.name,
|
||||||
|
src: `${baseUrl}/${data.path}/${item.path}`
|
||||||
|
}
|
||||||
|
this.$emit('input', "")
|
||||||
|
this.$emit('on-send', `<img class="emoticon" data-asset="${emoji.asset}" data-name="${emoji.name}" src="${emoji.src}"/>`)
|
||||||
|
this.emojiQuickShow = false
|
||||||
|
this.focus()
|
||||||
|
},
|
||||||
|
|
||||||
onSelectEmoji(item) {
|
onSelectEmoji(item) {
|
||||||
if (!this.quill) {
|
if (!this.quill) {
|
||||||
return;
|
return;
|
||||||
@ -848,7 +930,9 @@ export default {
|
|||||||
}
|
}
|
||||||
} else if (item.type === 'emoticon') {
|
} else if (item.type === 'emoticon') {
|
||||||
this.$emit('on-send', `<img class="emoticon" data-asset="${item.asset}" data-name="${item.name}" src="${item.src}"/>`)
|
this.$emit('on-send', `<img class="emoticon" data-asset="${item.asset}" data-name="${item.name}" src="${item.src}"/>`)
|
||||||
// this.showEmoji = false;
|
if (this.windowLarge) {
|
||||||
|
this.showEmoji = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-input-quick-emoji {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 24px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-input-wrapper {
|
.chat-input-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -421,6 +431,27 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-quick-emoji-popover {
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
.chat-quick-emoji-wrapper {
|
||||||
|
display: flex;
|
||||||
|
> li {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
> img {
|
||||||
|
width: 72%;
|
||||||
|
height: 72%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chat-input-more-popover {
|
.chat-input-more-popover {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
@ -637,6 +668,9 @@
|
|||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.chat-input-box {
|
.chat-input-box {
|
||||||
|
.chat-input-quick-emoji {
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
.chat-input-wrapper {
|
.chat-input-wrapper {
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
padding-right: 6px;
|
padding-right: 6px;
|
||||||
|
|||||||
@ -605,6 +605,9 @@
|
|||||||
padding: 10px 4px 10px 6px;
|
padding: 10px 4px 10px 6px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
.chat-input-box {
|
.chat-input-box {
|
||||||
|
.chat-input-quick-emoji {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
.chat-input-wrapper {
|
.chat-input-wrapper {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #F4F5F7;
|
background-color: #F4F5F7;
|
||||||
@ -678,6 +681,11 @@
|
|||||||
}
|
}
|
||||||
.dialog-footer {
|
.dialog-footer {
|
||||||
padding: 0 0 0 24px;
|
padding: 0 0 0 24px;
|
||||||
|
.chat-input-box {
|
||||||
|
.chat-input-quick-emoji {
|
||||||
|
right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user