555 lines
14 KiB
Vue
555 lines
14 KiB
Vue
<template>
|
|
<view class="message-item-container"
|
|
:class="checkBoxFlag?'u-flex u-row-left u-col-center':''">
|
|
<view v-if="checkBoxFlag">
|
|
<template v-if="item.messageType!=0">
|
|
<u-checkbox :size="46" v-model="item.checked"
|
|
shape="circle" active-color="#19be6b" @click.native="checkChange(item)"></u-checkbox>
|
|
</template>
|
|
</view>
|
|
<view class="u-p-b-20 u-p-t-20" style="width: 100%;">
|
|
<!-- 系统信息-->
|
|
<view v-if="item.messageType==0">
|
|
<view v-if="item.showTimeFlag" style="text-align: center;color:#aaaaaa;font-size: 28rpx;margin-top: 20rpx;">
|
|
<text v-if="item.formatTimeStr&&item.formatTimeStr.length>0">
|
|
{{item.formatTimeStr}}
|
|
</text>
|
|
<text v-else>
|
|
{{item.createTime.substring(10,16)}}
|
|
</text>
|
|
</view>
|
|
<view style="text-align: center;color:#aaaaaa;font-size: 30rpx;margin-top: 20rpx;">
|
|
{{parseSYSContent(item)}}
|
|
</view>
|
|
</view>
|
|
<view v-else>
|
|
<view class="chat-time">
|
|
<text v-if="item.showTimeFlag">
|
|
<text v-if="item.formatTimeStr&&item.formatTimeStr.length>0">
|
|
{{item.formatTimeStr}}
|
|
</text>
|
|
<text v-else>
|
|
{{item.createTime.length>10?item.createTime.substring(10,16):item.createTime}}
|
|
</text>
|
|
</text>
|
|
</view>
|
|
<view :class="{'chat-container':true,'chat-location-me':item.meFlag}">
|
|
<view class="chat-icon-container u-flex u-row-center u-col-center"
|
|
@click="toYYYPerson(item)">
|
|
<view hover-class="my-hover-class"
|
|
class="u-flex u-row-center u-col-center">
|
|
<u-image :class="{'chat-icon':true,'chat-icon-me':item.meFlag}"
|
|
:src="item.userAvatar" width="80rpx" height="80rpx"
|
|
mode="aspectFill">
|
|
<view slot="error"
|
|
class="u-flex u-row-center u-col-center u-p-t-10"
|
|
style="width: 80rpx;height: 80rpx;border-radius: 12rpx;">
|
|
<view>
|
|
<image src="/static/image/default/default-user/default-user.png"
|
|
style="width: 50rpx;height:50rpx;"></image>
|
|
</view>
|
|
</view>
|
|
</u-image>
|
|
</view>
|
|
</view>
|
|
<view class="chat-content-container u-p-t-10">
|
|
<!-- 文本信息 -->
|
|
<view v-if="item.contentType == messageApi.CONTENT_TYPE.TEXT_CONTENT_TYPE">
|
|
<zb-tooltip placement="top" :visible.sync="toolTipFlag" color="#4c4c4c">
|
|
<view slot="content" style="width: 550rpx;"
|
|
class="u-flex u-flex-wrap u-row-left u-col-center">
|
|
<view v-for="(item,index) in toolTipData" :key="index"
|
|
style="text-align: center;padding: 20rpx 30rpx;">
|
|
<view class="u-flex u-row-center u-col-center" @click="handleMessage(item)">
|
|
<view>
|
|
<u-image :src="item.icon" :width="36" :height="36"></u-image>
|
|
</view>
|
|
</view>
|
|
<view style="font-size:26rpx;margin-top: 6rpx;">
|
|
<text>{{item.title}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view @longpress="toolTipFlag=!toolTipFlag"
|
|
:class="{'chat-text-container':true,'chat-text-container-me u-text-reserve':item.meFlag}">
|
|
<u-parse :html="parseTextContent(item)"
|
|
:tag-style="tagStyle">
|
|
</u-parse>
|
|
</view>
|
|
</zb-tooltip>
|
|
</view>
|
|
<!-- 图片信息 -->
|
|
<view v-if="item.contentType == messageApi.CONTENT_TYPE.IMG_CONTENT_TYPE">
|
|
<view class="content contentType3" @tap="showPic(item)">
|
|
<u-image :width="item.content.width*2" :height="item.content.height*2"
|
|
:lazy-load="true" mode="widthFix" :src="parseImageSrc(item)">
|
|
<u-loading slot="loading"></u-loading>
|
|
</u-image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
var previewSrcArr = [];
|
|
export default {
|
|
name: "message-item",
|
|
props: {
|
|
item: {
|
|
type: Object,
|
|
default: function() {
|
|
return {
|
|
"id": "",
|
|
"chatGroupId": "",
|
|
"userId": 0,
|
|
"meFlag": true,
|
|
"userName": '',
|
|
"userAvatar": "",
|
|
'messageType': "",
|
|
"contentType": "",
|
|
"content": {},
|
|
"timestamp": "",
|
|
"createTime": "",
|
|
"platFrom": this.messageApi.msgPlat,
|
|
}
|
|
}
|
|
},
|
|
checkBoxFlag:{
|
|
type:Boolean,
|
|
default:false
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
toolTipFlag: false,
|
|
toolTipData: [{
|
|
id: 1,
|
|
icon: '/static/image/wx/handle-msg/copy.jpg',
|
|
title: '复制',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 2,
|
|
icon: '/static/image/wx/handle-msg/zhuanfa.jpg',
|
|
title: '转发', //转发
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 4,
|
|
icon: '/static/image/wx/handle-msg/shoucang.jpg',
|
|
title: '收藏',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 5,
|
|
icon: '/static/image/wx/handle-msg/shanchu.jpg',
|
|
title: '删除',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 6,
|
|
icon: '/static/image/wx/handle-msg/duoxuan.jpg',
|
|
title: '多选',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 7,
|
|
icon: '/static/image/wx/handle-msg/yinyong.jpg',
|
|
title: '引用',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 8,
|
|
icon: '/static/image/wx/handle-msg/tixing.jpg',
|
|
title: '提醒',
|
|
disabled: false
|
|
},
|
|
{
|
|
id: 9,
|
|
icon: '/static/image/wx/handle-msg/souyisou.jpg',
|
|
title: '搜一搜',
|
|
disabled: false
|
|
},
|
|
],
|
|
tagStyle:{
|
|
img:'width:22px;height:22px;position:relative;top:10rpx;',
|
|
span:'margin:0px;padding:0px;font-size:30rpx',
|
|
},
|
|
previewVideoFlag:false, //播放视频控制器
|
|
previewVideoSrc:'',
|
|
redbagPopFlag:false,
|
|
maskCustomStyle:{
|
|
background: 'rgba(255, 255, 255, 0.7)'
|
|
},
|
|
currentRedBagInfo:null,
|
|
};
|
|
},
|
|
|
|
methods: {
|
|
parseSYSContent:function(item){
|
|
let that=this;
|
|
let contentType = item.contentType;
|
|
let contentObj=item.content;
|
|
if (contentType == 1) {
|
|
let msgStr = contentObj.text;
|
|
console.log("transText",msgStr);
|
|
return msgStr;
|
|
}
|
|
},
|
|
//内容格式化
|
|
parseTextContent: function(item) {
|
|
let that=this;
|
|
let contentType = item.contentType;
|
|
let contentObj=item.content;
|
|
let msgStr = contentObj.text;
|
|
let sysType = contentObj.contentType; //内容类型
|
|
let optionType = contentObj.optionType;
|
|
let transText = this.transform(msgStr,'','',contentObj.linkName);
|
|
return transText;
|
|
},
|
|
|
|
//预览图片
|
|
showPic:function(item){
|
|
let url= item.content.fullPath;
|
|
let target= item.content.fileSaveTarget;
|
|
if(target=="local"){
|
|
url= this.$u.api.multipartAddress.getFileByPath+url;
|
|
}
|
|
uni.previewImage({
|
|
urls: previewSrcArr.length > 0 ? previewSrcArr : [url],
|
|
current: url,
|
|
loop: false,
|
|
});
|
|
},
|
|
|
|
parseImageSrc:function(item){
|
|
let that=this;
|
|
let msgId= item.id;
|
|
let localSrc= uni.getStorageSync("image"+msgId);
|
|
if(localSrc){
|
|
return localSrc;
|
|
}
|
|
let contentObj=item.content;
|
|
let url= contentObj.fullPath;
|
|
let target= contentObj.fileSaveTarget;
|
|
if(target=="local"){
|
|
let fileName= contentObj.fileName;
|
|
url=this.$u.api.multipartAddress.showFile+fileName;
|
|
}
|
|
that.setImageLocalSrc(url,msgId);
|
|
return url;
|
|
},
|
|
parseImgSize: function(item, type) {
|
|
let contentObj=item.content;
|
|
let height = contentObj.height;
|
|
let width = contentObj.width;
|
|
if (type == "h") {
|
|
if (height == null || height == undefined) {
|
|
return "auto";
|
|
} else {
|
|
return height * 2;
|
|
}
|
|
} else {
|
|
if (width == null || width == undefined) {
|
|
return 300;
|
|
} else {
|
|
return width * 2;
|
|
}
|
|
}
|
|
},
|
|
setImageLocalSrc(url,msgId){
|
|
let that=this;
|
|
that.messageApi.setImageLocalSrc(url,msgId);
|
|
},
|
|
toYYYPerson:function(item){
|
|
let that=this;
|
|
if(item.meFlag==false){
|
|
that.$emit("toYYYPerson",item);
|
|
}
|
|
},
|
|
checkChange:function(msg){
|
|
let that=this;
|
|
that.$emit("checkChange",msg);
|
|
},
|
|
handleMessage:function(menuItem){
|
|
this.toolTipFlag=false;
|
|
this.$emit("handleMessage",menuItem,this.item);
|
|
},
|
|
transform (content, fileSize, fileSuffix,linkName) {
|
|
if (fileSize === undefined) {
|
|
fileSize = '';
|
|
}
|
|
if (fileSuffix === undefined) {
|
|
fileSuffix = '';
|
|
}
|
|
let html = function(end) {
|
|
return new RegExp('\\n*\\[' + (end || '') +
|
|
'(code|pre|div|span|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)]\\n*',
|
|
'g');
|
|
};
|
|
if (content)
|
|
{
|
|
content = content.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/'/g, ''')
|
|
.replace(/"/g, '"') // XSS
|
|
.replace(html(), '<$1 $2>')
|
|
.replace(html('/'), '</$1>') // 转移HTML代码
|
|
.replace(/\n/g, '<br>'); // 转义换行
|
|
content=getUrl(content);
|
|
content=content.replace(/face\[([^\s\[\]]+?)]/g, function(face) {
|
|
let alt = face.replace(/^face/g, '');
|
|
let fa =faceUtil.emojiMap;
|
|
let srcPrefix=faceUtil.emojiUrl;
|
|
let imageSrc=srcPrefix+ fa[alt];
|
|
//console.log("表情",imageSrc);
|
|
let imgContent= '<img class="emoji" src="' +imageSrc+ '"/>';
|
|
return imgContent;
|
|
})
|
|
// 转义图片
|
|
.replace(/img\[([^\s]+?)]/g, function(img) {
|
|
let href = img.replace(/(^img\[)|(]$)/g, '');
|
|
return '<img class="message-img" src="' + href + '" alt="消息图片不能加载">';
|
|
})
|
|
// 转义文件
|
|
.replace(/file\([\s\S]+?\)\[[\s\S]*?]/g, function(str) {
|
|
let href = (str.match(/file\(([\s\S]+?)\)\[/) || [])[1];
|
|
let text = (str.match(/\)\[([\s\S]*?)]/) || [])[1];
|
|
if (!href) return str;
|
|
return '<div class="flex"><i class="iconfont icon-xiazai-yun"></i><a class="message-file" href="' +
|
|
href + '">' + (text || href) + '</a><span>' + fileSize + '</span></div>'
|
|
})
|
|
// 转义音频
|
|
.replace(/audio\[([^\s]+?)]/g, function(audio) {
|
|
return '<div class="message-audio" data-src="' + audio.replace(/(^audio\[)|(]$)/g, '') +
|
|
'"><i class="layui-icon"></i><p>音频消息</p></div>';
|
|
})
|
|
// 转义视频
|
|
.replace(/video\[([^\s]+?)]/g, function(video) {
|
|
return '<div class="message-video" data-src="' + video.replace(/(^video\[)|(]$)/g, '') +
|
|
'"><i class="layui-icon"></i></div>';
|
|
})
|
|
// 转义链接
|
|
.replace(/a\([\s\S]+?\)\[[\s\S]*?]/g, function(str) {
|
|
let href = (str.match(/a\(([\s\S]+?)\)\[/) || [])[1];
|
|
let text = (str.match(/\)\[([\s\S]*?)]/) || [])[1];
|
|
if (!href) return str;
|
|
if(linkName&&linkName.length>0){
|
|
return '<a href="' + href + '" target="_blank">' + linkName + '</a>';
|
|
};
|
|
return '<a href="' + href + '" target="_blank">' + (text || href) + '</a>';
|
|
})
|
|
|
|
}
|
|
return content;
|
|
}
|
|
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.message-item-container {
|
|
padding:0rpx 20rpx;
|
|
}
|
|
|
|
.chat-time {
|
|
padding: 4rpx 0rpx;
|
|
text-align: center;
|
|
font-size: 28rpx;
|
|
color: #aaaaaa;
|
|
}
|
|
|
|
.chat-container {
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: flex-start;
|
|
justify-items: flex-start;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.chat-location-me {
|
|
flex-direction: row-reverse;
|
|
text-align: right;
|
|
}
|
|
|
|
.chat-icon-me {
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.chat-icon-container {
|
|
margin-top: 12rpx;
|
|
}
|
|
|
|
.chat-icon {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 10rpx;
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
.chat-content-container {
|
|
margin: 0rpx 15rpx;
|
|
max-width: 70%;
|
|
}
|
|
|
|
.chat-user-name {
|
|
font-size: 26rpx;
|
|
color: #888888;
|
|
}
|
|
|
|
.chat-text-container {
|
|
//word-break: break-all;
|
|
word-wrap:break-word;
|
|
background-color: #ffffff;
|
|
border-radius: 10rpx;
|
|
padding: 20rpx 20rpx;
|
|
margin-top: 5rpx;
|
|
font-size: 32rpx;
|
|
}
|
|
|
|
.chat-text-container-me {
|
|
background-color: #95ec69;
|
|
}
|
|
|
|
.emoji {
|
|
width: 40rpx !important;
|
|
height: 40rpx !important;
|
|
position: relative;
|
|
top: 10rpx;
|
|
}
|
|
|
|
//语音信息样式
|
|
.content-audio-container {
|
|
background-color: #ffffff;
|
|
border-radius: 10rpx;
|
|
padding: 25rpx 20rpx;
|
|
margin-top: 5rpx;
|
|
/* #ifndef APP-NVUE */
|
|
max-width: 500rpx;
|
|
/* #endif */
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
|
|
.voice_icon {
|
|
height: 34rpx;
|
|
width: 34rpx;
|
|
background-repeat: no-repeat;
|
|
background-size: 100%;
|
|
}
|
|
|
|
.voice_icon_right {
|
|
background-image: url('@/static/images/chat/voice/voice-left-3.png');
|
|
margin-left: 10rpx;
|
|
}
|
|
|
|
.voice_icon_left {
|
|
background-image: url('@/static/images/chat/voice/voice-right-3.png');
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.voice_icon_right_an {
|
|
animation: voiceAn_right 1s linear alternate infinite;
|
|
}
|
|
|
|
.voice_icon_left_an {
|
|
animation: voiceAn_left 1s linear alternate infinite;
|
|
}
|
|
|
|
@keyframes voiceAn_right {
|
|
0% {
|
|
background-image: url('@/static/images/chat/voice/voice-left-1.png');
|
|
}
|
|
|
|
50% {
|
|
background-image: url('@/static/images/chat/voice/voice-left-2.png');
|
|
}
|
|
|
|
100% {
|
|
background-image: url('@/static/images/chat/voice/voice-left-3.png');
|
|
}
|
|
}
|
|
|
|
@keyframes voiceAn_left {
|
|
0% {
|
|
background-image: url('@/static/images/chat/voice/voice-right-1.png');
|
|
}
|
|
|
|
50% {
|
|
background-image: url('@/static/images/chat/voice/voice-right-2.png');
|
|
}
|
|
|
|
100% {
|
|
background-image: url('@/static/images/chat/voice/voice-right-3.png');
|
|
}
|
|
}
|
|
}
|
|
|
|
//我的语音信息样式
|
|
.chat-audio-container-me {
|
|
background-color: #95ec69;
|
|
flex-direction: row-reverse;
|
|
}
|
|
|
|
//文件信息样式
|
|
.contentType-file {
|
|
width: 450rpx;
|
|
padding: 0;
|
|
border-radius: 10rpx;
|
|
border: 1rpx solid #e4e7ed;
|
|
background-color: #ffffff !important;
|
|
}
|
|
|
|
//红包
|
|
.contentType-redbag {
|
|
padding: 20rpx 30rpx;
|
|
padding-bottom: 6rpx;
|
|
border-radius: 10rpx;
|
|
background-color: #f29100;
|
|
color: #ffffff;
|
|
}
|
|
|
|
//位置
|
|
.contentType-location {
|
|
width: 500rpx;
|
|
padding: 0rpx 10rpx;
|
|
border-radius: 10rpx;
|
|
border: 1rpx solid #e4e7ed;
|
|
background-color: #ffffff !important;
|
|
}
|
|
|
|
//组合信息
|
|
.contentType-fixed {
|
|
border-radius: 10rpx;
|
|
font-size: 32rpx;
|
|
word-break: break-word;
|
|
padding: 20rpx;
|
|
background-color: #95ec69 !important;
|
|
border: 1rpx solid #e4e7ed;
|
|
max-width: 400rpx;
|
|
|
|
.img {
|
|
width: 200rpx;
|
|
height: auto;
|
|
max-width: 300rpx;
|
|
max-height: 400rpx;
|
|
}
|
|
}
|
|
|
|
.u-flex-reserve {
|
|
flex-direction: row-reverse;
|
|
}
|
|
|
|
.u-text-reserve {
|
|
text-align: left;
|
|
}
|
|
</style>
|