聊天功能

master
2022-12-27 18:01:41 +08:00
commit 9cc6f519a9
5 changed files with 243 additions and 61 deletions

View File

@ -64,7 +64,7 @@ export function getTalk(talkId) {
params params
}); });
} }
// 从商品页点击 客服 跳转 获取聊天记录 // 从商品页点击 客服 跳转 获取商品详情
export function jumpObtain(skuId, goodsId) { export function jumpObtain(skuId, goodsId) {
return http.request({ return http.request({
url: `${api.im}/goods/goods/sku/${goodsId}/${skuId}`, url: `${api.im}/goods/goods/sku/${goodsId}/${skuId}`,

View File

@ -17,12 +17,31 @@
<!-- 用户消息 头像可选加入--> <!-- 用户消息 头像可选加入-->
<view v-if="item.my" class="flex justify-end padding-right one-show align-start padding-top"> <view v-if="item.my" class="flex justify-end padding-right one-show align-start padding-top">
<!-- <image class="chat-img flex-row-center" :src="'https://ikeeppet.oss-cn-zhangjiakou.aliyuncs.com/028b7818b78c47ef8f87a7faa1098faf.jpg'" mode="aspectFill" ></image> --> <!-- <image class="chat-img flex-row-center" :src="'https://ikeeppet.oss-cn-zhangjiakou.aliyuncs.com/028b7818b78c47ef8f87a7faa1098faf.jpg'" mode="aspectFill" ></image> -->
<view class="flex justify-end" style="width: 400rpx;margin-top: 12px;"> <view class="flex justify-end" style="width: 400rpx;margin-top: 12px;">
<view> <view>
<view class="user-name">{{ user.nickName }}</view> <view class="user-name">{{ user.nickName }}</view>
<view class="margin-left padding-chat bg-user-orang" style="border-radius: 35rpx;"> <view class="margin-left padding-chat bg-user-orang" style="border-radius: 35rpx;">
<text style="word-break: break-all;">{{ item.text }}</text> <text style="word-break: break-all;" v-if="item.messageType === 'MESSAGE'">{{ item.text }}</text>
<view v-else>
<view class="goodsCard u-flex u-row-between u-p-b-0" style="width:100%;margin: 0 0; ">
<view class="imagebox" @click="jumpGoodDelic">
<!-- <image class="image" :src="goodLiistData.thumbnail" mode="widthFix"></image> -->
<image class="image" :src="JSON.parse(item.text).thumbnail" mode="widthFix"></image>
</view>
<view class="goodsdesc" @click="jumpGoodDelic">
<view class="goodsdesc-name">
<text class="goodsCard_goodNmae">{{
JSON.parse(item.text).goodsName
}}</text>
</view>
<view class="goodsdesc-rice" style="margin-top:10rpx; color: orange;"><text
style="font-size:20rpx;">¥{{
JSON.parse(item.text).price
}}</text>
</view>
</view>
</view>
</view>
</view> </view>
</view> </view>
</view> </view>
@ -46,13 +65,55 @@
<view> <view>
<view class="other-name">{{ toUser.name }}</view> <view class="other-name">{{ toUser.name }}</view>
<view class="margin-left padding-chat flex-column-start bg-to-color" style="border-radius: 35rpx;"> <view class="margin-left padding-chat flex-column-start bg-to-color" style="border-radius: 35rpx;">
<text style="word-break: break-all;">{{ item.text }}</text> <text style="word-break: break-all;" v-if="item.messageType === 'MESSAGE'">{{ item.text }}</text>
<view v-else>
<view class="goodsCard u-flex u-row-between u-p-b-0" style="width:100%;margin: 0 0; ">
<view class="imagebox" @click="jumpGoodDelic">
<image class="image" :src="JSON.parse(item.text).thumbnail" mode="widthFix"></image>
</view>
<view class="goodsdesc" @click="jumpGoodDelic">
<view class="goodsdesc-name">
<text class="goodsCard_goodNmae">{{
JSON.parse(item.text).goodsName
}}</text>
</view>
<view class="goodsdesc-rice" style="margin-top:10rpx; color: orange;"><text
style="font-size:20rpx;">¥{{
JSON.parse(item.text).price
}}</text>
</view>
</view>
</view>
</view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view class="cartMessage" v-if="showHide && !localImGoodsId && showHideModel">
<view class="goodsCard u-flex u-row-between u-p-b-0">
<view class="imagebox" @click="jumpGoodDelic">
<image class="image" :src="goodLiistData.thumbnail" mode="widthFix"></image>
</view>
<view class="goodsdesc" @click="jumpGoodDelic">
<view class="goodsdesc-name">
<text class="goodsCard_goodNmae">{{
goodLiistData.goodsName
}}</text>
</view>
<view class="goodsdesc-rice" style="margin-top:10rpx; color: orange;"><text style="font-size:20rpx;">¥{{
goodLiistData.price
}}</text>
</view>
</view>
<view class="cancel" @click="cancenModel">X</view>
<view class="sendGood" @click="gotoCards">
<view>发送商品</view>
</view>
</view>
</view>
<!-- loading是显示 --> <!-- loading是显示 -->
<view v-show="msgLoad" class="flex-row-start margin-left margin-top"> <view v-show="msgLoad" class="flex-row-start margin-left margin-top">
<view class="chat-img flex-row-center"> <view class="chat-img flex-row-center">
@ -109,7 +170,20 @@ import SocketService from "@/utils/socket_service.js";
import storage from "@/utils/storage.js"; import storage from "@/utils/storage.js";
import { beautifyTime } from "@/utils/filters.js" import { beautifyTime } from "@/utils/filters.js"
export default { export default {
// imGoodId
onUnload () {
storage.setImGoodsLink('')
},
onLoad (options) { onLoad (options) {
// goodsid
this.showHideModel = options.goodsid
// localimGoodId
this.localImGoodsId = storage.getImGoodsLink()
this.rosolve = options
//
if (this.rosolve.goodsid) {
this.commodityDetails()
}
// msgList // msgList
// //
// , // ,
@ -118,7 +192,6 @@ export default {
query.select('#msgList').boundingClientRect(data => { query.select('#msgList').boundingClientRect(data => {
// 2, // 2,
var up = res.height * 2 - data.height - l * 110 var up = res.height * 2 - data.height - l * 110
console.log(up)
if (up > 0) { if (up > 0) {
// //
this.msgMove(up, 300) this.msgMove(up, 300)
@ -144,6 +217,7 @@ export default {
this.getTalkMessage() this.getTalkMessage()
} else { } else {
this.getTalk(options.userId) this.getTalk(options.userId)
} }
this.ws.connect(); this.ws.connect();
@ -151,7 +225,6 @@ export default {
onPullDownRefresh () { onPullDownRefresh () {
this.params.pageNumber = this.params.pageNumber + 1 this.params.pageNumber = this.params.pageNumber + 1
this.getTalkMessage() this.getTalkMessage()
console.log('下拉事件');
setTimeout(function () { setTimeout(function () {
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
}, 1000); }, 1000);
@ -161,6 +234,9 @@ export default {
}, },
data () { data () {
return { return {
showHideModel: undefined,
localImGoodsId: '',
showHide: true,
msgLoad: false, msgLoad: false,
anData: {}, anData: {},
animationData: {}, animationData: {},
@ -179,6 +255,8 @@ export default {
toUser: {}, toUser: {},
srcollHeight: 0, srcollHeight: 0,
ws: new SocketService(), ws: new SocketService(),
rosolve: {},
goodLiistData: {}
} }
}, },
watch: { watch: {
@ -189,7 +267,6 @@ export default {
this.msgList.push(val.result) this.msgList.push(val.result)
} }
this.newMessageNum++; this.newMessageNum++;
console.log(this.msgList)
// //
let msg = val let msg = val
msg.operation_type = 'READ' msg.operation_type = 'READ'
@ -198,6 +275,37 @@ export default {
} }
}, },
methods: { methods: {
//
jumpGoodDelic () {
uni.navigateTo({
url: `/pages/product/goods?id=${this.rosolve.skuid}&goodsId=${this.rosolve.goodsid}`,
});
},
//
gotoCards () {
let msg = {
operation_type: "MESSAGE",
to: this.toUser.userId,
from: this.user.id,
message_type: "GOODS",
context: this.goodLiistData,
talk_id: this.params.talkId,
}
this.ws.send(JSON.stringify(msg))
this.msgList.push({ "text": JSON.stringify(this.goodLiistData), "my": true })
this.showHide = false
storage.setImGoodsLink(this.params.talkId)
},
//
cancenModel () {
this.showHide = false
},
//
commodityDetails () {
jumpObtain(this.rosolve.skuid, this.rosolve.goodsid).then((res) => {
this.goodLiistData = res.data.result.data
})
},
beautifyTime, beautifyTime,
// (-->bug) // (-->bug)
goPag (kh) { goPag (kh) {
@ -265,11 +373,9 @@ export default {
// //
answer (id) { answer (id) {
// id,index // id,index
console.log(id)
}, },
sendMsg () { sendMsg () {
console.log("发送")
// //
if (this.msg == "") { if (this.msg == "") {
return 0; return 0;
@ -363,6 +469,7 @@ export default {
if (res.data.success) { if (res.data.success) {
this.toUser = res.data.result this.toUser = res.data.result
this.params.talkId = res.data.result.id this.params.talkId = res.data.result.id
this.getTalkMessage()
} }
}) })
}, },
@ -439,7 +546,88 @@ export default {
} }
</script> </script>
<style> <style lang="scss" scoped>
.goodsCard {
border-radius: 20rpx;
margin-top: 15rpx;
background-color: #ffffff;
padding-left: 12rpx;
width: 95%;
height: 120rpx;
display: flex;
flex-wrap: wrap;
color: #302c2b;
position: relative;
.imagebox {
width: 122rpx;
height: 122rpx;
.image {
width: 122rpx;
border-radius: 10rpx;
}
}
.goodsdesc {
flex: 1;
overflow: hidden;
margin-left: 12rpx;
.goodsdesc-name {
font-size: 12px;
line-height: 1.5;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-bottom: 20rpx;
.goodsCard_goodNmae {
color: black;
text-overflow: ellipsis;
font-size: 20rpx;
font-weight: bold;
}
}
.price {
margin-top: 50rpx;
line-height: 2;
margin-left: 5px;
font-size: 26rpx;
font-weight: 700;
}
}
.sendGood {
color: #ffffff;
height: 40rpx;
width: 110rpx;
background-color: #f21c0c;
font-size: 18rpx;
border-radius: 17rpx;
text-align: center;
line-height: 40rpx;
padding: 0 10rpx;
position: relative;
top: 20rpx;
right: 20rpx;
}
}
.cancel {
color: #737373;
position: relative;
bottom: 40rpx;
left: 12%;
}
.cartMessage {
display: flex;
justify-content: center;
align-items: center;
}
.bottom-dh-char { .bottom-dh-char {
background-color: #f9f9f9; background-color: #f9f9f9;
width: 750rpx; width: 750rpx;

View File

@ -36,7 +36,8 @@
<u-tag class="talk-tag" size="mini" text="店铺" type="warning" v-if="item.storeFlag" /> <u-tag class="talk-tag" size="mini" text="店铺" type="warning" v-if="item.storeFlag" />
</view> </view>
<view class="talk-message"> <view class="talk-message">
{{ item.lastTalkMessage }} <span v-if="item.lastMessageType == 'MESSAGE'">{{ item.lastTalkMessage }}</span>
<span v-if="item.lastMessageType == 'GOODS'">[]</span>
</view> </view>
</view> </view>
<view class="talk-time"> <view class="talk-time">
@ -180,6 +181,7 @@ export default {
.talk-time { .talk-time {
position: relative; position: relative;
} }
.iconBox { .iconBox {
width: 94%; width: 94%;
margin: 0 3%; margin: 0 3%;
@ -210,6 +212,7 @@ export default {
} }
} }
} }
.bag { .bag {
width: 56rpx; width: 56rpx;
height: 56rpx; height: 56rpx;
@ -220,6 +223,7 @@ export default {
.bag1 { .bag1 {
background: #ff0015; background: #ff0015;
} }
.bag2 { .bag2 {
background: #73AF7C; background: #73AF7C;
} }

View File

@ -3,12 +3,7 @@
<!-- uni 中不能使用 vue component 所以用if判断每个组件 --> <!-- uni 中不能使用 vue component 所以用if判断每个组件 -->
<div v-for="(item, index) in pageData.list" :key="index"> <div v-for="(item, index) in pageData.list" :key="index">
<!-- 搜索栏如果在楼层装修顶部则会自动浮动否则不浮动 --> <!-- 搜索栏如果在楼层装修顶部则会自动浮动否则不浮动 -->
<u-navbar <u-navbar class="navbar" v-if="item.type == 'search'" :is-back="false" :is-fixed="index === 1 ? false : true">
class="navbar"
v-if="item.type == 'search'"
:is-back="false"
:is-fixed="index === 1 ? false : true"
>
<search style="width: 100%" :res="item.options" /> <search style="width: 100%" :res="item.options" />
<!-- #ifndef H5 --> <!-- #ifndef H5 -->
<!-- 扫码功能 不兼容h5 详情文档: https://uniapp.dcloud.io/api/system/barcode?id=scancode --> <!-- 扫码功能 不兼容h5 详情文档: https://uniapp.dcloud.io/api/system/barcode?id=scancode -->
@ -19,22 +14,10 @@
</u-navbar> </u-navbar>
<carousel v-if="item.type == 'carousel'" :res="item.options" /> <carousel v-if="item.type == 'carousel'" :res="item.options" />
<titleLayout v-if="item.type == 'title'" :res="item.options" /> <titleLayout v-if="item.type == 'title'" :res="item.options" />
<leftOneRightTwo <leftOneRightTwo v-if="item.type == 'leftOneRightTwo'" :res="item.options" />
v-if="item.type == 'leftOneRightTwo'" <leftTwoRightOne v-if="item.type == 'leftTwoRightOne'" :res="item.options" />
:res="item.options" <topOneBottomTwo v-if="item.type == 'topOneBottomTwo'" :res="item.options" />
/> <topTwoBottomOne v-if="item.type == 'topTwoBottomOne'" :res="item.options" />
<leftTwoRightOne
v-if="item.type == 'leftTwoRightOne'"
:res="item.options"
/>
<topOneBottomTwo
v-if="item.type == 'topOneBottomTwo'"
:res="item.options"
/>
<topTwoBottomOne
v-if="item.type == 'topTwoBottomOne'"
:res="item.options"
/>
<flexThree v-if="item.type == 'flexThree'" :res="item.options" /> <flexThree v-if="item.type == 'flexThree'" :res="item.options" />
<flexFive v-if="item.type == 'flexFive'" :res="item.options" /> <flexFive v-if="item.type == 'flexFive'" :res="item.options" />
<flexFour v-if="item.type == 'flexFour'" :res="item.options" /> <flexFour v-if="item.type == 'flexFour'" :res="item.options" />

View File

@ -119,4 +119,11 @@ export default {
removeAfterSaleData() { removeAfterSaleData() {
uni.removeStorageSync(AFTERSALE_DATA); uni.removeStorageSync(AFTERSALE_DATA);
}, },
// 是否发送商品连接记录
setImGoodsLink(val) {
uni.setStorageSync('imGoodId', val);
},
getImGoodsLink() {
return uni.getStorageSync('imGoodId');
},
}; };