426 lines
10 KiB
Vue
426 lines
10 KiB
Vue
<template>
|
|
<view v-if="!getNoticeContent" :id="`auchor${source.clientMsgID}`" class="message_item"
|
|
:class="{ message_item_self: isSender, message_item_active: isActive }">
|
|
<my-avatar size="42" :desc="source.senderNickname" :src="source.senderFaceUrl" @click="viewDetail" />
|
|
<view class="message_container">
|
|
<view class="message_sender" :style="{ 'flex-direction': !isSender ? 'row-reverse' : 'row' }">
|
|
<text>{{ formattedMessageTime }}</text>
|
|
<text style="margin-left: 2rpx; margin-right: 2rpx">{{ "" }}</text>
|
|
<text v-if="!isSingle">{{ source.senderNickname }}</text>
|
|
</view>
|
|
<view class="message_send_state_box">
|
|
<view style="height: 100%;display: flex;justify-items: center;align-items: center;">
|
|
<view class="message_send_state">
|
|
<u-loading-icon v-if="showSending && !isPreview" />
|
|
<image v-if="isFailedMessage && !isPreview" src="@/static/images/chating_message_failed.png" />
|
|
</view>
|
|
</view>
|
|
<view class="message_content_wrap message_content_wrap_shadow" :id="`message_content_wrap_${source.clientMsgID}`" @longtap.stop.prevent="longtapEvent($event)">
|
|
<text-message-render v-if="showTextRender" :message="source" />
|
|
<media-message-render v-else-if="showMediaRender" :message="source" />
|
|
<error-message-render v-else />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 长按菜单 -->
|
|
<chunLei-popups v-model="toolTipFlag" :popData="toolTipData" @tapPopup="tapPopup"
|
|
:x="toolTipX" :y="toolTipY" :placement="popPostion"
|
|
:triangle="false"
|
|
direction="row" theme="dark" :dynamic="true">
|
|
</chunLei-popups>
|
|
</view>
|
|
|
|
<view v-else class="notice_message_container" style="margin: 0 auto;" :id="`auchor${source.clientMsgID}`">
|
|
<text>{{ getNoticeContent }}</text>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import {mapGetters} from "vuex";
|
|
import {MessageStatus,MessageType,SessionType,} from "openim-uniapp-polyfill";
|
|
import chunLeiPopups from "@/components/chunLei-popups.vue";
|
|
import MyAvatar from "@/components/MyAvatar/index.vue";
|
|
import TextMessageRender from "./TextMessageRender.vue";
|
|
import MediaMessageRender from "./MediaMessageRender.vue";
|
|
import ErrorMessageRender from "./ErrorMessageRender.vue";
|
|
import {noticeMessageTypes} from "@/constant";
|
|
import {tipMessaggeFormat,formatMessageTime} from "@/util/imCommon";
|
|
|
|
const textRenderTypes = [MessageType.TextMessage];
|
|
|
|
const mediaRenderTypes = [MessageType.PictureMessage];
|
|
|
|
export default {
|
|
components: {
|
|
MyAvatar,
|
|
TextMessageRender,
|
|
MediaMessageRender,
|
|
ErrorMessageRender,
|
|
chunLeiPopups
|
|
},
|
|
props: {
|
|
source: Object,
|
|
isSender: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
isPreview: Boolean,
|
|
isActive: Boolean,
|
|
},
|
|
data() {
|
|
return {
|
|
toolTipX: 0,
|
|
toolTipY: 0,
|
|
toolTipFlag: false,
|
|
popPostion:"default",
|
|
toolTipData: [],
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters([
|
|
"storeCurrentConversation",
|
|
"storeSelfInfo",
|
|
]),
|
|
isSingle() {
|
|
return (
|
|
this.storeCurrentConversation.conversationType === SessionType.Single
|
|
);
|
|
},
|
|
formattedMessageTime() {
|
|
return formatMessageTime(this.source.sendTime);
|
|
},
|
|
showTextRender() {
|
|
return textRenderTypes.includes(this.source.contentType);
|
|
},
|
|
showMediaRender() {
|
|
return mediaRenderTypes.includes(this.source.contentType);
|
|
},
|
|
getNoticeContent() {
|
|
const isNoticeMessage = noticeMessageTypes.includes(
|
|
this.source.contentType
|
|
);
|
|
return !isNoticeMessage ?
|
|
"" :
|
|
tipMessaggeFormat(
|
|
this.source,
|
|
this.$store.getters.storeCurrentUserID
|
|
);
|
|
},
|
|
isSuccessMessage() {
|
|
return this.source.status === MessageStatus.Succeed;
|
|
},
|
|
isFailedMessage() {
|
|
return this.source.status === MessageStatus.Failed;
|
|
},
|
|
showSending() {
|
|
return this.source.status === MessageStatus.Sending && !this.sendingDelay;
|
|
},
|
|
},
|
|
mounted() {
|
|
this.$emit("messageItemRender", this.source.clientMsgID);
|
|
this.setSendingDelay();
|
|
},
|
|
methods: {
|
|
viewDetail(){
|
|
if(this.isSender){
|
|
}else{
|
|
uni.navigateTo({
|
|
url:"/pages/common/userCard/index?sourceID="+this.source.sendID
|
|
})
|
|
}
|
|
},
|
|
setSendingDelay() {
|
|
if (this.source.status === MessageStatus.Sending) {
|
|
setTimeout(() => {
|
|
this.sendingDelay = false;
|
|
}, 2000);
|
|
}
|
|
},
|
|
longtapEvent(e){
|
|
console.log('longtapEvent');
|
|
// console.log("#"+e.currentTarget.id,e);
|
|
// let view = uni.createSelectorQuery().in(this).select("#"+e.currentTarget.id.replace('message_content_wrap_','auchor'));
|
|
// console.log(e.touches[0].clientX,e.touches[0].clientY);
|
|
// view.boundingClientRect((data) => {
|
|
// console.log(data.left,data.top);
|
|
// //console.log("得到布局位置信息" + JSON.stringify(data));
|
|
// }).exec();
|
|
this.$emit('userEvent',{type:"longtapMsgContent"},this.source);
|
|
//this.showToolTip(e);
|
|
},
|
|
//操作项
|
|
showToolTip: function(e) {
|
|
let that = this;
|
|
that.toolTipData=[
|
|
{
|
|
id: 1,
|
|
icon: '/static/images/chat/longTipIcon/copy.png',
|
|
title: '复制',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 4,
|
|
icon: '/static/images/chat/longTipIcon/zhuanfa.png',
|
|
title: '转发',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 6,
|
|
icon: '/static/images/chat/longTipIcon/select.png',
|
|
title: '多选',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 7,
|
|
icon: '/static/images/chat/longTipIcon/delete.png',
|
|
title: '删除',
|
|
disabled: false
|
|
},
|
|
// {
|
|
// id: 5,
|
|
// icon: '/static/images/chat/longTipIcon/tag.png',
|
|
// title: '编辑',
|
|
// disabled: false
|
|
// }
|
|
];
|
|
that.toolTipX =e.touches[0].clientX;
|
|
that.toolTipY = e.touches[0].clientY-20;
|
|
that.toolTipFlag = !that.toolTipFlag;
|
|
if(that.toolTipFlag==true){
|
|
let nowTime=new Date().getTime();
|
|
let msgTime=that.source.createTime;
|
|
let diff= nowTime-msgTime;
|
|
if(this.isSender&&diff<120000){
|
|
that.toolTipData.push({
|
|
id: 3,
|
|
icon: '/static/images/chat/longTipIcon/revert.png',
|
|
title: '撤回',
|
|
disabled: false
|
|
})
|
|
}
|
|
}
|
|
},
|
|
tapPopup(e) {
|
|
let that = this;
|
|
let currentHandleMsg=that.source;
|
|
console.log(currentHandleMsg);
|
|
if (e.title == "撤回") {
|
|
that.toolTipFlag = false;
|
|
that.$emit('userEvent',{type:'revokeMessage'},that.source);
|
|
}
|
|
if (e.title == "复制") {
|
|
let content = currentHandleMsg.textElem?.content;
|
|
if (content) {
|
|
let copyContent =content.text;
|
|
let formatStr = copyContent;
|
|
//let formatStr = this.replaceReseverEmoji(copyContent);
|
|
uni.setClipboardData({
|
|
data:formatStr,
|
|
success: (res) => {
|
|
uni.showToast({
|
|
title: res,
|
|
icon: 'none'
|
|
})
|
|
},
|
|
error: (e) => {
|
|
uni.showToast({
|
|
title: e,
|
|
icon: 'none',
|
|
duration: 3000,
|
|
})
|
|
}
|
|
})
|
|
}
|
|
that.toolTipFlag = false;
|
|
return;
|
|
}
|
|
if (e.title == "转发") {
|
|
that.$emit('userEvent',{type:'forward'},that.source);
|
|
that.toolTipFlag = false;
|
|
return
|
|
}
|
|
if(e.title=="调换"){
|
|
that.toolTipFlag = false;
|
|
return;
|
|
}
|
|
if (e.title == "多选") {
|
|
that.$emit('userEvent',{type:'select'},that.source);
|
|
that.toolTipFlag = false;
|
|
return
|
|
}
|
|
if (e.title == "删除") {
|
|
that.toolTipFlag = false;
|
|
that.$emit('userEvent',{type:'deleteMsg'},that.source);
|
|
return
|
|
}
|
|
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.message_item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
padding: 16rpx 44rpx;
|
|
// padding-top: 48rpx;
|
|
position: relative;
|
|
|
|
.check_wrap {
|
|
@include centerBox();
|
|
box-sizing: border-box;
|
|
width: 40rpx;
|
|
min-width: 40rpx;
|
|
height: 40rpx;
|
|
min-height: 40rpx;
|
|
border: 2px solid #979797;
|
|
border-radius: 50%;
|
|
margin-top: 16rpx;
|
|
margin-right: 24rpx;
|
|
|
|
&_active {
|
|
background-color: #1d6bed;
|
|
border: none;
|
|
}
|
|
|
|
&_disabled {
|
|
background-color: #c8c9cc;
|
|
}
|
|
}
|
|
|
|
.message_container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
margin-left: 20rpx;
|
|
// text-align: flex-start;
|
|
max-width: 80%;
|
|
position: relative;
|
|
|
|
.message_sender {
|
|
@include nomalEllipsis();
|
|
display: flex;
|
|
max-width: 480rpx;
|
|
// font-size: 24rpx;
|
|
font-size: 0.85rem;
|
|
color: #666;
|
|
margin-bottom: 6rpx;
|
|
}
|
|
.message_content_wrap_shadow {
|
|
box-shadow: 0px 0px 2px rgba(0,0,0,0.1);
|
|
}
|
|
.message_content_wrap {
|
|
@include vCenterBox();
|
|
text-align: flex-start;
|
|
// font-size: 14px;
|
|
color: $uni-text-color;
|
|
width: fit-content;
|
|
word-wrap: break-word;
|
|
word-break: break-word;
|
|
|
|
.bg_container {
|
|
padding: 16rpx 24rpx;
|
|
border-radius: 12rpx;
|
|
background-color: #fff;
|
|
}
|
|
}
|
|
}
|
|
|
|
.message_send_state_box {
|
|
display: flex;
|
|
flex-direction: row-reverse;
|
|
}
|
|
|
|
.message_send_state {
|
|
@include centerBox();
|
|
margin-left: 12rpx;
|
|
// margin-top: 48rpx;
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
|
|
.read_limit_count {
|
|
// font-size: 24rpx;
|
|
font-size: 0.85rem;
|
|
color: #999;
|
|
}
|
|
|
|
image {
|
|
width: 16px;
|
|
height: 16px;
|
|
}
|
|
}
|
|
|
|
::v-deep.emoji_display {
|
|
width: 24px;
|
|
height: 18px;
|
|
vertical-align: sub;
|
|
}
|
|
|
|
&_self {
|
|
flex-direction: row-reverse;
|
|
|
|
.check_wrap {
|
|
margin-right: 0;
|
|
margin-left: 24rpx;
|
|
}
|
|
|
|
.message_container {
|
|
margin-left: 0;
|
|
margin-right: 20rpx;
|
|
// text-align: end;
|
|
align-items: flex-end;
|
|
.message_content_wrap_shadow {
|
|
box-shadow: 0px 0px 2px #95e261;
|
|
}
|
|
.message_content_wrap {
|
|
flex-direction: row-reverse;
|
|
|
|
.bg_container {
|
|
border-radius: 12rpx 0 12rpx 12rpx;
|
|
background-color: #94ec68 !important;
|
|
}
|
|
}
|
|
}
|
|
|
|
.message_send_state_box {
|
|
flex-direction: row;
|
|
}
|
|
|
|
.message_send_state {
|
|
margin-left: 0rpx;
|
|
margin-right: 12rpx;
|
|
}
|
|
}
|
|
|
|
&_active {
|
|
background-color: #fdf5e9;
|
|
}
|
|
}
|
|
|
|
.notice_message_container {
|
|
@include ellipsisWithLine(2);
|
|
text-align: center;
|
|
margin: 24rpx 48rpx;
|
|
// font-size: 24rpx;
|
|
font-size: 0.85rem;
|
|
color: #999;
|
|
position: relative;
|
|
}
|
|
|
|
.fade-leave,
|
|
.fade-enter-to {
|
|
opacity: 1;
|
|
}
|
|
|
|
.fade-leave-active,
|
|
.fade-enter-active {
|
|
transition: all 0.5s;
|
|
}
|
|
|
|
.fade-leave-to,
|
|
.fade-enter {
|
|
opacity: 0;
|
|
}
|
|
</style> |