281 lines
6.6 KiB
Vue
281 lines
6.6 KiB
Vue
<template>
|
|
<scroll-view :scroll-with-animation="withAnimation" @click="click" id="scroll_view" :style="{
|
|
height: '1px'
|
|
}" @scroll="throttleScroll" :scroll-top="scrollTop" scroll-y :scroll-into-view="scrollIntoView"
|
|
upper-threshold="250" @scrolltoupper="scrolltoupper">
|
|
<view id="scroll_wrap">
|
|
<u-loadmore nomoreText="" :status="loadMoreStatus" />
|
|
<view class="msg_item" v-for="item in storeHistoryMessageList" :key="item.clientMsgID" @click="onUserMessageEvent({type:'selected'},item)">
|
|
<template v-if="selectFlag">
|
|
<uni-icons class="selectedIcon" size="30" color="#07c160" type="checkbox-filled" v-if="selectClientMsgIDItems.indexOf(item.clientMsgID)>-1"></uni-icons>
|
|
<uni-icons class="selectedIcon" size="30" color="#ccc" type="circle" v-else></uni-icons>
|
|
</template>
|
|
<MessageItemRender
|
|
@userEvent="onUserMessageEvent"
|
|
:source="item"
|
|
:conversationID="storeCurrentConversation.conversationID"
|
|
:isSender="item.sendID === storeCurrentUserID"
|
|
/>
|
|
<!-- :isActive="selectClientMsgIDItems.indexOf(item.clientMsgID)>-1" -->
|
|
</view>
|
|
<view style="visibility: hidden; height: 12px" id="auchormessage_bottom_item"></view>
|
|
</view>
|
|
</scroll-view>
|
|
</template>
|
|
|
|
<script>
|
|
import {mapGetters,mapActions} from "vuex";
|
|
import MessageItemRender from "./MessageItem/index";
|
|
|
|
export default {
|
|
name: "",
|
|
components: {
|
|
MessageItemRender,
|
|
},
|
|
props: {
|
|
selectFlag:{
|
|
type:Boolean,
|
|
default:false
|
|
},
|
|
selectItems:{
|
|
type:Array,
|
|
default(){
|
|
return [];
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
scrollIntoView: "",
|
|
scrollWithAnimation: false,
|
|
scrollTop: 0,
|
|
old: {
|
|
scrollTop: 0
|
|
},
|
|
initFlag: true,
|
|
isOverflow: false,
|
|
needScoll: true,
|
|
withAnimation: false,
|
|
messageLoadState: {
|
|
loading: false,
|
|
}
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters([
|
|
"storeCurrentConversation",
|
|
"storeHistoryMessageList",
|
|
"storeHasMoreMessage",
|
|
"storeCurrentUserID",
|
|
"storeSelfInfo",
|
|
]),
|
|
loadMoreStatus() {
|
|
if (!this.storeHasMoreMessage) {
|
|
return "nomore";
|
|
}
|
|
return this.messageLoadState.loading ? "loading" : "loadmore";
|
|
},
|
|
selectClientMsgIDItems(){
|
|
let arr = [];
|
|
this.selectItems.forEach((v,k)=>{
|
|
arr.push(v.clientMsgID);
|
|
});
|
|
return arr;
|
|
}
|
|
},
|
|
mounted() {
|
|
this.loadMessageList();
|
|
},
|
|
methods: {
|
|
...mapActions("message", ["getHistoryMesageList"]),
|
|
async loadMessageList(isLoadMore = false) {
|
|
this.messageLoadState.loading = true;
|
|
const lastMsgID = this.storeHistoryMessageList[0]?.clientMsgID;
|
|
const options = {
|
|
conversationID: this.storeCurrentConversation.conversationID,
|
|
count: 20,
|
|
startClientMsgID: this.storeHistoryMessageList[0]?.clientMsgID ?? "",
|
|
viewType: 0,
|
|
};
|
|
try {
|
|
const {emptyFlag} =await this.getHistoryMesageList(options);
|
|
if (emptyFlag) {
|
|
this.$emit("initSuccess");
|
|
}
|
|
} catch (e) {
|
|
console.log(e);
|
|
//TODO handle the exception
|
|
}
|
|
this.$nextTick(function() {
|
|
if (isLoadMore && lastMsgID) {
|
|
this.scrollToAnchor(`auchor${lastMsgID}`);
|
|
}
|
|
this.messageLoadState.loading = false;
|
|
});
|
|
},
|
|
click(e) {
|
|
this.$emit("click", e);
|
|
},
|
|
onScroll(event) {
|
|
const {scrollHeight,scrollTop} = event.target;
|
|
this.old.scrollTop = scrollTop
|
|
this.needScoll =
|
|
scrollHeight - scrollTop < uni.getWindowInfo().windowHeight * 1.2;
|
|
},
|
|
throttleScroll(event) {
|
|
uni.$u.throttle(() => this.onScroll(event), 150);
|
|
},
|
|
scrolltoupper() {
|
|
if (!this.messageLoadState.loading && this.storeHasMoreMessage) {
|
|
this.loadMessageList(true);
|
|
}
|
|
},
|
|
scrollToBottom(isInit = false, isRecv = false) {
|
|
if (isRecv && !this.needScoll) {
|
|
return;
|
|
}
|
|
|
|
if (!isInit) {
|
|
this.withAnimation = true;
|
|
setTimeout(() => (this.withAnimation = false), 100);
|
|
}
|
|
|
|
this.$nextTick(() => {
|
|
uni
|
|
.createSelectorQuery()
|
|
.in(this)
|
|
.select("#scroll_wrap")
|
|
.boundingClientRect((res) => {
|
|
// let top = res.height - this.scrollViewHeight;
|
|
// if (top > 0) {
|
|
this.scrollTop = this.old.scrollTop
|
|
this.$nextTick(() => this.scrollTop = res.height);
|
|
if (isInit) {
|
|
this.$emit("initSuccess");
|
|
}
|
|
// }
|
|
})
|
|
.exec();
|
|
});
|
|
},
|
|
scrollToAnchor(auchor) {
|
|
this.$nextTick(function() {
|
|
this.scrollIntoView = auchor;
|
|
});
|
|
},
|
|
checkInitHeight() {
|
|
this.getEl("#scroll_view").then(({height}) => {
|
|
this.bgHeight = `${height}px`;
|
|
});
|
|
},
|
|
getEl(el) {
|
|
return new Promise((resolve) => {
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query
|
|
.select(el)
|
|
.boundingClientRect((data) => {
|
|
resolve(data);
|
|
})
|
|
.exec();
|
|
});
|
|
},
|
|
onUserMessageEvent(e,data){
|
|
if(e.type == 'messageItemRender'){
|
|
if (
|
|
this.initFlag && data === this.storeHistoryMessageList[this.storeHistoryMessageList.length - 1].clientMsgID
|
|
) {
|
|
this.initFlag = false;
|
|
setTimeout(() => this.scrollToBottom(true), 200);
|
|
this.checkInitHeight();
|
|
}
|
|
return ;
|
|
}
|
|
this.$emit('userEvent',e,data)
|
|
},
|
|
empty(){}
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
#scroll_view {
|
|
flex: 1;
|
|
background-repeat: no-repeat;
|
|
position: relative;
|
|
}
|
|
|
|
.watermark-view {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: fixed;
|
|
}
|
|
|
|
.watermark {
|
|
font-size: 16px;
|
|
/* 水印文字大小 */
|
|
color: #f0f2f6;
|
|
/* 水印文字颜色,使用透明度控制可见度 */
|
|
position: absolute;
|
|
/* 水印相对定位 */
|
|
transform: rotate(-45deg);
|
|
pointer-events: none;
|
|
/* 防止水印文字干扰交互 */
|
|
}
|
|
|
|
.uni-scroll-view {
|
|
position: relative;
|
|
}
|
|
|
|
.new_message_flag {
|
|
position: sticky;
|
|
background: #ffffff;
|
|
box-shadow: 0px 3px 8px 0px rgba(0, 0, 0, 0.1);
|
|
border-radius: 14px;
|
|
padding: 4px 8px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
bottom: 12px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: fit-content;
|
|
font-size: 24rpx;
|
|
color: #006aff;
|
|
}
|
|
|
|
.time_gap_line {
|
|
position: relative;
|
|
padding: 0 10vw 12rpx;
|
|
text-align: center;
|
|
// font-size: 24rpx;
|
|
font-size: 0.93rem;
|
|
color: #999;
|
|
}
|
|
|
|
.fade-leave,
|
|
.fade-enter-to {
|
|
opacity: 1;
|
|
}
|
|
|
|
.fade-leave-active,
|
|
.fade-enter-active {
|
|
transition: all 0.3s;
|
|
}
|
|
|
|
.fade-leave-to,
|
|
.fade-enter {
|
|
opacity: 0;
|
|
}
|
|
.msg_item{
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: flex-start;
|
|
width: 100%;
|
|
.message_item{
|
|
flex:1;
|
|
}
|
|
.selectedIcon{
|
|
margin-top: 20rpx;
|
|
}
|
|
}
|
|
</style> |