You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shop-app/pages/account/message/chat/index.vue

309 lines
7.3 KiB

<!--
* @Author: ch
* @Date: 2022-03-26 14:32:03
* @LastEditors: ch
* @LastEditTime: 2022-05-14 18:35:48
* @Description: file content
-->
<template>
<view class="main">
<template v-for="item in msgData">
<view class="send" :key="item.id" v-if="item.fromId == $store.state.userInfo.id">
<template v-if="item.type == MSG_TYPE.CUSTOM">
<GoodsInfo class="send--box" position="msg" v-if="item.payload.id" :goodsInfo="item.payload"/>
<OrderInfo class="send--box" position="msg" v-if="item.payload.orderId" :orderInfo="item.payload"/>
</template>
<view class="send--box send--box__txt" v-if="item.type == MSG_TYPE.TXT">{{item.payload.text}}</view>
<img class="send--box send--box__img" mode="aspectFit" v-if="item.type == MSG_TYPE.IMG"
:src="item.payload.url" @click="previewImg(item.payload.url)"/>
<view class="send--box" v-if="item.type == MSG_TYPE.VIDEO">
<video class="send--box__video" :src="item.payload.url"></video>
</view>
<image class="avatar" :src="item.fromAvatar || '@/static/message/xt.png'" mode="widthFix"/>
</view>
<view class="tips" :key="item.id" v-else-if="item.type == MSG_TYPE.TIP">
<view class="tips--box">{{item.payload.text}}</view>
</view>
<view class="receive" :key="item.id" v-else>
<image class="avatar" :src="item.fromAvatar || '@/static/message/xt.png'" mode="widthFix"/>
<view>
<view class="receive--name">{{item.fromNickname}}</view>
<template v-if="item.type == MSG_TYPE.CUSTOM">
<GoodsInfo class="receive--box" position="msg" v-if="item.payload.id" :goodsInfo="item.payload"/>
<OrderInfo class="receive--box" position="msg" v-if="item.payload.orderId" :orderInfo="item.payload"/>
</template>
<view class="receive--box receive--box__txt" v-if="item.type == MSG_TYPE.TXT">{{item.payload.text}}</view>
<img class="receive--box receive--box__img" mode="aspectFit" v-if="item.type == MSG_TYPE.IMG"
:src="item.payload.url" @click="previewImg(item.payload.url)"/>
<view class="receive--box" v-if="item.type == MSG_TYPE.VIDEO">
<video class="receive--box__video" :src="item.payload.url"></video>
</view>
</view>
</view>
</template>
<Footer :goodsInfo="goodsInfo" :orderInfo="orderInfo"></Footer>
</view>
</template>
<script>
import {MSG_TYPE} from '@/common/dicts/im';
import {MsbWebSkt, createUUID} from '@/common/utils';
import {ApiGetOrderDetail} from '@/common/api/order';
import {ApiGetGoodsDetail} from '@/common/api/goods';
import UiButton from '@/components/UiButton.vue';
import Footer from './components/Footer.vue';
import GoodsInfo from './components/GoodsInfo.vue';
import OrderInfo from './components/OrderInfo.vue';
export default {
components: { UiButton, Footer, GoodsInfo, OrderInfo },
data(){
return {
MSG_TYPE,
orderId : null,
goodsId : null,
sessionId : null,
orderInfo : {},
goodsInfo : {}
}
},
computed:{
curSessionData(){
return this.$store.state.sessionData.find(i =>i.id == this.$store.state.sessionMsgId) || {}
},
msgData (){
return this.curSessionData ? this.curSessionData.messageList : [];
}
},
watch:{
msgData(){
console.log('------+++-');
this.$nextTick(()=>{
uni.pageScrollTo({
scrollTop : 99999,
duration : 0
});
});
}
},
onPageScroll(res) {
// && !this.isInput
if (res.scrollTop <= 0) {
this.getHistoryMsg();
}
},
onLoad(){
if(!this.$store.state.token){
this.$Router.push('/login');
return false;
}
this.goodsId = this.$Route.query.goodsId;
this.orderId = this.$Route.query.orderId;
this.sessionId = this.$Route.query.sessionId;
if(this.goodsId){
this.createSessionMain();
this.getGoodsInfo();
}else if(this.orderId){
this.createSessionMain();
this.getOrderInfo();
}else if(this.sessionId){
this.$store.commit('SET_SESSION_MSG_ID',this.sessionId);
this.getHistoryMsg();
this.readMsg();
this.heartMsg();
}else{
this.createSessionMain();
}
},
methods:{
/**
* 创建会话主体
* 如果是从商品或订单进来,需要创建会话
*/
createSessionMain(){
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : '21',
content : {
storeId : 1
}
}),
success:()=>{
// 不能这样啊啊啊啊
setTimeout(()=>{
this.getHistoryMsg();
this.readMsg();
this.heartMsg();
},1000)
}
});
},
/**
* 发送心跳
*/
heartMsg(){
return false;
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : '22',
content : {
storeId : 1
}
}),
complete: () =>{
setTimeout(()=>{
this.heartMsg();
},1000000)
}
})
},
/**
* 获取历史消息
*/
getHistoryMsg(){
this.loading = true;
const lastMsg = this.msgData?.length ? this.msgData[0] : {};
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : "23",
content: {
sessionId : this.$store.state.sessionMsgId,
topMessageId : lastMsg.id || null
}
})
})
},
/**
* 已读消息
*/
readMsg(){
MsbWebSkt.send({
data : JSON.stringify({
traceId : createUUID(),
traceType : "6",
content: {
sessionId : this.$store.state.sessionMsgId
}
})
});
// 计算页头消息数
const count = this.$store.state.sessionMsgCount - this.curSessionData.unreadCount;
// 计算会话列表消息数
this.curSessionData.unreadCount = 0;
this.$store.commit('SET_SESSION_MSG_COUNT', count)
},
/**
* 从订单页进来查询订单信息
*/
async getOrderInfo(){
const {error, result} = await ApiGetOrderDetail(this.orderId);
if(error){
uni.$u.toast(error.message);
return false;
}
this.orderInfo = result;
},
/**
* 从商品进来查询查询商品信息
*/
async getGoodsInfo(){
const {error, result} = await ApiGetGoodsDetail({id : this.goodsId});
if(error){
uni.$u.toast(error.message);
return false;
}
this.goodsInfo = result;
},
previewImg(logourl) {
let imgsArray = [];
imgsArray[0] = logourl
uni.previewImage({
current: 0,
urls: imgsArray
});
}
}
}
</script>
<style lang="scss">
page{
background: $color-grey1;
padding-bottom: 140px;
}
</style>
<style lang="scss" scoped>
.main{
padding: 40rpx;
}
.avatar{
width: 70rpx;
height: 70rpx;
}
.receive{
display: flex;
justify-content: flex-start;
margin-top:30rpx ;
&--name{
margin:0 0 20rpx 30rpx;
font-size: 24rpx;
color: #333;
}
&--box{
max-width: 552rpx;
margin-left:30rpx;
&__txt{
padding: 20rpx 30rpx;
background: #fff;
border-radius: 16rpx;
color: #333;
font-size: 32rpx;
line-height: 40rpx;
}
&__img{
height: 140rpx;
}
}
}
.send{
display: flex;
justify-content: flex-end;
margin-top:30rpx ;
&--box{
max-width: 552rpx;
margin-right:30rpx;
&__txt{
padding: 20rpx 30rpx;
background: #FF875B;
border-radius: 16rpx;
color: #fff;
font-size: 32rpx;
line-height: 46rpx;
}
&__img{
height: 140rpx;
}
&__video{
max-width: 552rpx;
}
}
}
.tips{
margin-top:30rpx ;
display: flex;
justify-content: center;
&--box{
background: #eee;
color: #9E9E9E;
text-align: center;
border-radius: 30rpx;
padding: 10rpx 30rpx;
line-height: 32rpx;
}
}
</style>