mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-12 03:01:12 +00:00
perf: 右键或长按消息发送按钮可选无声发送、Markdown格式发送
This commit is contained in:
parent
1cef313689
commit
0aa6911159
@ -36,7 +36,7 @@
|
||||
@paste="handlePaste"></div>
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<ul class="chat-toolbar" @click.stop="">
|
||||
<ul class="chat-toolbar" @click.stop>
|
||||
<!-- 桌面端表情(漂浮) -->
|
||||
<li>
|
||||
<EPopover
|
||||
@ -101,22 +101,42 @@
|
||||
</li>
|
||||
|
||||
<!-- 发送按钮 -->
|
||||
<li class="chat-send" :class="sendClass" v-touchmouse="clickSend">
|
||||
<ETooltip placement="top" :disabled="windowSmall || $isEEUiApp" :content="$L(sendClass === 'recorder' ? '长按录音' : '发送')">
|
||||
<div v-if="loading">
|
||||
<div class="chat-load">
|
||||
<Loading/>
|
||||
<li
|
||||
ref="chatSend"
|
||||
class="chat-send"
|
||||
:class="sendClass"
|
||||
v-touchmouse="clickSend"
|
||||
v-longpress="{callback: longSend, delay: 300}">
|
||||
<EPopover
|
||||
v-model="showMenu"
|
||||
:visibleArrow="false"
|
||||
trigger="manual"
|
||||
placement="top"
|
||||
popperClass="chat-input-more-popover">
|
||||
<ETooltip slot="reference" ref="sendTip" placement="top" :disabled="windowSmall || $isEEUiApp || showMenu" :content="$L(sendContent)">
|
||||
<div v-if="loading">
|
||||
<div class="chat-load">
|
||||
<Loading/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<transition name="mobile-send">
|
||||
<i v-if="sendClass === 'recorder'" class="taskfont"></i>
|
||||
</transition>
|
||||
<transition name="mobile-send">
|
||||
<i v-if="sendClass !== 'recorder'" class="taskfont"></i>
|
||||
</transition>
|
||||
</div>
|
||||
</ETooltip>
|
||||
<div class="chat-input-popover-item" @click="onSend('silence')">
|
||||
<i class="taskfont"></i>
|
||||
{{$L('无声发送')}}
|
||||
</div>
|
||||
<div v-else>
|
||||
<transition name="mobile-send">
|
||||
<i v-if="sendClass === 'recorder'" class="taskfont"></i>
|
||||
</transition>
|
||||
<transition name="mobile-send">
|
||||
<i v-if="sendClass !== 'recorder'" class="taskfont"></i>
|
||||
</transition>
|
||||
<div class="chat-input-popover-item" @click="onSend('md')">
|
||||
<i class="taskfont"></i>
|
||||
{{$L('Markdown 格式发送')}}
|
||||
</div>
|
||||
</ETooltip>
|
||||
</EPopover>
|
||||
</li>
|
||||
|
||||
<!-- 录音效果 -->
|
||||
@ -156,12 +176,13 @@ import ChatEmoji from "./emoji";
|
||||
import touchmouse from "../../../../directives/touchmouse";
|
||||
import TransferDom from "../../../../directives/transfer-dom";
|
||||
import clickoutside from "../../../../directives/clickoutside";
|
||||
import longpress from "../../../../directives/longpress";
|
||||
import {Store} from "le5le-store";
|
||||
|
||||
export default {
|
||||
name: 'ChatInput',
|
||||
components: {ChatEmoji},
|
||||
directives: {touchmouse, TransferDom, clickoutside},
|
||||
directives: {touchmouse, TransferDom, clickoutside, longpress},
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number],
|
||||
@ -226,10 +247,12 @@ export default {
|
||||
taskList: null,
|
||||
fileList: {},
|
||||
|
||||
showMenu: false,
|
||||
showMore: false,
|
||||
showEmoji: false,
|
||||
emojiQuickTimer: null,
|
||||
|
||||
emojiQuickShow: false,
|
||||
emojiQuickTimer: null,
|
||||
emojiQuickKey: '',
|
||||
emojiQuickItems: [],
|
||||
|
||||
@ -356,6 +379,9 @@ export default {
|
||||
array.push('record-ready');
|
||||
}
|
||||
}
|
||||
if (this.showMenu) {
|
||||
array.push('show-menu');
|
||||
}
|
||||
if (this.showMore) {
|
||||
array.push('show-more');
|
||||
}
|
||||
@ -378,6 +404,20 @@ export default {
|
||||
return ''
|
||||
},
|
||||
|
||||
sendContent() {
|
||||
const {sendTip} = this.$refs
|
||||
if (sendTip && sendTip.$refs.popper) {
|
||||
sendTip.$refs.popper.style.visibility = 'hidden'
|
||||
sendTip.showPopper = false
|
||||
setTimeout(_ => {
|
||||
if (sendTip.$refs.popper) {
|
||||
sendTip.$refs.popper.style.visibility = 'visible'
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
return this.sendClass === 'recorder' ? '长按录音' : '发送'
|
||||
},
|
||||
|
||||
recordFormatDuration() {
|
||||
const {recordDuration} = this;
|
||||
let minute = Math.floor(recordDuration / 60000),
|
||||
@ -446,6 +486,24 @@ export default {
|
||||
this.loadInputDraft()
|
||||
},
|
||||
|
||||
showMenu(val) {
|
||||
if (val) {
|
||||
// this.showMenu = false;
|
||||
this.showMore = false;
|
||||
this.showEmoji = false;
|
||||
this.emojiQuickShow = false;
|
||||
}
|
||||
},
|
||||
|
||||
showMore(val) {
|
||||
if (val) {
|
||||
this.showMenu = false;
|
||||
// this.showMore = false;
|
||||
this.showEmoji = false;
|
||||
this.emojiQuickShow = false;
|
||||
}
|
||||
},
|
||||
|
||||
showEmoji(val) {
|
||||
if (this.emojiBottom) {
|
||||
if (val) {
|
||||
@ -466,7 +524,9 @@ export default {
|
||||
this.emojiQuickKey = "";
|
||||
}
|
||||
//
|
||||
this.showMenu = false;
|
||||
this.showMore = false;
|
||||
// this.showEmoji = false;
|
||||
this.emojiQuickShow = false;
|
||||
if (this.quill) {
|
||||
const range = this.quill.selection.savedRange;
|
||||
@ -478,11 +538,13 @@ export default {
|
||||
this.$emit('on-emoji-visible-change', val)
|
||||
},
|
||||
|
||||
showMore(val) {
|
||||
emojiQuickShow(val) {
|
||||
if (val) {
|
||||
this.showMenu = false;
|
||||
this.showMore = false;
|
||||
this.showEmoji = false;
|
||||
// this.emojiQuickShow = false;
|
||||
}
|
||||
this.$emit('on-more-visible-change', val)
|
||||
},
|
||||
|
||||
isFocus(val) {
|
||||
@ -787,6 +849,13 @@ export default {
|
||||
}, 100)
|
||||
},
|
||||
|
||||
getText() {
|
||||
if (this.quill) {
|
||||
return this.quill.getText()
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
setText(value) {
|
||||
if (this.quill) {
|
||||
this.quill.setText(value)
|
||||
@ -843,7 +912,7 @@ export default {
|
||||
this.touchLimitX = false;
|
||||
this.touchLimitY = false;
|
||||
this.touchStart = event.type === "touchstart" ? event.touches[0] : event;
|
||||
if (this.startRecord()) {
|
||||
if (event.button === 0 && this.startRecord()) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -855,6 +924,9 @@ export default {
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
if (this.showMenu) {
|
||||
return;
|
||||
}
|
||||
if (this.stopRecord(this.touchLimitY)) {
|
||||
return;
|
||||
}
|
||||
@ -866,10 +938,22 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
onSend() {
|
||||
longSend() {
|
||||
if (this.sendClass === 'recorder') {
|
||||
return;
|
||||
}
|
||||
this.showMenu = true;
|
||||
},
|
||||
|
||||
onSend(type) {
|
||||
this.hidePopover()
|
||||
this.rangeIndex = 0
|
||||
this.$store.state.messengerSearchKey = {dialog: '', contacts: ''}
|
||||
this.$emit('on-send')
|
||||
if (type) {
|
||||
this.$emit('on-send', null, type)
|
||||
} else {
|
||||
this.$emit('on-send')
|
||||
}
|
||||
},
|
||||
|
||||
startRecord() {
|
||||
@ -931,6 +1015,7 @@ export default {
|
||||
},
|
||||
|
||||
hidePopover() {
|
||||
this.showMenu = false;
|
||||
this.showMore = false;
|
||||
this.showEmoji = false;
|
||||
this.emojiQuickShow = false;
|
||||
|
||||
@ -1104,25 +1104,38 @@ export default {
|
||||
/**
|
||||
* 发送消息
|
||||
* @param text
|
||||
* @param type
|
||||
*/
|
||||
sendMsg(text) {
|
||||
let msgText;
|
||||
let emptied = false;
|
||||
sendMsg(text, type) {
|
||||
let textBody,
|
||||
textType = "text",
|
||||
silence = "no",
|
||||
emptied = false;
|
||||
if (typeof text === "string" && text) {
|
||||
msgText = text;
|
||||
textBody = text;
|
||||
} else {
|
||||
msgText = this.msgText;
|
||||
textBody = this.msgText;
|
||||
emptied = true;
|
||||
}
|
||||
if (msgText == '') {
|
||||
if (type === "md") {
|
||||
textBody = this.$refs.input.getText()
|
||||
textType = "md"
|
||||
} else if (type === "silence") {
|
||||
silence = "yes"
|
||||
}
|
||||
if (textBody == '') {
|
||||
this.inputFocus();
|
||||
return;
|
||||
}
|
||||
msgText = msgText.replace(/<\/span> <\/p>$/, "</span></p>")
|
||||
if (textType === "text") {
|
||||
textBody = textBody.replace(/<\/span> <\/p>$/, "</span></p>")
|
||||
}
|
||||
//
|
||||
if (this.quoteUpdate) {
|
||||
// 修改
|
||||
msgText = msgText.replace(new RegExp(`src=(["'])${$A.apiUrl('../')}`, "g"), "src=$1{{RemoteURL}}")
|
||||
if (textType === "text") {
|
||||
textBody = textBody.replace(new RegExp(`src=(["'])${$A.apiUrl('../')}`, "g"), "src=$1{{RemoteURL}}")
|
||||
}
|
||||
const update_id = this.quoteId
|
||||
this.$store.dispatch("setLoad", {
|
||||
key: `msg-${update_id}`,
|
||||
@ -1136,7 +1149,9 @@ export default {
|
||||
data: {
|
||||
dialog_id: this.dialogId,
|
||||
update_id,
|
||||
text: msgText,
|
||||
text: textBody,
|
||||
text_type: textType,
|
||||
silence,
|
||||
},
|
||||
method: 'post',
|
||||
complete: _ => this.$store.dispatch("cancelLoad", `msg-${update_id}`)
|
||||
@ -1148,7 +1163,7 @@ export default {
|
||||
});
|
||||
} else {
|
||||
// 发送
|
||||
const typeLoad = $A.stringLength(msgText.replace(/<img[^>]*?>/g, '')) > 5000
|
||||
const typeLoad = $A.stringLength(textBody.replace(/<img[^>]*?>/g, '')) > 5000
|
||||
const tempMsg = {
|
||||
id: this.getTempId(),
|
||||
dialog_id: this.dialogData.id,
|
||||
@ -1157,7 +1172,8 @@ export default {
|
||||
type: typeLoad ? 'loading' : 'text',
|
||||
userid: this.userId,
|
||||
msg: {
|
||||
text: typeLoad ? '' : msgText,
|
||||
text: typeLoad ? '' : textBody,
|
||||
type: textType,
|
||||
},
|
||||
}
|
||||
this.tempMsgs.push(tempMsg)
|
||||
@ -1171,7 +1187,9 @@ export default {
|
||||
data: {
|
||||
dialog_id: tempMsg.dialog_id,
|
||||
reply_id: tempMsg.reply_id,
|
||||
text: msgText,
|
||||
text: textBody,
|
||||
text_type: textType,
|
||||
silence,
|
||||
},
|
||||
method: 'post',
|
||||
}).then(({data}) => {
|
||||
@ -1179,7 +1197,7 @@ export default {
|
||||
this.sendSuccess(data)
|
||||
}).catch(error => {
|
||||
this.$set(tempMsg, 'error', true)
|
||||
this.$set(tempMsg, 'errorData', {type: 'text', content: error.msg, msg: msgText})
|
||||
this.$set(tempMsg, 'errorData', {type: 'text', content: error.msg, msg: textBody})
|
||||
});
|
||||
}
|
||||
if (emptied) {
|
||||
@ -2244,16 +2262,20 @@ export default {
|
||||
const {type} = this.operateItem
|
||||
this.onReply(type === 'text' ? 'update' : 'reply')
|
||||
if (type === 'text') {
|
||||
let {text} = this.operateItem.msg
|
||||
if (text.indexOf("mention") > -1) {
|
||||
text = text.replace(/<a class="mention file" href="([^'"]*)"([^>]*)>~([^>]*)<\/a>/g, '<span class="mention" data-denotation-char="~" data-id="$1" data-value="$3"><span contenteditable="false"><span class="ql-mention-denotation-char">~</span>$3</span></span>')
|
||||
text = text.replace(/<span class="mention ([^'"]*)" data-id="(\d+)">([@#])([^>]*)<\/span>/g, '<span class="mention" data-denotation-char="$3" data-id="$2" data-value="$4"><span contenteditable="false"><span class="ql-mention-denotation-char">$3</span>$4</span></span>')
|
||||
}
|
||||
text = text.replace(/<img[^>]*>/gi, match => {
|
||||
return match.replace(/(width|height)="\d+"\s*/ig, "");
|
||||
})
|
||||
let {text, type} = this.operateItem.msg
|
||||
this.$refs.input.setPasteMode(false)
|
||||
this.msgText = $A.formatMsgBasic(text)
|
||||
if (type === 'md') {
|
||||
this.$refs.input.setText(text)
|
||||
} else {
|
||||
if (text.indexOf("mention") > -1) {
|
||||
text = text.replace(/<a class="mention file" href="([^'"]*)"([^>]*)>~([^>]*)<\/a>/g, '<span class="mention" data-denotation-char="~" data-id="$1" data-value="$3"><span contenteditable="false"><span class="ql-mention-denotation-char">~</span>$3</span></span>')
|
||||
text = text.replace(/<span class="mention ([^'"]*)" data-id="(\d+)">([@#])([^>]*)<\/span>/g, '<span class="mention" data-denotation-char="$3" data-id="$2" data-value="$4"><span contenteditable="false"><span class="ql-mention-denotation-char">$3</span>$4</span></span>')
|
||||
}
|
||||
text = text.replace(/<img[^>]*>/gi, match => {
|
||||
return match.replace(/(width|height)="\d+"\s*/ig, "");
|
||||
})
|
||||
this.msgText = $A.formatMsgBasic(text)
|
||||
}
|
||||
this.$nextTick(_ => this.$refs.input.setPasteMode(true))
|
||||
}
|
||||
},
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.show-menu,
|
||||
&.show-more,
|
||||
&.show-emoji {
|
||||
.chat-input-wrapper {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user