perf: 优化消息列表

This commit is contained in:
kuaifan 2022-05-12 15:10:21 +08:00
parent 1d4602db0b
commit a13bc3f0bd
6 changed files with 587 additions and 595 deletions

View File

@ -53,6 +53,7 @@
"vue-resize-observer": "^2.0.16",
"vue-router": "^3.5.3",
"vue-template-compiler": "^2.6.14",
"vue-virtual-scroller-hi": "^1.0.10-1",
"vuedraggable": "^2.24.3",
"vuex": "^3.6.2",
"webpack": "^5.69.1",

View File

@ -1,6 +1,6 @@
<template>
<div
v-if="dialogData && dialogData.id"
v-if="isReady"
class="dialog-wrapper"
@drop.prevent="chatPasteDrag($event, 'drag')"
@dragover.prevent="chatDragOver(true, $event)"
@ -51,42 +51,38 @@
</ETooltip>
</div>
</slot>
<ScrollerY
<DynamicScroller
ref="scroller"
class="dialog-scroller overlay-y"
:style="{opacity: visible ? 1 : 0}"
:auto-bottom="isAutoBottom"
@on-scroll="chatScroll"
static>
<div ref="manageList" class="dialog-list">
<ul>
<li v-if="dialogData.hasMorePages" class="history" @click="loadNextPage">{{$L('加载历史消息')}}</li>
<li v-else-if="dialogData.loading > 0 && dialogMsgList.length === 0" class="loading"><Loading/></li>
<li v-else-if="dialogMsgList.length === 0" class="nothing">{{$L('暂无消息')}}</li>
<li
v-for="item in dialogMsgList"
:id="'view_' + item.id"
:key="item.id"
:class="{self:item.userid == userId, 'history-tip': topId == item.id}">
<em v-if="topId == item.id" class="history-text">{{$L('历史消息')}}</em>
<div class="dialog-avatar">
<UserAvatar :userid="item.userid" :tooltipDisabled="item.userid == userId" :size="30"/>
</div>
<DialogView :msg-data="item" :dialog-type="dialogData.type"/>
</li>
<li
v-for="item in tempMsgList"
:id="'tmp_' + item.id"
:key="'tmp_' + item.id"
:class="{self:item.userid == userId}">
<div class="dialog-avatar">
<UserAvatar :userid="item.userid" :tooltipDisabled="item.userid == userId" :size="30"/>
</div>
<DialogView :msg-data="item" :dialog-type="dialogData.type"/>
</li>
</ul>
</div>
</ScrollerY>
:items="allMsgs"
:min-item-size="58"
@onScroll="onScroll"
class="dialog-scroller overlay-y">
<template #before>
<div v-if="dialogData.hasMorePages" class="dialog-item history" @click="loadNextPage">{{$L('加载历史消息')}}</div>
<div v-else-if="dialogData.loading > 0 && dialogMsgList.length === 0" class="dialog-item loading"><Loading/></div>
<div v-else-if="dialogMsgList.length === 0" class="dialog-item nothing">{{$L('暂无消息')}}</div>
</template>
<template v-slot="{ item, index, active }">
<DynamicScrollerItem
:item="item"
:active="active"
:size-dependencies="[item.msg]"
:data-index="index"
:data-active="active"
:class="{
'dialog-item': true,
'self': item.userid == userId,
'history-tip': topId == item.id
}"
@click.native="">
<em v-if="topId == item.id" class="history-text">{{$L('历史消息')}}</em>
<div class="dialog-avatar">
<UserAvatar :userid="item.userid" :tooltipDisabled="item.userid == userId" :size="30"/>
</div>
<DialogView :msg-data="item" :dialog-type="dialogData.type"/>
</DynamicScrollerItem>
</template>
</DynamicScroller>
<div :class="['dialog-footer', msgNew > 0 && dialogMsgList.length > 0 ? 'newmsg' : '']" @click="onActive">
<div class="dialog-newmsg" @click="onToBottom">{{$L('' + msgNew + '条新消息')}}</div>
<div class="dialog-input">
@ -161,19 +157,30 @@
</template>
<script>
import ScrollerY from "../../../components/ScrollerY";
import {mapState} from "vuex";
import DialogView from "./DialogView";
import DialogUpload from "./DialogUpload";
import {Store} from "le5le-store";
import UserInput from "../../../components/UserInput";
import DrawerOverlay from "../../../components/DrawerOverlay";
import DialogGroupInfo from "./DialogGroupInfo";
import ChatInput from "./ChatInput";
import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller-hi'
import 'vue-virtual-scroller-hi/dist/vue-virtual-scroller.css'
export default {
name: "DialogWrapper",
components: {ChatInput, DialogGroupInfo, DrawerOverlay, UserInput, DialogUpload, DialogView, ScrollerY},
components: {
DynamicScroller,
DynamicScrollerItem,
ChatInput,
DialogGroupInfo,
DrawerOverlay,
UserInput,
DialogUpload,
DialogView
},
props: {
dialogId: {
type: Number,
@ -183,21 +190,13 @@ export default {
data() {
return {
visible: true,
autoBottom: true,
autoInterval: null,
dialogDrag: false,
inputFocus: false,
msgText: '',
msgNew: 0,
topId: 0,
allMsgs: [],
tempMsgs: [],
dialogMsgSubscribe: null,
pasteShow: false,
pasteFile: [],
pasteItem: [],
@ -206,19 +205,17 @@ export default {
createGroupData: {},
createGroupLoad: 0,
dialogDrag: false,
groupInfoShow: false,
}
},
mounted() {
this.dialogMsgSubscribe = Store.subscribe('dialogMsgPush', this.addDialogMsg);
},
beforeDestroy() {
if (this.dialogMsgSubscribe) {
this.dialogMsgSubscribe.unsubscribe();
this.dialogMsgSubscribe = null;
}
},
computed: {
@ -230,12 +227,16 @@ export default {
'wsOpenNum',
]),
isReady() {
return this.dialogId > 0 && this.dialogData.id > 0
},
dialogData() {
return this.cacheDialogs.find(({id}) => id == this.dialogId) || {};
},
dialogMsgList() {
if (!this.dialogId) {
if (!this.isReady) {
return [];
}
return $A.cloneJSON(this.dialogMsgs.filter(({dialog_id}) => {
@ -245,15 +246,8 @@ export default {
});
},
isAutoBottom() {
if (this.inputFocus && !this.isDesktop) {
return false;
}
return this.autoBottom
},
tempMsgList() {
if (!this.dialogId) {
if (!this.isReady) {
return [];
}
return $A.cloneJSON(this.tempMsgs.filter(({dialog_id}) => {
@ -261,6 +255,14 @@ export default {
}));
},
allMsgList() {
const {dialogMsgList, tempMsgList} = this;
if (tempMsgList.length > 0) {
dialogMsgList.push(...tempMsgList);
}
return dialogMsgList;
},
peopleNum() {
return this.dialogData.type === 'group' ? $A.runNum(this.dialogData.people) : 0;
},
@ -313,20 +315,7 @@ export default {
if (id) {
this.msgNew = 0;
this.topId = -1;
this.visible = false;
if (this.dialogMsgList.length > 0) {
setTimeout(_ => {
this.onToBottom();
this.visible = true;
}, 10);
}
let startTime = new Date().getTime();
this.$store.dispatch("getDialogMsgs", id).then(_ => {
setTimeout(_ => {
this.onToBottom();
this.visible = true;
}, Math.max(0, 100 - (new Date().getTime() - startTime)));
});
this.$store.dispatch("getDialogMsgs", id).then(this.onToBottom).catch(_ => {});
}
},
immediate: true
@ -335,7 +324,21 @@ export default {
wsOpenNum(num) {
if (num <= 1) return
this.$store.dispatch("getDialogMsgs", this.dialogId).catch(_ => {});
}
},
allMsgList(newList, oldList) {
const {scrollE} = this.scrollInfo();
this.allMsgs = newList;
this.$nextTick(_ => {
if (scrollE > 10 && oldList.length > 0) {
const lastId = oldList[oldList.length - 1].id
const tmpList = newList.filter(item => item.id && item.id > lastId)
this.msgNew += tmpList.length
} else {
this.onToBottom();
}
})
},
},
methods: {
@ -353,6 +356,12 @@ export default {
}
msgText = msgText.replace(/<\/span> <\/p>$/, "</span></p>")
//
if (!this.isDesktop) {
this.$refs.input.blur();
}
this.onToBottom();
this.onActive();
//
let tempId = $A.randomString(16);
this.tempMsgs.push({
id: tempId,
@ -363,11 +372,6 @@ export default {
text: msgText,
},
});
if (!this.isDesktop) {
this.$refs.input.blur();
}
this.onToBottom();
this.onActive();
//
this.$store.dispatch("call", {
url: 'dialog/msg/sendtext',
@ -441,6 +445,12 @@ export default {
chatFile(type, file) {
switch (type) {
case 'progress':
if (!this.isDesktop) {
this.$refs.input.blur();
}
this.onToBottom();
this.onActive();
//
this.tempMsgs.push({
id: file.tempId,
dialog_id: this.dialogData.id,
@ -448,11 +458,6 @@ export default {
userid: this.userId,
msg: { },
});
if (!this.isDesktop) {
this.$refs.input.blur();
}
this.onToBottom();
this.onActive();
break;
case 'error':
@ -479,31 +484,11 @@ export default {
this.onActive();
},
chatScroll(res) {
switch (res.directionreal) {
case 'up':
if (res.scrollE < 10) {
this.msgNew = 0;
this.autoBottom = true;
}
break;
case 'down':
this.autoBottom = false;
break;
}
if (res.scale >= 1) {
this.msgNew = 0;
this.autoBottom = true;
}
},
onEventFocus(e) {
this.inputFocus = true;
this.$emit("on-focus", e)
},
onEventBlur(e) {
this.inputFocus = false;
this.$emit("on-blur", e)
},
@ -518,8 +503,10 @@ export default {
},
onToBottom() {
this.autoBottom = true;
this.$refs.scroller && this.$refs.scroller.autoToBottom();
this.msgNew = 0;
if (this.isReady) {
this.$refs.scroller.scrollToBottom();
}
},
openProject() {
@ -537,30 +524,18 @@ export default {
},
loadNextPage() {
let topId = this.dialogMsgList[0].id;
let tmpId = this.allMsgs[0].id;
this.$store.dispatch('getDialogMoreMsgs', this.dialogId).then(() => {
this.$nextTick(() => {
this.topId = topId;
$A.scrollToView(document.getElementById("view_" + topId), {
behavior: 'instant',
inline: 'start',
})
this.topId = tmpId;
const index = this.allMsgs.findIndex(({id}) => id == tmpId);
if (index > -1) {
this.$refs.scroller.scrollToItem(index);
}
});
}).catch(() => {})
},
addDialogMsg() {
if (this.isAutoBottom) {
this.$nextTick(this.onToBottom);
} else {
this.$nextTick(() => {
if (this.$refs.scroller && this.$refs.scroller.scrollInfo().scrollE > 10) {
this.msgNew++;
}
})
}
},
openCreateGroup() {
this.createGroupData = {
userids: this.dialogData.dialog_user ? [this.userId, this.dialogData.dialog_user.userid] : [this.userId],
@ -586,6 +561,36 @@ export default {
this.createGroupLoad--;
});
},
scrollInfo() {
if (!this.isReady) {
return {
scale: 0, //
scrollY: 0, //
scrollE: 0, //
}
}
const scrollerView = this.$refs.scroller.$el;
let wInnerH = scrollerView.clientHeight;
let wScrollY = scrollerView.scrollTop;
let bScrollH = scrollerView.scrollHeight;
this.scrollY = wScrollY;
return {
scale: wScrollY / (bScrollH - wInnerH),
scrollY: wScrollY,
scrollE: bScrollH - wInnerH - wScrollY,
}
},
onScroll() {
this.__onScroll && clearTimeout(this.__onScroll);
this.__onScroll = setTimeout(_ => {
const {scrollE} = this.scrollInfo();
if (scrollE <= 10) {
this.msgNew = 0;
}
}, 100)
},
}
}
</script>

View File

@ -179,37 +179,33 @@ body.dark-mode-reverse {
}
}
.dialog-scroller {
.dialog-list {
> ul {
> li {
.dialog-view {
.dialog-head {
.dialog-content {
background-color: #e1e1e1;
.content-text {
color: #ffffff;
.content-text {
> pre {
.mention {
color: #000000;
}
}
.dialog-item {
.dialog-view {
.dialog-head {
.dialog-content {
background-color: #e1e1e1;
.content-text {
color: #ffffff;
.content-text {
> pre {
.mention {
color: #000000;
}
}
}
}
}
&.self {
.dialog-view {
.dialog-head {
.dialog-content {
background-color: #8bcf70;
.content-text {
> pre {
.mention {
color: #000000;
}
}
}
}
&.self {
.dialog-view {
.dialog-head {
.dialog-content {
background-color: #8bcf70;
.content-text {
> pre {
.mention {
color: #000000;
}
}
}

View File

@ -180,478 +180,469 @@
}
.dialog-scroller {
position: relative;
flex: 1;
padding: 0 32px;
overflow: auto;
position: relative;
padding: 16px 32px 0;
.dialog-list {
> ul {
> li {
display: flex;
flex-direction: row;
align-items: flex-start;
list-style: none;
margin-bottom: 16px;
.dialog-item {
display: flex;
flex-direction: row;
align-items: flex-start;
list-style: none;
padding-bottom: 16px;
&:first-child {
margin-top: 16px;
}
.dialog-avatar {
position: relative;
margin-bottom: 20px;
flex-shrink: 0;
width: 30px;
height: 30px;
}
.dialog-avatar {
position: relative;
margin-bottom: 20px;
flex-shrink: 0;
width: 30px;
height: 30px;
}
.dialog-view {
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 0 0 0 8px;
position: relative;
.dialog-view {
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 0 0 0 8px;
position: relative;
&.text {
max-width: 70%;
}
&.text {
max-width: 70%;
}
&:hover {
.dialog-head {
.dialog-menu {
opacity: 1;
}
}
}
.dialog-username {
margin-bottom: 6px;
opacity: 0.8;
}
.dialog-head {
display: flex;
align-items: flex-start;
.dialog-content {
background-color: #F4F5F7;
padding: 8px;
min-width: 32px;
border-radius: 0 6px 6px 6px;
display: flex;
align-items: flex-start;
&.an-emoticon,
&.an-emoji,
&.two-emoji,
&.three-emoji {
background-color: transparent !important;
}
&.an-emoji {
.content-text {
> pre {
font-size: 72px;
line-height: 1;
}
}
}
&.two-emoji {
.content-text {
> pre {
font-size: 52px;
line-height: 1;
}
}
}
&.three-emoji {
.content-text {
> pre {
font-size: 32px;
line-height: 1;
}
}
}
.content-text {
color: #333333;
> pre {
display: block;
margin: 0;
padding: 0;
line-height: 1.5;
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-word;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
font-size: 14px;
ol,
ul {
li {
list-style-type: none;
&::before {
display: inline-block;
white-space: nowrap;
width: 1.2em;
color: #0088ff;
text-align: left;
margin-right: 0.2em;
}
}
}
ul {
li {
&::before {
content: '\2022';
font-weight: 900;
}
}
}
ol {
li {
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
counter-increment: list-0;
&:before {
content: counter(list-0, decimal) '. ';
}
}
}
blockquote {
border-left: 4px solid #ccc;
margin-bottom: 5px;
margin-top: 5px;
padding-left: 16px;
}
pre {
white-space: pre-wrap;
margin: 5px 0;
padding: 5px 10px;
border-radius: 3px;
background-color: #23241f;
color: #f8f8f2;
overflow: visible;
}
img {
cursor: pointer;
max-width: 220px;
max-height: 220px;
vertical-align: bottom;
&.emoticon {
max-width: 150px;
max-height: 150px;
}
}
.mention {
color: $flow-status-end-color;
background-color: transparent;
user-select: auto;
padding: 0;
margin: 0;
> span {
margin: 0;
}
&.task {
cursor: pointer;
}
&.me {
font-size: 13px;
font-weight: 600;
padding: 3px 4px;
color: #ffffff;
background-color: $primary-color;
}
}
}
}
.content-file {
&.file {
display: inline-block;
.file-box {
background-color: #ffffff;
display: flex;
align-items: center;
padding: 10px 14px;
border-radius: 3px;
width: 220px;
.file-thumb {
width: 36px;
}
.file-info {
margin-left: 12px;
display: flex;
flex-direction: column;
justify-content: center;
.file-name {
color: #333333;
font-size: 14px;
line-height: 18px;
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.file-size {
padding-top: 4px;
color: #666666;
font-size: 14px;
}
}
}
}
&.img {
padding: 0;
display: flex;
max-width: 220px;
max-height: 220px;
border-radius: 6px;
background-color: transparent;
overflow: hidden;
.file-img {
display: flex;
cursor: pointer;
}
}
}
.content-loading {
display: flex;
.common-loading {
width: 20px;
height: 20px;
margin: 4px;
}
}
.content-unknown {
text-decoration: underline;
}
}
.dialog-menu {
opacity: 0;
margin-left: 6px;
transition: all 0.3s;
.menu-icon {
display: flex;
align-items: center;
border-radius: 4px;
border: 1px solid #ddd;
background-color: #ffffff;
> i {
flex: 1;
display: inline-block;
padding: 4px 6px;
color: #999;
font-size: 13px;
cursor: pointer;
& + i {
border-left: 1px solid #ddd;
}
&:hover {
color: #777;
}
}
}
}
}
.dialog-foot {
display: flex;
align-items: center;
padding-top: 4px;
height: 21px;
line-height: 1;
.common-loading {
margin: 0 2px;
width: 10px;
height: 10px;
}
.time {
color: #bbbbbb;
font-size: 12px;
}
.done {
display: none;
margin-left: 4px;
transform: scale(0.9);
font-size: 12px;
color: $primary-color;
}
.percent {
display: none;
margin-left: 4px;
align-items: center;
cursor: pointer;
}
}
}
.dialog-action {
align-self: flex-start;
display: flex;
align-items: flex-start;
height: 100%;
> * {
margin: 0 5px;
}
}
&.history {
cursor: pointer;
justify-content: center;
font-size: 13px;
padding: 3px 0;
margin: 12px 0;
opacity: 0.6;
transition: opacity 0.2s;
&:hover {
&:hover {
.dialog-head {
.dialog-menu {
opacity: 1;
}
}
}
&.history-tip {
position: relative;
padding-top: 60px;
.dialog-username {
margin-bottom: 6px;
opacity: 0.8;
}
.history-text {
font-style: normal;
position: absolute;
top: 10px;
left: 50%;
height: 22px;
line-height: 22px;
padding: 0 48px;
text-align: center;
font-size: 12px;
border-radius: 2px;
background: #f5f5f5;
transform: translateX(-50%);
.dialog-head {
display: flex;
align-items: flex-start;
.dialog-content {
background-color: #F4F5F7;
padding: 8px;
min-width: 32px;
border-radius: 0 6px 6px 6px;
display: flex;
align-items: flex-start;
&.an-emoticon,
&.an-emoji,
&.two-emoji,
&.three-emoji {
background-color: transparent !important;
}
}
&.loading {
padding: 12px 0;
justify-content: center;
.common-loading {
margin: 0;
width: 18px;
height: 18px;
&.an-emoji {
.content-text {
> pre {
font-size: 72px;
line-height: 1;
}
}
}
}
&.nothing {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #999999;
}
&.two-emoji {
.content-text {
> pre {
font-size: 52px;
line-height: 1;
}
}
}
&.bottom {
height: 0;
margin: 0;
padding: 0;
}
&.three-emoji {
.content-text {
> pre {
font-size: 32px;
line-height: 1;
}
}
}
&.self {
flex-direction: row-reverse;
.content-text {
color: #333333;
.dialog-view {
align-items: flex-end;
margin: 0 8px 0 0;
> pre {
display: block;
margin: 0;
padding: 0;
line-height: 1.5;
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-word;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
font-size: 14px;
.dialog-head {
flex-direction: row-reverse;
ol,
ul {
li {
list-style-type: none;
.dialog-content {
background-color: $primary-color;
border-radius: 6px 0 6px 6px;
.content-text {
color: #ffffff;
> pre {
.mention {
color: #333333;
&.me {
font-size: 14px;
font-weight: normal;
padding: 3px 0;
background-color: transparent;
}
}
&::before {
display: inline-block;
white-space: nowrap;
width: 1.2em;
color: #0088ff;
text-align: left;
margin-right: 0.2em;
}
}
}
.content-file {
&.file {
background-color: #F4F5F7;
ul {
li {
&::before {
content: '\2022';
font-weight: 900;
}
}
}
ol {
li {
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
counter-increment: list-0;
&:before {
content: counter(list-0, decimal) '. ';
}
}
}
blockquote {
border-left: 4px solid #ccc;
margin-bottom: 5px;
margin-top: 5px;
padding-left: 16px;
}
pre {
white-space: pre-wrap;
margin: 5px 0;
padding: 5px 10px;
border-radius: 3px;
background-color: #23241f;
color: #f8f8f2;
overflow: visible;
}
img {
cursor: pointer;
max-width: 220px;
max-height: 220px;
vertical-align: bottom;
&.emoticon {
max-width: 150px;
max-height: 150px;
}
}
.mention {
color: $flow-status-end-color;
background-color: transparent;
user-select: auto;
padding: 0;
margin: 0;
> span {
margin: 0;
}
&.task {
cursor: pointer;
}
&.me {
font-size: 13px;
font-weight: 600;
padding: 3px 4px;
color: #ffffff;
background-color: $primary-color;
}
}
}
}
.content-file {
&.file {
display: inline-block;
.file-box {
background-color: #ffffff;
display: flex;
align-items: center;
padding: 10px 14px;
border-radius: 3px;
width: 220px;
.file-thumb {
width: 36px;
}
.file-info {
margin-left: 12px;
display: flex;
flex-direction: column;
justify-content: center;
.file-name {
color: #333333;
font-size: 14px;
line-height: 18px;
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
&.img {
border-radius: 6px;
.file-size {
padding-top: 4px;
color: #666666;
font-size: 14px;
}
}
}
}
&.img {
padding: 0;
display: flex;
max-width: 220px;
max-height: 220px;
border-radius: 6px;
background-color: transparent;
overflow: hidden;
.file-img {
display: flex;
cursor: pointer;
}
}
}
.content-loading {
display: flex;
.common-loading {
width: 20px;
height: 20px;
margin: 4px;
}
}
.content-unknown {
text-decoration: underline;
}
}
.dialog-menu {
opacity: 0;
margin-left: 6px;
transition: all 0.3s;
.menu-icon {
display: flex;
align-items: center;
border-radius: 4px;
border: 1px solid #ddd;
background-color: #ffffff;
> i {
flex: 1;
display: inline-block;
padding: 4px 6px;
color: #999;
font-size: 13px;
cursor: pointer;
& + i {
border-left: 1px solid #ddd;
}
&:hover {
color: #777;
}
}
}
}
}
.dialog-foot {
display: flex;
align-items: center;
padding-top: 4px;
height: 21px;
line-height: 1;
.common-loading {
margin: 0 2px;
width: 10px;
height: 10px;
}
.time {
color: #bbbbbb;
font-size: 12px;
}
.done {
display: none;
margin-left: 4px;
transform: scale(0.9);
font-size: 12px;
color: $primary-color;
}
.percent {
display: none;
margin-left: 4px;
align-items: center;
cursor: pointer;
}
}
}
.dialog-action {
align-self: flex-start;
display: flex;
align-items: flex-start;
height: 100%;
> * {
margin: 0 5px;
}
}
&.history {
cursor: pointer;
justify-content: center;
font-size: 13px;
padding: 3px 0;
margin: 12px 0;
opacity: 0.6;
transition: opacity 0.2s;
&:hover {
opacity: 1;
}
}
&.history-tip {
position: relative;
padding-top: 60px;
.history-text {
font-style: normal;
position: absolute;
top: 10px;
left: 50%;
height: 22px;
line-height: 22px;
padding: 0 48px;
text-align: center;
font-size: 12px;
border-radius: 2px;
background: #f5f5f5;
transform: translateX(-50%);
}
}
&.loading {
padding: 12px 0;
justify-content: center;
.common-loading {
margin: 0;
width: 18px;
height: 18px;
}
}
&.nothing {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #999999;
}
&.bottom {
height: 0;
margin: 0;
padding: 0;
}
&.self {
flex-direction: row-reverse;
.dialog-view {
align-items: flex-end;
margin: 0 8px 0 0;
.dialog-head {
flex-direction: row-reverse;
.dialog-content {
background-color: $primary-color;
border-radius: 6px 0 6px 6px;
.content-text {
color: #ffffff;
> pre {
.mention {
color: #333333;
&.me {
font-size: 14px;
font-weight: normal;
padding: 3px 0;
background-color: transparent;
}
}
}
.dialog-menu {
margin-left: 0;
margin-right: 6px;
}
}
.dialog-foot {
.done {
display: inline-block;
.content-file {
&.file {
background-color: #F4F5F7;
}
.percent {
display: flex;
&.img {
border-radius: 6px;
background-color: transparent;
}
}
}
.dialog-menu {
margin-left: 0;
margin-right: 6px;
}
}
.dialog-foot {
.done {
display: inline-block;
}
.percent {
display: flex;
}
}
}
}
@ -877,7 +868,8 @@
}
}
.dialog-scroller {
padding: 0 14px;
padding-right: 14px;
padding-left: 14px;
}
.dialog-footer {
background-color: #f8f8f8;

View File

@ -81,9 +81,6 @@
padding: 0 12px;
height: 64px;
}
.dialog-scroller {
padding: 0 14px;
}
}
}
}

View File

@ -637,7 +637,8 @@
}
.dialog-wrapper {
.dialog-scroller {
padding: 0 16px 0 32px
padding-right: 16px;
padding-left: 32px;
}
.dialog-footer {
padding: 0 14px 0 28px;
@ -672,7 +673,7 @@
min-width: 320px;
max-width: 450px;
border-left: 1px solid #f4f5f5;
.head {
&:before {
left: 18px;