聊天功能

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
});
}
// 从商品页点击 客服 跳转 获取聊天记录
// 从商品页点击 客服 跳转 获取商品详情
export function jumpObtain(skuId, goodsId) {
return http.request({
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">
<!-- <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>
<view class="user-name">{{ user.nickName }}</view>
<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>
@ -46,13 +65,55 @@
<view>
<view class="other-name">{{ toUser.name }}</view>
<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 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是显示 -->
<view v-show="msgLoad" class="flex-row-start margin-left margin-top">
<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 { beautifyTime } from "@/utils/filters.js"
export default {
// imGoodId
onUnload () {
storage.setImGoodsLink('')
},
onLoad (options) {
// goodsid
this.showHideModel = options.goodsid
// localimGoodId
this.localImGoodsId = storage.getImGoodsLink()
this.rosolve = options
//
if (this.rosolve.goodsid) {
this.commodityDetails()
}
// msgList
//
// ,
@ -118,7 +192,6 @@ export default {
query.select('#msgList').boundingClientRect(data => {
// 2,
var up = res.height * 2 - data.height - l * 110
console.log(up)
if (up > 0) {
//
this.msgMove(up, 300)
@ -144,6 +217,7 @@ export default {
this.getTalkMessage()
} else {
this.getTalk(options.userId)
}
this.ws.connect();
@ -151,7 +225,6 @@ export default {
onPullDownRefresh () {
this.params.pageNumber = this.params.pageNumber + 1
this.getTalkMessage()
console.log('下拉事件');
setTimeout(function () {
uni.stopPullDownRefresh();
}, 1000);
@ -161,6 +234,9 @@ export default {
},
data () {
return {
showHideModel: undefined,
localImGoodsId: '',
showHide: true,
msgLoad: false,
anData: {},
animationData: {},
@ -179,6 +255,8 @@ export default {
toUser: {},
srcollHeight: 0,
ws: new SocketService(),
rosolve: {},
goodLiistData: {}
}
},
watch: {
@ -189,7 +267,6 @@ export default {
this.msgList.push(val.result)
}
this.newMessageNum++;
console.log(this.msgList)
//
let msg = val
msg.operation_type = 'READ'
@ -198,6 +275,37 @@ export default {
}
},
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,
// (-->bug)
goPag (kh) {
@ -265,11 +373,9 @@ export default {
//
answer (id) {
// id,index
console.log(id)
},
sendMsg () {
console.log("发送")
//
if (this.msg == "") {
return 0;
@ -363,6 +469,7 @@ export default {
if (res.data.success) {
this.toUser = res.data.result
this.params.talkId = res.data.result.id
this.getTalkMessage()
}
})
},
@ -439,7 +546,88 @@ export default {
}
</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 {
background-color: #f9f9f9;
width: 750rpx;

View File

@ -36,7 +36,8 @@
<u-tag class="talk-tag" size="mini" text="店铺" type="warning" v-if="item.storeFlag" />
</view>
<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 class="talk-time">
@ -60,7 +61,7 @@ import { getTalkList } from "@/api/im.js";
import storage from "@/utils/storage.js";
import { beautifyTime } from "@/utils/filters.js"
export default {
data() {
data () {
return {
count: {
loadStatus: "more",
@ -73,10 +74,10 @@ export default {
components: {
beautifyTime
},
onShow() {
onShow () {
this.getList();
},
onPullDownRefresh() {
onPullDownRefresh () {
this.getList()
console.log('下拉事件');
setTimeout(function () {
@ -86,12 +87,12 @@ export default {
/**
* 触底加载
*/
onReachBottom() {
onReachBottom () {
this.getList();
},
methods: {
beautifyTime,
onclickToTalkInfo(val) {
onclickToTalkInfo (val) {
storage.setTalkToUser(val)
uni.navigateTo({
url:
@ -101,7 +102,7 @@ export default {
/**
* 获取聊天列表
*/
getList() {
getList () {
let params = {
userName: this.userName,
}
@ -115,15 +116,15 @@ export default {
}
});
},
navigateTo(url) {
navigateTo (url) {
uni.navigateTo({
url,
});
},
cleanUnread(){
cleanUnread () {
},
search() {
search () {
},
// clear() {
@ -180,6 +181,7 @@ export default {
.talk-time {
position: relative;
}
.iconBox {
width: 94%;
margin: 0 3%;
@ -210,6 +212,7 @@ export default {
}
}
}
.bag {
width: 56rpx;
height: 56rpx;
@ -220,6 +223,7 @@ export default {
.bag1 {
background: #ff0015;
}
.bag2 {
background: #73AF7C;
}

View File

@ -3,12 +3,7 @@
<!-- uni 中不能使用 vue component 所以用if判断每个组件 -->
<div v-for="(item, index) in pageData.list" :key="index">
<!-- 搜索栏如果在楼层装修顶部则会自动浮动否则不浮动 -->
<u-navbar
class="navbar"
v-if="item.type == 'search'"
:is-back="false"
:is-fixed="index === 1 ? false : true"
>
<u-navbar class="navbar" v-if="item.type == 'search'" :is-back="false" :is-fixed="index === 1 ? false : true">
<search style="width: 100%" :res="item.options" />
<!-- #ifndef H5 -->
<!-- 扫码功能 不兼容h5 详情文档: https://uniapp.dcloud.io/api/system/barcode?id=scancode -->
@ -19,22 +14,10 @@
</u-navbar>
<carousel v-if="item.type == 'carousel'" :res="item.options" />
<titleLayout v-if="item.type == 'title'" :res="item.options" />
<leftOneRightTwo
v-if="item.type == 'leftOneRightTwo'"
: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"
/>
<leftOneRightTwo v-if="item.type == 'leftOneRightTwo'" :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" />
<flexFive v-if="item.type == 'flexFive'" :res="item.options" />
<flexFour v-if="item.type == 'flexFour'" :res="item.options" />
@ -80,12 +63,12 @@ import tpl_notice from "@/pages/tabbar/home/template/tpl_notice"; //标题栏模
import tpl_promotions from "@/pages/tabbar/home/template/tpl_promotions_detail"; //
export default {
data() {
data () {
return {
config,
pageData: "", //
isIos: "",
enableLoad:false, //
enableLoad: false, //
};
},
components: {
@ -109,7 +92,7 @@ export default {
promotions: tpl_promotions,
},
mounted() {
mounted () {
this.init();
// #ifdef MP-WEIXIN
//
@ -121,23 +104,23 @@ export default {
/**
* 实例化首页数据楼层
*/
init() {
init () {
this.pageData = "";
getFloorData().then((res) => {
if (res.data.success) {
const result = JSON.parse(res.data.result.pageData)
this.pageData = result;
if(result.list.length){
if (result.list.length) {
//
result.list[result.list.length-1] ? result.list[result.list.length-1].model == 'goods' ? this.enableLoad = true : '' : ''
}
result.list[result.list.length - 1] ? result.list[result.list.length - 1].model == 'goods' ? this.enableLoad = true : '' : ''
}
}
});
},
//
isConnected(val){
val ? this.init() : ''
},
//
isConnected (val) {
val ? this.init() : ''
},
/**
* TODO 扫码功能后续还会后续增加
@ -147,18 +130,18 @@ export default {
* 扫描二维码登录
* 扫描其他站信息 弹出提示返回首页
*/
seacnCode() {
seacnCode () {
uni.scanCode({
success: function (res) {
let path = encodeURIComponent(res.result);
if(path!=undefined && path.indexOf("QR_CODE_LOGIN_SESSION")==0){
if (path != undefined && path.indexOf("QR_CODE_LOGIN_SESSION") == 0) {
console.log(path)
//app
uni.navigateTo({
url:"/pages/passport/scannerCodeLoginConfirm?token="+path
url: "/pages/passport/scannerCodeLoginConfirm?token=" + path
});
return;
}
@ -192,7 +175,7 @@ export default {
/**
* 提示获取权限
*/
tipsGetSettings() {
tipsGetSettings () {
uni.showModal({
title: "提示",
content: "您已经关闭相机权限,去设置",
@ -212,7 +195,7 @@ export default {
* 唤醒客户端扫码
* 没权限去申请权限有权限获取扫码功能
*/
async scan() {
async scan () {
// #ifdef APP-PLUS
this.isIos = plus.os.name == "iOS";
// Ios

View File

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