perf: 优化聊天窗口样式

This commit is contained in:
kuaifan 2022-05-25 09:20:47 +08:00
parent 85a9e33de1
commit fc5ce7c5db
5 changed files with 140 additions and 26 deletions

35
resources/assets/js/directives/touchmouse.js vendored Executable file
View File

@ -0,0 +1,35 @@
const isSupportTouch = "ontouchend" in document;
export default {
bind (el, binding) {
let isMove = false;
el.__touchMouseDown__ = e => {
isMove = false;
e.preventDefault();
};
el.__touchMouseMove__ = _ => {
isMove = true;
};
el.__touchMouseUp__ = e => {
if (isMove) {
return;
}
if (binding.expression) {
binding.value(e);
}
};
el.addEventListener(isSupportTouch ? 'touchstart' : 'mousedown', el.__touchMouseDown__);
el.addEventListener(isSupportTouch ? 'touchmove' : 'mousemove', el.__touchMouseMove__);
el.addEventListener(isSupportTouch ? 'touchend' : 'mouseup', el.__touchMouseUp__);
},
update () {
},
unbind (el) {
el.removeEventListener(isSupportTouch ? 'touchstart' : 'mousedown', el.__touchMouseDown__);
el.removeEventListener(isSupportTouch ? 'touchmove' : 'mousemove', el.__touchMouseMove__);
el.removeEventListener(isSupportTouch ? 'touchend' : 'mouseup', el.__touchMouseUp__);
delete el.__touchMouseDown__;
delete el.__touchMouseMove__;
delete el.__touchMouseUp__;
}
};

View File

@ -40,10 +40,12 @@
</div> </div>
</EPopover> </EPopover>
<div class="toolbar-spacing"></div> <ETooltip placement="top" :disabled="!$isDesktop" :content="$L('发送')">
<div class="chat-send" :class="[value ? '' : 'disabled']" v-touchmouse="send">
<Loading v-if="loading"/> <Loading v-if="loading"/>
<ETooltip v-else placement="top" :disabled="!$isDesktop" :content="$L('发送')"><Icon :class="[value ? '' : 'disabled']" type="md-send" @click="send"/></ETooltip> <Icon v-else type="md-send"/>
</div>
</ETooltip>
<slot name="toolbarAfter"/> <slot name="toolbarAfter"/>
</div> </div>
@ -51,15 +53,16 @@
</template> </template>
<script> <script>
import {mapGetters, mapState} from "vuex"; import {mapState} from "vuex";
import Quill from 'quill'; import Quill from 'quill';
import "quill-mention"; import "quill-mention";
import ChatEmoji from "./emoji"; import ChatEmoji from "./emoji";
import touchmouse from "../../../../directives/touchmouse";
export default { export default {
name: 'ChatInput', name: 'ChatInput',
components: {ChatEmoji}, components: {ChatEmoji},
directives: {touchmouse},
props: { props: {
dialogId: { dialogId: {
type: Number, type: Number,
@ -87,7 +90,9 @@ export default {
}, },
enterSend: { enterSend: {
type: Boolean, type: Boolean,
default: true default: () => {
return $A.$isDesktop
}
}, },
options: { options: {
type: Object, type: Object,
@ -337,14 +342,26 @@ export default {
} }
let html = this.$refs.editor.children[0].innerHTML let html = this.$refs.editor.children[0].innerHTML
html = html.replace(/^(<p><br><\/p>)+|(<p><br><\/p>)+$/gi, '') html = html.replace(/^(<p><br><\/p>)+|(<p><br><\/p>)+$/gi, '')
const quill = this.quill
const text = this.quill.getText()
this._content = html this._content = html
this.$emit('input', this._content) this.$emit('input', this._content)
this.$emit('on-change', { html, text, quill }) this.$nextTick(_ => {
const range = this.quill.getSelection();
if (range) {
const endText = this.quill.getText(range.index);
/\n\n/.test(endText) && this.quill.deleteText(range.index, 1);
}
})
}) })
// Emit ready event // Clipboard Matcher ()
this.quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
delta.ops = delta.ops.map(op => ({
insert: op.insert
}))
return delta
})
// Ready event
this.$emit('on-ready', this.quill) this.$emit('on-ready', this.quill)
}, },
@ -390,6 +407,9 @@ export default {
}, },
send() { send() {
if (this.loading) {
return;
}
this.$emit('on-send') this.$emit('on-send')
}, },

View File

@ -72,6 +72,7 @@
</div> </div>
</div> </div>
<Badge class="dialog-num" :count="$A.getDialogUnread(dialog)"/> <Badge class="dialog-num" :count="$A.getDialogUnread(dialog)"/>
<div class="dialog-split"></div>
</li> </li>
</ul> </ul>
<ul v-else class="contacts"> <ul v-else class="contacts">

View File

@ -221,16 +221,6 @@
width: 170px; width: 170px;
height: 28px; height: 28px;
padding: 0 2px; padding: 0 2px;
.common-loading {
width: 18px;
height: 18px;
}
.toolbar-spacing {
width: 1px;
height: 14px;
margin: 2px 7px 0;
background-color: #cccccc;
}
> i { > i {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
@ -240,8 +230,73 @@
&.disabled { &.disabled {
opacity: 0.5; opacity: 0.5;
} }
&:last-child { }
margin-right: -5px; .chat-send {
display: flex;
align-items: center;
justify-content: flex-end;
cursor: pointer;
font-size: 20px;
padding-right: 16px;
margin: 0 -16px 0 7px;
height: 48px;
width: 48px;
position: relative;
.common-loading {
width: 18px;
height: 18px;
padding: 0;
margin: 0 1px;
}
> i {
position: static;
z-index: 2;
display: flex;
align-items: center;
height: 100%;
color: #ffffff;
transition: all 0.3s;
}
&:after {
position: absolute;
content: "";
left: 0;
z-index: 1;
width: 1px;
height: 14px;
background-color: #cccccc;
transition: all 0.3s ease;
transform: scale(0);
opacity: 0;
}
&:before {
position: absolute;
content: "";
left: 2px;
z-index: 1;
border-radius: 50%;
background-color: #8bcf70;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
transition: all 0.3s ease;
transform: scale(1);
opacity: 1;
}
&.disabled {
> i {
color: rgba($primary-text-color, 0.5);
}
&:after {
transform: scale(1);
opacity: 1;
}
&:before {
transform: scale(0);
opacity: 0;
}
} }
} }
.el-tooltip.taskfont { .el-tooltip.taskfont {

View File

@ -219,6 +219,9 @@
left: 42px; left: 42px;
transform: scale(0.8); transform: scale(0.8);
} }
.dialog-split {
display: none;
}
&.top { &.top {
background-color: #EEEFF1; background-color: #EEEFF1;
} }
@ -432,8 +435,8 @@
> ul { > ul {
&.dialog { &.dialog {
> li { > li {
&:after { .dialog-split {
content: ""; display: block;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
@ -443,7 +446,7 @@
transform: scaleY(0.5); transform: scaleY(0.5);
} }
&:last-child { &:last-child {
&:after { .dialog-split {
display: none; display: none;
} }
} }