|
|
@ -1,49 +1,54 @@ |
|
|
<template> |
|
|
<template> |
|
|
<view class="page chat-box"> |
|
|
<view class="page chat-box"> |
|
|
<nav-bar back more @more="onShowMore">{{ title }}</nav-bar> |
|
|
<nav-bar back more @more="onShowMore">{{ title }}</nav-bar> |
|
|
<view class="chat-msg" @click="switchChatTabBox('none', true)"> |
|
|
<view class="chat-main-box" :style="{height: chatMainHeight+'px'}"> |
|
|
<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop" |
|
|
<view class="chat-msg" @click="switchChatTabBox('none')"> |
|
|
:scroll-into-view="'chat-item-' + scrollMsgIdx"> |
|
|
<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop" |
|
|
<view v-if="chat" v-for="(msgInfo, idx) in chat.messages" :key="idx"> |
|
|
:scroll-into-view="'chat-item-' + scrollMsgIdx"> |
|
|
<chat-message-item v-if="idx >= showMinIdx" :headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)" |
|
|
<view v-if="chat" v-for="(msgInfo, idx) in chat.messages" :key="idx"> |
|
|
:showName="showName(msgInfo)" @recall="onRecallMessage" @copy="onCopyMessage" |
|
|
<chat-message-item v-if="idx >= showMinIdx" :headImage="headImage(msgInfo)" |
|
|
@delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile" |
|
|
@call="onRtCall(msgInfo)" :showName="showName(msgInfo)" @recall="onRecallMessage" |
|
|
:id="'chat-item-' + idx" :msgInfo="msgInfo" :groupMembers="groupMembers"> |
|
|
@copy="onCopyMessage" @delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)" |
|
|
</chat-message-item> |
|
|
@download="onDownloadFile" :id="'chat-item-' + idx" :msgInfo="msgInfo" |
|
|
</view> |
|
|
:groupMembers="groupMembers"> |
|
|
</scroll-view> |
|
|
</chat-message-item> |
|
|
</view> |
|
|
|
|
|
<view v-if="atUserIds.length > 0" class="chat-at-bar" @click="openAtBox()"> |
|
|
|
|
|
<view class="iconfont icon-at">: </view> |
|
|
|
|
|
<scroll-view v-if="atUserIds.length > 0" class="chat-at-scroll-box" scroll-x="true" scroll-left="120"> |
|
|
|
|
|
<view class="chat-at-items"> |
|
|
|
|
|
<view v-for="m in atUserItems" class="chat-at-item"> |
|
|
|
|
|
<head-image :name="m.showNickName" :url="m.headImage" size="minier"></head-image> |
|
|
|
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
</scroll-view> |
|
|
</scroll-view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="send-bar"> |
|
|
|
|
|
<view v-if="!showRecord" class="iconfont icon-voice-circle" @click="onRecorderInput()"></view> |
|
|
|
|
|
<view v-else class="iconfont icon-keyboard" @click="onKeyboardInput()"></view> |
|
|
|
|
|
<chat-record v-if="showRecord" class="chat-record" @send="onSendRecord"></chat-record> |
|
|
|
|
|
<view v-else class="send-text"> |
|
|
|
|
|
<textarea class="send-text-area" v-model="sendText" auto-height :show-confirm-bar="false" |
|
|
|
|
|
:placeholder="isReceipt ? '[回执消息]' : ''" :adjust-position="false" @confirm="sendTextMessage()" |
|
|
|
|
|
@keyboardheightchange="onKeyboardheightchange" @input="onTextInput" confirm-type="send" confirm-hold |
|
|
|
|
|
:hold-keyboard="true"></textarea> |
|
|
|
|
|
</view> |
|
|
</view> |
|
|
<view v-if="chat && chat.type == 'GROUP'" class="iconfont icon-at" @click="openAtBox()"></view> |
|
|
<view v-if="atUserIds.length > 0" class="chat-at-bar" @click="openAtBox()"> |
|
|
<view class="iconfont icon-icon_emoji" @click="onShowEmoChatTab()"></view> |
|
|
<view class="iconfont icon-at">: </view> |
|
|
<view v-if="sendText == ''" class="iconfont icon-add" @click="onShowToolsChatTab()"> |
|
|
<scroll-view v-if="atUserIds.length > 0" class="chat-at-scroll-box" scroll-x="true" scroll-left="120"> |
|
|
|
|
|
<view class="chat-at-items"> |
|
|
|
|
|
<view v-for="m in atUserItems" class="chat-at-item"> |
|
|
|
|
|
<head-image :name="m.showNickName" :url="m.headImage" size="minier"></head-image> |
|
|
|
|
|
</view> |
|
|
|
|
|
</view> |
|
|
|
|
|
</scroll-view> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view class="send-bar"> |
|
|
|
|
|
<view v-if="!showRecord" class="iconfont icon-voice-circle" @click="onRecorderInput()"></view> |
|
|
|
|
|
<view v-else class="iconfont icon-keyboard" @click="onKeyboardInput()"></view> |
|
|
|
|
|
<chat-record v-if="showRecord" class="chat-record" @send="onSendRecord"></chat-record> |
|
|
|
|
|
<view v-else class="send-text"> |
|
|
|
|
|
<editor id="editor" class="send-text-area" :placeholder="isReceipt ? '[回执消息]' : ''" |
|
|
|
|
|
:read-only="isReadOnly" @focus="onEditorFocus" @blur="onEditorBlur" @ready="onEditorReady" |
|
|
|
|
|
@input="onTextInput"> |
|
|
|
|
|
</editor> |
|
|
|
|
|
<!-- <textarea class="send-text-area" v-model="sendText" auto-height :show-confirm-bar="false" |
|
|
|
|
|
:placeholder="isReceipt ? '[回执消息]' : ''" :adjust-position="false" @confirm="sendTextMessage()" |
|
|
|
|
|
@keyboardheightchange="onKeyboardheightchange" @input="onTextInput" confirm-type="send" |
|
|
|
|
|
confirm-hold :hold-keyboard="true"></textarea> --> |
|
|
|
|
|
</view> |
|
|
|
|
|
<view v-if="chat && chat.type == 'GROUP'" class="iconfont icon-at" @click="openAtBox()"></view> |
|
|
|
|
|
<view class="iconfont icon-icon_emoji" @click="onShowEmoChatTab()"></view> |
|
|
|
|
|
<view v-if="isEmpty" class="iconfont icon-add" @click="onShowToolsChatTab()"> |
|
|
|
|
|
</view> |
|
|
|
|
|
<button v-if="!isEmpty || atUserIds.length > 0" class="btn-send" type="primary" |
|
|
|
|
|
@touchend.prevent="sendTextMessage()" size="mini">发送</button> |
|
|
</view> |
|
|
</view> |
|
|
<button v-if="sendText != '' || atUserIds.length > 0" class="btn-send" type="primary" |
|
|
|
|
|
@touchend.prevent="sendTextMessage()" size="mini">发送</button> |
|
|
|
|
|
</view> |
|
|
</view> |
|
|
|
|
|
<view class="chat-tab-bar"> |
|
|
<view class="chat-tab-bar" v-show="chatTabBox != 'none' || (showKeyBoard && !isH5)" |
|
|
<view v-if="chatTabBox == 'tools'" class="chat-tools" :style="{height: keyboardHeight+'px'}"> |
|
|
:style="{ height: `${keyboardHeight}px` }"> |
|
|
|
|
|
<view v-if="chatTabBox == 'tools'" class="chat-tools"> |
|
|
|
|
|
<view class="chat-tools-item"> |
|
|
<view class="chat-tools-item"> |
|
|
<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore" |
|
|
<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore" |
|
|
:onSuccess="onUploadImageSuccess" :onError="onUploadImageFail"> |
|
|
:onSuccess="onUploadImageSuccess" :onError="onUploadImageFail"> |
|
|
@ -60,7 +65,7 @@ |
|
|
</view> |
|
|
</view> |
|
|
|
|
|
|
|
|
<view class="chat-tools-item"> |
|
|
<view class="chat-tools-item"> |
|
|
<file-upload :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess" |
|
|
<file-upload ref="fileUpload" :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess" |
|
|
:onError="onUploadFileFail"> |
|
|
:onError="onUploadFileFail"> |
|
|
<view class="tool-icon iconfont icon-folder"></view> |
|
|
<view class="tool-icon iconfont icon-folder"></view> |
|
|
</file-upload> |
|
|
</file-upload> |
|
|
@ -91,9 +96,10 @@ |
|
|
</view> |
|
|
</view> |
|
|
<!-- #endif --> |
|
|
<!-- #endif --> |
|
|
</view> |
|
|
</view> |
|
|
<scroll-view v-if="chatTabBox === 'emo'" class="chat-emotion" scroll-y="true"> |
|
|
<scroll-view v-if="chatTabBox === 'emo'" class="chat-emotion" scroll-y="true" |
|
|
|
|
|
:style="{height: keyboardHeight+'px'}"> |
|
|
<view class="emotion-item-list"> |
|
|
<view class="emotion-item-list"> |
|
|
<image class="emotion-item" :title="emoText" :src="$emo.textToPath(emoText)" |
|
|
<image class="emotion-item emoji-large" :title="emoText" :src="$emo.textToPath(emoText)" |
|
|
v-for="(emoText, i) in $emo.emoTextList" :key="i" @click="selectEmoji(emoText)" mode="aspectFit" |
|
|
v-for="(emoText, i) in $emo.emoTextList" :key="i" @click="selectEmoji(emoText)" mode="aspectFit" |
|
|
lazy-load="true"></image> |
|
|
lazy-load="true"></image> |
|
|
</view> |
|
|
</view> |
|
|
@ -122,29 +128,31 @@ export default { |
|
|
friend: {}, |
|
|
friend: {}, |
|
|
group: {}, |
|
|
group: {}, |
|
|
groupMembers: [], |
|
|
groupMembers: [], |
|
|
sendText: "", |
|
|
|
|
|
isReceipt: false, // 是否回执消息 |
|
|
isReceipt: false, // 是否回执消息 |
|
|
scrollMsgIdx: 0, // 滚动条定位为到哪条消息 |
|
|
scrollMsgIdx: 0, // 滚动条定位为到哪条消息 |
|
|
chatTabBox: 'none', |
|
|
chatTabBox: 'none', |
|
|
showKeyBoard: false, |
|
|
|
|
|
showRecord: false, |
|
|
showRecord: false, |
|
|
keyboardHeight: 322, |
|
|
keyboardHeight: 300, |
|
|
atUserIds: [], |
|
|
atUserIds: [], |
|
|
needScrollToBottom: false, // 需要滚动到底部 |
|
|
needScrollToBottom: false, // 需要滚动到底部 |
|
|
showMinIdx: 0, // 下标小于showMinIdx的消息不显示,否则可能很卡 |
|
|
showMinIdx: 0, // 下标小于showMinIdx的消息不显示,否则可能很卡 |
|
|
reqQueue: [], // 请求队列 |
|
|
reqQueue: [], // 请求队列 |
|
|
isSending: false, // 是否正在发送请求 |
|
|
isSending: false, // 是否正在发送请求 |
|
|
isH5: false // h5键盘会强制推起页面,有些地方要区别对待 |
|
|
isShowKeyBoard: false, // 键盘是否正在弹起 |
|
|
|
|
|
editorCtx: null, // 编辑器上下文 |
|
|
|
|
|
isEmpty: true, // 编辑器是否为空 |
|
|
|
|
|
isFocus: false, // 编辑器是否焦点 |
|
|
|
|
|
isReadOnly: false // 编辑器是否只读 |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
methods: { |
|
|
methods: { |
|
|
onRecorderInput() { |
|
|
onRecorderInput() { |
|
|
this.showRecord = true; |
|
|
this.showRecord = true; |
|
|
this.switchChatTabBox('none', true); |
|
|
this.switchChatTabBox('none'); |
|
|
}, |
|
|
}, |
|
|
onKeyboardInput() { |
|
|
onKeyboardInput() { |
|
|
this.showRecord = false; |
|
|
this.showRecord = false; |
|
|
this.switchChatTabBox('none', false); |
|
|
this.switchChatTabBox('none'); |
|
|
}, |
|
|
}, |
|
|
onSendRecord(data) { |
|
|
onSendRecord(data) { |
|
|
let msgInfo = { |
|
|
let msgInfo = { |
|
|
@ -250,35 +258,49 @@ export default { |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
sendTextMessage() { |
|
|
sendTextMessage() { |
|
|
if (!this.sendText.trim() && this.atUserIds.length == 0) { |
|
|
this.editorCtx.getContents({ |
|
|
return uni.showToast({ |
|
|
success: (e) => { |
|
|
title: "不能发送空白信息", |
|
|
let sendText = this.isReceipt ? "【回执消息】" : ""; |
|
|
icon: "none" |
|
|
e.delta.ops.forEach((op) => { |
|
|
}); |
|
|
if (op.insert.image) { |
|
|
} |
|
|
// emo表情 |
|
|
let receiptText = this.isReceipt ? "【回执消息】" : ""; |
|
|
sendText += `#${op.attributes.alt};` |
|
|
let atText = this.createAtText(); |
|
|
} else( |
|
|
let msgInfo = { |
|
|
// 文字 |
|
|
content: receiptText + this.sendText + atText, |
|
|
sendText += op.insert |
|
|
atUserIds: this.atUserIds, |
|
|
) |
|
|
receipt: this.isReceipt, |
|
|
}) |
|
|
type: 0 |
|
|
if (!sendText.trim() && this.atUserIds.length == 0) { |
|
|
} |
|
|
return uni.showToast({ |
|
|
this.sendText = ""; |
|
|
title: "不能发送空白信息", |
|
|
// 填充对方id |
|
|
icon: "none" |
|
|
this.fillTargetId(msgInfo, this.chat.targetId); |
|
|
}); |
|
|
this.sendMessageRequest(msgInfo).then((m) => { |
|
|
} |
|
|
m.selfSend = true; |
|
|
let receiptText = this.isReceipt ? "【回执消息】" : ""; |
|
|
this.chatStore.insertMessage(m); |
|
|
let atText = this.createAtText(); |
|
|
// 会话置顶 |
|
|
let msgInfo = { |
|
|
this.moveChatToTop(); |
|
|
content: receiptText + sendText + atText, |
|
|
}).finally(() => { |
|
|
atUserIds: this.atUserIds, |
|
|
// 滚动到底部 |
|
|
receipt: this.isReceipt, |
|
|
this.scrollToBottom(); |
|
|
type: 0 |
|
|
// 清空@用户列表 |
|
|
} |
|
|
this.atUserIds = []; |
|
|
// 填充对方id |
|
|
this.isReceipt = false; |
|
|
this.fillTargetId(msgInfo, this.chat.targetId); |
|
|
}); |
|
|
this.sendMessageRequest(msgInfo).then((m) => { |
|
|
|
|
|
m.selfSend = true; |
|
|
|
|
|
this.chatStore.insertMessage(m, this.chat); |
|
|
|
|
|
// 会话置顶 |
|
|
|
|
|
this.moveChatToTop(); |
|
|
|
|
|
}).finally(() => { |
|
|
|
|
|
// 滚动到底部 |
|
|
|
|
|
this.scrollToBottom(); |
|
|
|
|
|
// 清空编辑框数据 |
|
|
|
|
|
this.atUserIds = []; |
|
|
|
|
|
this.isReceipt = false; |
|
|
|
|
|
this.editorCtx.clear(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
}, |
|
|
}, |
|
|
createAtText() { |
|
|
createAtText() { |
|
|
let atText = ""; |
|
|
let atText = ""; |
|
|
@ -325,31 +347,35 @@ export default { |
|
|
}, |
|
|
}, |
|
|
onShowEmoChatTab() { |
|
|
onShowEmoChatTab() { |
|
|
this.showRecord = false; |
|
|
this.showRecord = false; |
|
|
this.switchChatTabBox('emo', true) |
|
|
this.switchChatTabBox('emo') |
|
|
}, |
|
|
}, |
|
|
onShowToolsChatTab() { |
|
|
onShowToolsChatTab() { |
|
|
this.showRecord = false; |
|
|
this.showRecord = false; |
|
|
this.switchChatTabBox('tools', true) |
|
|
this.switchChatTabBox('tools') |
|
|
}, |
|
|
}, |
|
|
switchChatTabBox(chatTabBox, hideKeyBoard) { |
|
|
switchChatTabBox(chatTabBox) { |
|
|
this.chatTabBox = chatTabBox; |
|
|
this.chatTabBox = chatTabBox; |
|
|
if (hideKeyBoard) { |
|
|
if (chatTabBox != 'tools' && this.$refs.fileUpload) { |
|
|
uni.hideKeyboard(); |
|
|
this.$refs.fileUpload.hide() |
|
|
this.showKeyBoard = false; |
|
|
|
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
selectEmoji(emoText) { |
|
|
selectEmoji(emoText) { |
|
|
this.sendText += `#${emoText};`; |
|
|
let path = this.$emo.textToPath(emoText) |
|
|
}, |
|
|
// 先把键盘禁用了,否则会重新弹出键盘 |
|
|
onKeyboardheightchange(e) { |
|
|
this.isReadOnly = true; |
|
|
if (e.detail.height > 0) { |
|
|
this.isEmpty = false; |
|
|
this.showKeyBoard = true; |
|
|
this.$nextTick(() => { |
|
|
this.switchChatTabBox('none', false) |
|
|
this.editorCtx.insertImage({ |
|
|
this.keyboardHeight = this.rpxTopx(e.detail.height); |
|
|
src: path, |
|
|
this.scrollToBottom(); |
|
|
alt: emoText, |
|
|
} else { |
|
|
extClass: 'emoji-small', |
|
|
this.showKeyBoard = false; |
|
|
nowrap: true, |
|
|
} |
|
|
complete: () => { |
|
|
|
|
|
this.isReadOnly = false; |
|
|
|
|
|
this.editorCtx.blur(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}) |
|
|
}, |
|
|
}, |
|
|
onUploadImageBefore(file) { |
|
|
onUploadImageBefore(file) { |
|
|
let data = { |
|
|
let data = { |
|
|
@ -540,14 +566,22 @@ export default { |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
onTextInput(e) { |
|
|
onTextInput(e) { |
|
|
let idx = e.detail.cursor - 1; |
|
|
this.isEmpty = e.detail.html == '<p><br></p>' |
|
|
if (this.chat.type == 'GROUP' && e.detail.value[idx] == '@') { |
|
|
}, |
|
|
this.openAtBox(); |
|
|
onEditorReady() { |
|
|
let sendText = e.detail.value.replace("@", ''); |
|
|
const query = uni.createSelectorQuery().in(this); |
|
|
this.$nextTick(() => { |
|
|
query.select('#editor').context((res) => { |
|
|
this.sendText = sendText; |
|
|
this.editorCtx = res.context |
|
|
}) |
|
|
}).exec() |
|
|
} |
|
|
}, |
|
|
|
|
|
onEditorFocus(e) { |
|
|
|
|
|
this.isFocus = true; |
|
|
|
|
|
this.scrollToBottom() |
|
|
|
|
|
this.switchChatTabBox('none') |
|
|
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
|
onEditorBlur(e) { |
|
|
|
|
|
this.isFocus = false; |
|
|
}, |
|
|
}, |
|
|
loadReaded(fid) { |
|
|
loadReaded(fid) { |
|
|
this.$http({ |
|
|
this.$http({ |
|
|
@ -638,21 +672,27 @@ export default { |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
listenKeyBoardForH5() { |
|
|
listenKeyBoard() { |
|
|
|
|
|
// #ifdef H5 |
|
|
// 由于H5无法触发TextArea的@keyboardheightchange事件,所以通过 |
|
|
// 由于H5无法触发TextArea的@keyboardheightchange事件,所以通过 |
|
|
// 监听屏幕高度变化来实现键盘监听 |
|
|
// 监听屏幕高度变化来实现键盘监听 |
|
|
let initHeight = window.innerHeight; |
|
|
let initHeight = window.innerHeight; |
|
|
window.addEventListener('resize', () => { |
|
|
window.addEventListener('resize', () => { |
|
|
let keyboardHeight = initHeight - window.innerHeight; |
|
|
let keyboardHeight = initHeight - window.innerHeight; |
|
|
if (keyboardHeight > 0) { |
|
|
this.isShowKeyBoard = keyboardHeight > 0; |
|
|
this.keyboardHeight = keyboardHeight - 20; |
|
|
if (this.isShowKeyBoard) { |
|
|
this.showKeyBoard = true; |
|
|
this.keyboardHeight = keyboardHeight; |
|
|
this.switchChatTabBox('none', false) |
|
|
|
|
|
this.scrollToBottom(); |
|
|
|
|
|
} else { |
|
|
|
|
|
this.showKeyBoard = false; |
|
|
|
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
// #endif |
|
|
|
|
|
// #ifndef H5 |
|
|
|
|
|
uni.onKeyboardHeightChange((res) => { |
|
|
|
|
|
this.isShowKeyBoard = res.height > 0; |
|
|
|
|
|
if (this.isShowKeyBoard) { |
|
|
|
|
|
this.keyboardHeight = res.height; // 获取并保存键盘高度 |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
// #endif |
|
|
}, |
|
|
}, |
|
|
generateId() { |
|
|
generateId() { |
|
|
// 生成临时id |
|
|
// 生成临时id |
|
|
@ -705,10 +745,30 @@ export default { |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
return atUsers; |
|
|
return atUsers; |
|
|
|
|
|
}, |
|
|
|
|
|
chatMainHeight() { |
|
|
|
|
|
const sysInfo = uni.getSystemInfoSync(); |
|
|
|
|
|
let h = sysInfo.windowHeight; |
|
|
|
|
|
// 减去标题栏高度 |
|
|
|
|
|
h -= 50; |
|
|
|
|
|
// #ifdef H5 |
|
|
|
|
|
// h5的sysInfo.windowHeight默认就已经减去键盘高度了 |
|
|
|
|
|
if (this.chatTabBox != 'none') { |
|
|
|
|
|
h -= this.keyboardHeight; |
|
|
|
|
|
} |
|
|
|
|
|
// #endif |
|
|
|
|
|
// #ifndef H5 |
|
|
|
|
|
// 减去状态栏高度 |
|
|
|
|
|
h -= sysInfo.statusBarHeight; |
|
|
|
|
|
if (this.isShowKeyBoard || this.chatTabBox != 'none') { |
|
|
|
|
|
h -= this.keyboardHeight; |
|
|
|
|
|
} |
|
|
|
|
|
// #endif |
|
|
|
|
|
return h; |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
watch: { |
|
|
watch: { |
|
|
messageSize: function (newSize, oldSize) { |
|
|
messageSize: function(newSize, oldSize) { |
|
|
// 接收到消息时滚动到底部 |
|
|
// 接收到消息时滚动到底部 |
|
|
if (newSize > oldSize) { |
|
|
if (newSize > oldSize) { |
|
|
let pages = getCurrentPages(); |
|
|
let pages = getCurrentPages(); |
|
|
@ -730,10 +790,6 @@ export default { |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
onLoad(options) { |
|
|
onLoad(options) { |
|
|
// #ifdef H5 |
|
|
|
|
|
this.isH5 = true; |
|
|
|
|
|
this.listenKeyBoardForH5(); |
|
|
|
|
|
// #endif |
|
|
|
|
|
// 聊天数据 |
|
|
// 聊天数据 |
|
|
this.chat = this.chatStore.chats[options.chatIdx]; |
|
|
this.chat = this.chatStore.chats[options.chatIdx]; |
|
|
// 初始状态只显示20条消息 |
|
|
// 初始状态只显示20条消息 |
|
|
@ -752,6 +808,8 @@ export default { |
|
|
this.chatStore.activeChat(options.chatIdx); |
|
|
this.chatStore.activeChat(options.chatIdx); |
|
|
// 复位回执消息 |
|
|
// 复位回执消息 |
|
|
this.isReceipt = false; |
|
|
this.isReceipt = false; |
|
|
|
|
|
// 监听键盘高度 |
|
|
|
|
|
this.listenKeyBoard(); |
|
|
}, |
|
|
}, |
|
|
onShow() { |
|
|
onShow() { |
|
|
if (this.needScrollToBottom) { |
|
|
if (this.needScrollToBottom) { |
|
|
@ -765,9 +823,11 @@ export default { |
|
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
<style lang="scss" scoped> |
|
|
.chat-box { |
|
|
.chat-box { |
|
|
|
|
|
$icon-color: rgba(0, 0, 0, 0.88); |
|
|
position: relative; |
|
|
position: relative; |
|
|
display: flex; |
|
|
background-color: #fafafa; |
|
|
flex-direction: column; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.header { |
|
|
.header { |
|
|
display: flex; |
|
|
display: flex; |
|
|
@ -775,7 +835,7 @@ export default { |
|
|
align-items: center; |
|
|
align-items: center; |
|
|
height: 60rpx; |
|
|
height: 60rpx; |
|
|
padding: 5px; |
|
|
padding: 5px; |
|
|
background-color: #f9f9f9; |
|
|
background-color: #fafafa; |
|
|
line-height: 50px; |
|
|
line-height: 50px; |
|
|
font-size: $im-font-size-large; |
|
|
font-size: $im-font-size-large; |
|
|
box-shadow: $im-box-shadow-lighter; |
|
|
box-shadow: $im-box-shadow-lighter; |
|
|
@ -792,99 +852,118 @@ export default { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.chat-msg { |
|
|
.chat-main-box { |
|
|
flex: 1; |
|
|
// #ifdef H5 |
|
|
padding: 0; |
|
|
top: $im-nav-bar-height; |
|
|
overflow: hidden; |
|
|
// #endif |
|
|
position: relative; |
|
|
// #ifndef H5 |
|
|
background-color: white; |
|
|
top: calc($im-nav-bar-height + var(--status-bar-height)); |
|
|
|
|
|
// #endif |
|
|
.scroll-box { |
|
|
position: fixed; |
|
|
height: 100%; |
|
|
width: 100%; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.chat-at-bar { |
|
|
|
|
|
display: flex; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
flex-direction: column; |
|
|
padding: 0 10rpx; |
|
|
z-index: 9; |
|
|
|
|
|
|
|
|
.icon-at { |
|
|
.chat-msg { |
|
|
font-size: $im-font-size-larger; |
|
|
|
|
|
color: $im-color-primary; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.chat-at-scroll-box { |
|
|
|
|
|
flex: 1; |
|
|
flex: 1; |
|
|
width: 80%; |
|
|
padding: 0; |
|
|
|
|
|
overflow: hidden; |
|
|
.chat-at-items { |
|
|
position: relative; |
|
|
display: flex; |
|
|
background-color: white; |
|
|
align-items: center; |
|
|
|
|
|
height: 70rpx; |
|
|
|
|
|
|
|
|
|
|
|
.chat-at-item { |
|
|
.scroll-box { |
|
|
padding: 0 3rpx; |
|
|
height: 100%; |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
.chat-at-bar { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
padding: 0 10rpx; |
|
|
|
|
|
|
|
|
$icon-color: rgba(0, 0, 0, 0.88); |
|
|
.icon-at { |
|
|
|
|
|
font-size: $im-font-size-larger; |
|
|
|
|
|
color: $im-color-primary; |
|
|
|
|
|
font-weight: bold; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.send-bar { |
|
|
.chat-at-scroll-box { |
|
|
display: flex; |
|
|
flex: 1; |
|
|
align-items: center; |
|
|
width: 80%; |
|
|
padding: 10rpx; |
|
|
|
|
|
//margin-bottom: 10rpx; |
|
|
|
|
|
border-top: $im-border solid 1px; |
|
|
|
|
|
background-color: $im-bg; |
|
|
|
|
|
height: 80rpx; |
|
|
|
|
|
//box-shadow: $im-box-shadow-lighter; |
|
|
|
|
|
z-index: 1; |
|
|
|
|
|
|
|
|
|
|
|
.iconfont { |
|
|
.chat-at-items { |
|
|
font-size: 60rpx; |
|
|
display: flex; |
|
|
margin: 0 10rpx; |
|
|
align-items: center; |
|
|
color: $icon-color; |
|
|
height: 70rpx; |
|
|
} |
|
|
|
|
|
|
|
|
.chat-at-item { |
|
|
|
|
|
padding: 0 3rpx; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.chat-record { |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.send-text { |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
overflow: auto; |
|
|
|
|
|
padding: 14rpx 20rpx; |
|
|
|
|
|
background-color: #fff; |
|
|
|
|
|
border-radius: 8rpx; |
|
|
|
|
|
font-size: $im-font-size; |
|
|
|
|
|
box-sizing: border-box; |
|
|
|
|
|
margin: 0 10rpx; |
|
|
|
|
|
|
|
|
|
|
|
.send-text-area { |
|
|
|
|
|
width: 100%; |
|
|
.send-bar { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
padding: 10rpx; |
|
|
|
|
|
border-top: $im-border solid 1px; |
|
|
|
|
|
background-color: $im-bg; |
|
|
|
|
|
min-height: 80rpx; |
|
|
|
|
|
margin-bottom: 14rpx; |
|
|
|
|
|
|
|
|
|
|
|
.iconfont { |
|
|
|
|
|
font-size: 60rpx; |
|
|
|
|
|
margin: 0 10rpx; |
|
|
|
|
|
color: $icon-color; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.chat-record { |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.send-text { |
|
|
|
|
|
flex: 1; |
|
|
|
|
|
overflow: auto; |
|
|
|
|
|
padding: 14rpx 20rpx; |
|
|
|
|
|
background-color: #fff; |
|
|
|
|
|
border-radius: 8rpx; |
|
|
|
|
|
font-size: $im-font-size; |
|
|
|
|
|
box-sizing: border-box; |
|
|
|
|
|
margin: 0 10rpx; |
|
|
|
|
|
position: relative; |
|
|
|
|
|
|
|
|
|
|
|
.send-text-area { |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
height: 100%; |
|
|
|
|
|
min-height: 40rpx; |
|
|
|
|
|
max-height: 200rpx; |
|
|
|
|
|
font-size: 30rpx; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.btn-send { |
|
|
.btn-send { |
|
|
margin: 5rpx; |
|
|
margin: 5rpx; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.chat-tab-bar { |
|
|
.chat-tab-bar { |
|
|
height: 500rpx; |
|
|
position: fixed; |
|
|
padding: 20rpx; |
|
|
bottom: 0; |
|
|
background-color: $im-bg; |
|
|
background-color: $im-bg; |
|
|
|
|
|
|
|
|
.chat-tools { |
|
|
.chat-tools { |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-wrap: wrap; |
|
|
flex-wrap: wrap; |
|
|
padding-top: 20rpx; |
|
|
align-items: top; |
|
|
|
|
|
height: 310px; |
|
|
|
|
|
padding: 40rpx; |
|
|
|
|
|
box-sizing: border-box; |
|
|
|
|
|
|
|
|
.chat-tools-item { |
|
|
.chat-tools-item { |
|
|
width: 25%; |
|
|
width: 25%; |
|
|
@ -915,19 +994,20 @@ export default { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.chat-emotion { |
|
|
.chat-emotion { |
|
|
height: 100%; |
|
|
height: 310px; |
|
|
|
|
|
padding: 20rpx; |
|
|
|
|
|
box-sizing: border-box; |
|
|
|
|
|
|
|
|
.emotion-item-list { |
|
|
.emotion-item-list { |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-wrap: wrap; |
|
|
flex-wrap: wrap; |
|
|
justify-content: space-between; |
|
|
justify-content: space-between; |
|
|
|
|
|
align-content: center; |
|
|
|
|
|
|
|
|
.emotion-item { |
|
|
.emotion-item { |
|
|
width: 34px; |
|
|
|
|
|
height: 34px; |
|
|
|
|
|
text-align: center; |
|
|
text-align: center; |
|
|
cursor: pointer; |
|
|
cursor: pointer; |
|
|
padding: 6px; |
|
|
padding: 5px; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|