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

284 lines
6.6 KiB

3 years ago
<!--
* @Author: ch
* @Date: 2022-03-26 14:32:03
* @LastEditors: ch
* @LastEditTime: 2022-05-21 15:43:32
3 years ago
* @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>
3 years ago
<image class="avatar" :src="$store.state.userInfo.avatar || require('@/static/message/xt.png')" mode="widthFix"/>
3 years ago
</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>
3 years ago
<image class="avatar" :src="item.fromAvatar || require('@/static/message/xt.png')" mode="widthFix"/>
3 years ago
<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 {Im, ToAsyncAwait} from '@/common/utils';
3 years ago
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(){
const data = this.$store.state.imData.find(i =>{
return i.id == this.sessionId
}) || {};
3 years ago
if(data.id){
Im.setCurSessionId(data.id);
}
return data;
3 years ago
},
msgData (){
return this.curSessionData ? this.curSessionData.messageList : [];
}
},
watch:{
msgData(){
this.$nextTick(()=>{
3 years ago
uni.setNavigationBarTitle({
title : this.curSessionData.fromNickname
});
3 years ago
uni.pageScrollTo({
scrollTop : 99999,
duration : 0
});
});
}
},
onPageScroll(res) {
if (res.scrollTop <= 0) {
this.getHistoryMsg();
}
},
onLoad(){
if(!this.$store.state.token){
this.$Router.push('/login');
return false;
}
3 years ago
3 years ago
this.goodsId = this.$Route.query.goodsId;
this.orderId = this.$Route.query.orderId;
this.sessionId = this.$Route.query.sessionId;
3 years ago
3 years ago
if(this.goodsId){
this.createSessionMain();
this.getGoodsInfo();
}else if(this.orderId){
this.createSessionMain();
this.getOrderInfo();
}else if(this.sessionId){
this.getHistoryMsg();
this.readMsg();
}else{
this.createSessionMain();
}
3 years ago
uni.pageScrollTo({
scrollTop : 99999,
duration : 0
});
3 years ago
},
methods:{
/**
* 创建会话主体
* 如果是从商品或订单进来需要创建会话
*/
3 years ago
async createSessionMain(){
const {error, result} = await ToAsyncAwait(Im.createSession({
3 years ago
content : {
storeId : 1
3 years ago
}
}));
3 years ago
if(error){
uni.$u.toast(error);
return false;
}
this.sessionId = result.content.id
3 years ago
this.getHistoryMsg();
this.readMsg();
3 years ago
},
/**
* 获取历史消息
*/
3 years ago
async getHistoryMsg(){
3 years ago
this.loading = true;
const lastMsg = this.msgData?.length ? this.msgData[0] : {};
3 years ago
await Im.getHistoryMsg({
3 years ago
content : {
sessionId : this.sessionId,
3 years ago
topMessageId : lastMsg.id || null
}
});
this.loading = false;
3 years ago
},
/**
3 years ago
* 把当前会话消息置为已读
3 years ago
*/
readMsg(){
3 years ago
Im.setRead({
3 years ago
content: {
sessionId : this.sessionId
3 years ago
}
})
3 years ago
},
/**
* 从订单页进来查询订单信息
*/
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>