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