mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-10 00:18:21 +00:00
perf: 消息输入框支持全屏输入
This commit is contained in:
parent
c2715f9b5e
commit
4957f32d06
@ -93,6 +93,10 @@
|
|||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
{{$L('上传文件')}}
|
{{$L('上传文件')}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="chat-input-popover-item" @click="onToolbar('full')">
|
||||||
|
<i class="taskfont"></i>
|
||||||
|
{{$L('全屏输入')}}
|
||||||
|
</div>
|
||||||
<div v-if="canAnon" class="chat-input-popover-item" @click="onToolbar('anon')">
|
<div v-if="canAnon" class="chat-input-popover-item" @click="onToolbar('anon')">
|
||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
{{$L('匿名消息')}}
|
{{$L('匿名消息')}}
|
||||||
@ -165,6 +169,22 @@
|
|||||||
<div class="record-cancel" @click.stop="stopRecord(true)">{{$L(touchLimitY ? '松开取消' : '向上滑动取消')}}</div>
|
<div class="record-cancel" @click.stop="stopRecord(true)">{{$L(touchLimitY ? '松开取消' : '向上滑动取消')}}</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
v-model="fullInput"
|
||||||
|
:value="true"
|
||||||
|
:mask-closable="false"
|
||||||
|
:beforeClose="onFullBeforeClose"
|
||||||
|
class-name="chat-input-full-input"
|
||||||
|
footer-hide
|
||||||
|
fullscreen>
|
||||||
|
<div class="chat-input-box">
|
||||||
|
<div class="chat-input-wrapper">
|
||||||
|
<div ref="editorFull" class="no-dark-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i slot="close" class="taskfont"></i>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -278,6 +298,9 @@ export default {
|
|||||||
isSpecVersion: this.checkIOSVersion(),
|
isSpecVersion: this.checkIOSVersion(),
|
||||||
|
|
||||||
timer: null,
|
timer: null,
|
||||||
|
|
||||||
|
fullInput: false,
|
||||||
|
fullQuill: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -641,61 +664,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mention: {
|
mention: this.quillMention()
|
||||||
allowedChars: /^\S*$/,
|
|
||||||
mentionDenotationChars: ["@", "#", "~"],
|
|
||||||
defaultMenuOrientation: this.defaultMenuOrientation,
|
|
||||||
isolateCharacter: true,
|
|
||||||
positioningStrategy: 'fixed',
|
|
||||||
renderItem: (data) => {
|
|
||||||
if (data.disabled === true) {
|
|
||||||
return `<div class="mention-item-disabled">${data.value}</div>`;
|
|
||||||
}
|
|
||||||
if (data.id === 0) {
|
|
||||||
return `<div class="mention-item-at">@</div><div class="mention-item-name">${data.value}</div><div class="mention-item-tip">${data.tip}</div>`;
|
|
||||||
}
|
|
||||||
if (data.avatar) {
|
|
||||||
const botHtml = data.bot ? `<div class="taskfont mention-item-bot"></div>` : ''
|
|
||||||
return `<div class="mention-item-img${data.online ? ' online' : ''}"><img src="${data.avatar}"/><em></em></div>${botHtml}<div class="mention-item-name">${data.value}</div>`;
|
|
||||||
}
|
|
||||||
if (data.tip) {
|
|
||||||
return `<div class="mention-item-name" title="${data.value}">${data.value}</div><div class="mention-item-tip">${data.tip}</div>`;
|
|
||||||
}
|
|
||||||
return `<div class="mention-item-name" title="${data.value}">${data.value}</div>`;
|
|
||||||
},
|
|
||||||
renderLoading: () => {
|
|
||||||
return "Loading...";
|
|
||||||
},
|
|
||||||
source: (searchTerm, renderList, mentionChar) => {
|
|
||||||
const mentionName = mentionChar == "@" ? 'user-mention' : (mentionChar == "#" ? 'task-mention' : 'file-mention');
|
|
||||||
const containers = document.getElementsByClassName("ql-mention-list-container");
|
|
||||||
for (let i = 0; i < containers.length; i++) {
|
|
||||||
containers[i].classList.remove("user-mention");
|
|
||||||
containers[i].classList.remove("task-mention");
|
|
||||||
containers[i].classList.remove("file-mention");
|
|
||||||
containers[i].classList.add(mentionName);
|
|
||||||
$A.scrollPreventThrough(containers[i]);
|
|
||||||
}
|
|
||||||
let mentionSourceCache = null;
|
|
||||||
this.getMentionSource(mentionChar, searchTerm, array => {
|
|
||||||
const values = [];
|
|
||||||
array.some(item => {
|
|
||||||
let list = item.list;
|
|
||||||
if (searchTerm) {
|
|
||||||
list = list.filter(({value}) => $A.strExists(value, searchTerm));
|
|
||||||
}
|
|
||||||
if (list.length > 0) {
|
|
||||||
item.label && values.push(...item.label)
|
|
||||||
values.push(...list)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if ($A.jsonStringify(values.map(({id}) => id)) !== mentionSourceCache) {
|
|
||||||
mentionSourceCache = $A.jsonStringify(values.map(({id}) => id))
|
|
||||||
renderList(values, searchTerm);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, this.options)
|
}, this.options)
|
||||||
|
|
||||||
@ -730,7 +699,7 @@ export default {
|
|||||||
if (this.maxlength > 0 && this.quill.getLength() > this.maxlength) {
|
if (this.maxlength > 0 && this.quill.getLength() > this.maxlength) {
|
||||||
this.quill.deleteText(this.maxlength, this.quill.getLength());
|
this.quill.deleteText(this.maxlength, this.quill.getLength());
|
||||||
}
|
}
|
||||||
let html = this.$refs.editor.children[0].innerHTML
|
let html = this.$refs.editor.firstChild.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.updateEmojiQuick(html)
|
||||||
@ -808,6 +777,64 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
quillMention() {
|
||||||
|
return {
|
||||||
|
allowedChars: /^\S*$/,
|
||||||
|
mentionDenotationChars: ["@", "#", "~"],
|
||||||
|
defaultMenuOrientation: this.defaultMenuOrientation,
|
||||||
|
isolateCharacter: true,
|
||||||
|
positioningStrategy: 'fixed',
|
||||||
|
renderItem: (data) => {
|
||||||
|
if (data.disabled === true) {
|
||||||
|
return `<div class="mention-item-disabled">${data.value}</div>`;
|
||||||
|
}
|
||||||
|
if (data.id === 0) {
|
||||||
|
return `<div class="mention-item-at">@</div><div class="mention-item-name">${data.value}</div><div class="mention-item-tip">${data.tip}</div>`;
|
||||||
|
}
|
||||||
|
if (data.avatar) {
|
||||||
|
const botHtml = data.bot ? `<div class="taskfont mention-item-bot"></div>` : ''
|
||||||
|
return `<div class="mention-item-img${data.online ? ' online' : ''}"><img src="${data.avatar}"/><em></em></div>${botHtml}<div class="mention-item-name">${data.value}</div>`;
|
||||||
|
}
|
||||||
|
if (data.tip) {
|
||||||
|
return `<div class="mention-item-name" title="${data.value}">${data.value}</div><div class="mention-item-tip">${data.tip}</div>`;
|
||||||
|
}
|
||||||
|
return `<div class="mention-item-name" title="${data.value}">${data.value}</div>`;
|
||||||
|
},
|
||||||
|
renderLoading: () => {
|
||||||
|
return "Loading...";
|
||||||
|
},
|
||||||
|
source: (searchTerm, renderList, mentionChar) => {
|
||||||
|
const mentionName = mentionChar == "@" ? 'user-mention' : (mentionChar == "#" ? 'task-mention' : 'file-mention');
|
||||||
|
const containers = document.getElementsByClassName("ql-mention-list-container");
|
||||||
|
for (let i = 0; i < containers.length; i++) {
|
||||||
|
containers[i].classList.remove("user-mention");
|
||||||
|
containers[i].classList.remove("task-mention");
|
||||||
|
containers[i].classList.remove("file-mention");
|
||||||
|
containers[i].classList.add(mentionName);
|
||||||
|
$A.scrollPreventThrough(containers[i]);
|
||||||
|
}
|
||||||
|
let mentionSourceCache = null;
|
||||||
|
this.getMentionSource(mentionChar, searchTerm, array => {
|
||||||
|
const values = [];
|
||||||
|
array.some(item => {
|
||||||
|
let list = item.list;
|
||||||
|
if (searchTerm) {
|
||||||
|
list = list.filter(({value}) => $A.strExists(value, searchTerm));
|
||||||
|
}
|
||||||
|
if (list.length > 0) {
|
||||||
|
item.label && values.push(...item.label)
|
||||||
|
values.push(...list)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if ($A.jsonStringify(values.map(({id}) => id)) !== mentionSourceCache) {
|
||||||
|
mentionSourceCache = $A.jsonStringify(values.map(({id}) => id))
|
||||||
|
renderList(values, searchTerm);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
updateEmojiQuick(text) {
|
updateEmojiQuick(text) {
|
||||||
if (!this.isFocus || !text) {
|
if (!this.isFocus || !text) {
|
||||||
this.emojiQuickShow = false
|
this.emojiQuickShow = false
|
||||||
@ -1099,6 +1126,10 @@ export default {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'full':
|
||||||
|
this.onFullInput()
|
||||||
|
break;
|
||||||
|
|
||||||
case 'image':
|
case 'image':
|
||||||
case 'file':
|
case 'file':
|
||||||
case 'call':
|
case 'call':
|
||||||
@ -1108,6 +1139,38 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onFullInput() {
|
||||||
|
if (this.disabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.fullInput = !this.fullInput;
|
||||||
|
//
|
||||||
|
if (this.fullInput) {
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
this.fullQuill = new Quill(this.$refs.editorFull, Object.assign({
|
||||||
|
theme: 'bubble',
|
||||||
|
readOnly: false,
|
||||||
|
placeholder: this.placeholder,
|
||||||
|
modules: {
|
||||||
|
toolbar: [
|
||||||
|
['bold', 'strike', 'italic', 'underline', {'list': 'ordered'}, {'list': 'bullet'}, 'blockquote', 'code-block']
|
||||||
|
],
|
||||||
|
mention: this.quillMention()
|
||||||
|
}
|
||||||
|
}, this.options))
|
||||||
|
this.fullQuill.enable(true)
|
||||||
|
this.$refs.editorFull.firstChild.innerHTML = this.$refs.editor.firstChild.innerHTML
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onFullBeforeClose() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.$refs.editor.firstChild.innerHTML = this.$refs.editorFull.firstChild.innerHTML
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
onMoreVisibleChange(v) {
|
onMoreVisibleChange(v) {
|
||||||
this.showMore = v;
|
this.showMore = v;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -605,6 +605,52 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-input-full-input {
|
||||||
|
.ivu-modal {
|
||||||
|
.ivu-modal-content {
|
||||||
|
margin-top: 46px;
|
||||||
|
border-top-left-radius: 18px !important;
|
||||||
|
border-top-right-radius: 18px !important;
|
||||||
|
.ivu-modal-body {
|
||||||
|
overflow: visible;
|
||||||
|
padding: 24px !important;
|
||||||
|
}
|
||||||
|
.ivu-modal-close {
|
||||||
|
> i {
|
||||||
|
top: 3px;
|
||||||
|
right: 2px;
|
||||||
|
font-size: 24px;
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input-box {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.chat-input-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.ql-container {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.ql-editor {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ql-mention-list-container {
|
.ql-mention-list-container {
|
||||||
width: auto;
|
width: auto;
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user