37 changed files with 2153 additions and 1555 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,67 @@ |
|||
<template> |
|||
<div class="chat-group-member" :style="{'height':height+'px'}"> |
|||
<div class="member-avatar"> |
|||
<head-image :size="headImageSize" :name="member.aliasName" :url="member.headImage"> </head-image> |
|||
</div> |
|||
<div class="member-name" :style="{'line-height':height+'px'}"> |
|||
<div>{{ member.aliasName }}</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import HeadImage from "../common/HeadImage.vue"; |
|||
export default { |
|||
name: "groupMember", |
|||
components: { HeadImage }, |
|||
data() { |
|||
return {}; |
|||
}, |
|||
props: { |
|||
member: { |
|||
type: Object, |
|||
required: true |
|||
}, |
|||
height:{ |
|||
type: Number, |
|||
default: 50 |
|||
} |
|||
}, |
|||
computed:{ |
|||
headImageSize(){ |
|||
return Math.ceil(this.height * 0.75) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.chat-group-member { |
|||
display: flex; |
|||
margin-bottom: 1px; |
|||
position: relative; |
|||
padding: 0 5px; |
|||
align-items: center; |
|||
background-color: #fafafa; |
|||
white-space: nowrap; |
|||
box-sizing: border-box; |
|||
|
|||
&:hover { |
|||
background-color: #eeeeee; |
|||
} |
|||
|
|||
&.active { |
|||
background-color: #eeeeee; |
|||
} |
|||
|
|||
.member-name { |
|||
padding-left: 10px; |
|||
height: 100%; |
|||
text-align: left; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
font-size: 14px; |
|||
font-weight: 600; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,186 @@ |
|||
<template> |
|||
<div v-show="show"> |
|||
<div class="chat-group-readed-mask" @click.self="close()"> |
|||
<div class="chat-group-readed" :style="{ 'left': pos.x + 'px', 'top': pos.y + 'px' }" @click.prevent=""> |
|||
<el-tabs type="border-card" :stretch="true"> |
|||
<el-tab-pane :label="`已读(${readedMembers.length})`"> |
|||
<el-scrollbar class="scroll-box"> |
|||
<div v-for="(member) in readedMembers" :key="member.id"> |
|||
<chat-group-member :member="member"></chat-group-member> |
|||
</div> |
|||
</el-scrollbar> |
|||
</el-tab-pane> |
|||
<el-tab-pane :label="`未读(${unreadMembers.length})`"> |
|||
<el-scrollbar class="scroll-box"> |
|||
<div v-for="(member) in unreadMembers" :key="member.id"> |
|||
<chat-group-member :member="member"></chat-group-member> |
|||
</div> |
|||
</el-scrollbar> |
|||
</el-tab-pane> |
|||
</el-tabs> |
|||
<div v-show="msgInfo.selfSend" class="arrow-right" :style="{ 'top': pos.arrowY + 'px' }"> |
|||
<div class="arrow-right-inner"> |
|||
</div> |
|||
</div> |
|||
<div v-show="!msgInfo.selfSend" class="arrow-left" :style="{ 'top': pos.arrowY + 'px' }"> |
|||
<div class="arrow-left-inner"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</template> |
|||
|
|||
|
|||
<script> |
|||
import ChatGroupMember from "./ChatGroupMember.vue"; |
|||
|
|||
export default { |
|||
name: "chatGroupReaded", |
|||
components: { |
|||
ChatGroupMember |
|||
}, |
|||
data() { |
|||
return { |
|||
show: false, |
|||
pos: { |
|||
x: 0, |
|||
y: 0, |
|||
arrowY: 0 |
|||
}, |
|||
msgInfo: {}, |
|||
readedMembers: [], |
|||
unreadMembers: [] |
|||
} |
|||
}, |
|||
props: { |
|||
groupMembers: { |
|||
type: Array |
|||
} |
|||
}, |
|||
methods: { |
|||
close() { |
|||
this.show = false; |
|||
}, |
|||
open(msgInfo, rect) { |
|||
this.show = true; |
|||
this.msgInfo = msgInfo; |
|||
this.pos.arrowY = 200; |
|||
// 计算窗口位置 |
|||
if (this.msgInfo.selfSend) { |
|||
// 自己发的消息弹出在消息的左边 |
|||
this.pos.x = rect.left - 310; |
|||
} else { |
|||
// 别人发的消息弹窗在消息右边 |
|||
this.pos.x = rect.right + 20; |
|||
} |
|||
this.pos.y = rect.top + rect.height / 2 - 215; |
|||
// 防止窗口溢出 |
|||
if (this.pos.y < 0) { |
|||
this.pos.arrowY += this.pos.y |
|||
this.pos.y = 0; |
|||
} |
|||
this.loadReadedUser() |
|||
}, |
|||
loadReadedUser() { |
|||
this.readedMembers = []; |
|||
this.unreadMembers = []; |
|||
this.$http({ |
|||
url: "/message/group/findReadedUsers", |
|||
method: 'get', |
|||
params: { groupId: this.msgInfo.groupId, messageId: this.msgInfo.id } |
|||
}).then(userIds => { |
|||
this.groupMembers.forEach(member => { |
|||
// 发送者和已退群的不显示 |
|||
if (member.userId == this.msgInfo.sendId && member.quit) { |
|||
return; |
|||
} |
|||
// 区分已读还是未读 |
|||
if (userIds.find(userId => member.userId == userId)) { |
|||
this.readedMembers.push(member); |
|||
} else { |
|||
this.unreadMembers.push(member); |
|||
} |
|||
}) |
|||
// 更新已读人数 |
|||
this.$store.commit("updateMessage", { |
|||
id: this.msgInfo.id, |
|||
groupId: this.msgInfo.groupId, |
|||
readedCount: this.readedMembers.length |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.chat-group-readed-mask { |
|||
position: fixed; |
|||
left: 0; |
|||
top: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
z-index: 9999; |
|||
} |
|||
|
|||
.chat-group-readed { |
|||
position: fixed; |
|||
box-shadow: 0px 0px 10px #ccc; |
|||
width: 300px; |
|||
background-color: #fafafa; |
|||
border-radius: 8px; |
|||
|
|||
.scroll-box { |
|||
height: 400px; |
|||
} |
|||
|
|||
.arrow-left { |
|||
|
|||
position: absolute; |
|||
left: -15px; |
|||
width: 0; |
|||
height: 0; |
|||
border-top: 15px solid transparent; |
|||
border-bottom: 15px solid transparent; |
|||
border-right: 15px solid #ccc; |
|||
|
|||
.arrow-left-inner { |
|||
position: absolute; |
|||
top: -12px; |
|||
left: 3px; |
|||
width: 0; |
|||
height: 0; |
|||
overflow: hidden; |
|||
border-top: 12px solid transparent; |
|||
border-bottom: 12px solid transparent; |
|||
border-right: 12px solid white; |
|||
} |
|||
} |
|||
|
|||
.arrow-right { |
|||
position: absolute; |
|||
right: -15px; |
|||
width: 0; |
|||
height: 0; |
|||
border-top: 15px solid transparent; |
|||
border-bottom: 15px solid transparent; |
|||
border-left: 15px solid #ccc; |
|||
|
|||
.arrow-right-inner { |
|||
position: absolute; |
|||
top: -12px; |
|||
right: 3px; |
|||
width: 0; |
|||
height: 0; |
|||
overflow: hidden; |
|||
border-top: 12px solid transparent; |
|||
border-bottom: 12px solid transparent; |
|||
border-left: 12px solid white; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,131 @@ |
|||
<template> |
|||
<uni-popup ref="popup" type="bottom"> |
|||
<view class="chat-group-readed"> |
|||
<view class="uni-padding-wrap uni-common-mt"> |
|||
<uni-segmented-control :current="current" :values="items" style-type="button" active-color="#587ff0" @clickItem="onClickItem"/> |
|||
</view> |
|||
<view class="content"> |
|||
<view v-if="current === 0"> |
|||
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> |
|||
<view v-for="m in readedMembers" :key="m.userId"> |
|||
<view class="member-item"> |
|||
<head-image :name="m.aliasName" :online="m.online" :url="m.headImage" |
|||
:size="90"></head-image> |
|||
<view class="member-name">{{ m.aliasName}}</view> |
|||
</view> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
<view v-if="current === 1"> |
|||
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> |
|||
<view v-for="m in unreadMembers" :key="m.userId"> |
|||
<view class="member-item"> |
|||
<head-image :name="m.aliasName" :online="m.online" :url="m.headImage" |
|||
:size="90"></head-image> |
|||
<view class="member-name">{{ m.aliasName}}</view> |
|||
</view> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</uni-popup> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: "chat-group-readed", |
|||
data() { |
|||
return { |
|||
items: ['已读', '未读'], |
|||
current: 0, |
|||
readedMembers: [], |
|||
unreadMembers: [] |
|||
}; |
|||
}, |
|||
props: { |
|||
msgInfo: { |
|||
type: Object, |
|||
required: true |
|||
}, |
|||
groupMembers: { |
|||
type: Array |
|||
} |
|||
}, |
|||
methods: { |
|||
open() { |
|||
this.$refs.popup.open(); |
|||
this.loadReadedUser(); |
|||
}, |
|||
loadReadedUser() { |
|||
this.readedMembers = []; |
|||
this.unreadMembers = []; |
|||
this.$http({ |
|||
url: `/message/group/findReadedUsers?groupId=${this.msgInfo.groupId}&messageId=${this.msgInfo.id}`, |
|||
method: 'Get' |
|||
}).then(userIds => { |
|||
this.groupMembers.forEach(member => { |
|||
// 发送者和已退群的不显示 |
|||
if (member.userId == this.msgInfo.sendId && member.quit) { |
|||
return; |
|||
} |
|||
// 区分已读还是未读 |
|||
if (userIds.find(userId => member.userId == userId)) { |
|||
this.readedMembers.push(member); |
|||
} else { |
|||
this.unreadMembers.push(member); |
|||
} |
|||
}) |
|||
this.items[0] = `已读(${this.readedMembers.length})`; |
|||
this.items[1] = `未读(${this.unreadMembers.length})`; |
|||
// 更新已读人数 |
|||
this.$store.commit("updateMessage", { |
|||
id: this.msgInfo.id, |
|||
groupId: this.msgInfo.groupId, |
|||
readedCount: this.readedMembers.length |
|||
}) |
|||
}) |
|||
}, |
|||
onClickItem(e){ |
|||
this.current = e.currentIndex; |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.chat-group-readed { |
|||
position: relative; |
|||
border: #dddddd solid 1rpx; |
|||
display: flex; |
|||
flex-direction: column; |
|||
background-color: white; |
|||
padding: 10rpx; |
|||
border-radius: 15rpx; |
|||
.scroll-bar { |
|||
height: 800rpx; |
|||
} |
|||
|
|||
.member-item { |
|||
height: 120rpx; |
|||
display: flex; |
|||
position: relative; |
|||
padding: 0 30rpx; |
|||
align-items: center; |
|||
background-color: white; |
|||
white-space: nowrap; |
|||
|
|||
.member-name { |
|||
flex: 1; |
|||
padding-left: 20rpx; |
|||
font-size: 30rpx; |
|||
font-weight: 600; |
|||
line-height: 60rpx; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
</style> |
|||
Binary file not shown.
Loading…
Reference in new issue