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.

1808 lines
52 KiB

3 weeks ago
<template>
<view class="content">
<!-- 聊天内容 -->
<scroll-view class="chat" scroll-y="true" scroll-with-animation="true" :scroll-into-view="scrollToView"
refresher-enabled="true" :refresher-triggered="triggered" :refresher-threshold="100"
refresher-background="#f0f0f0" @refresherpulling="onPulling"
@refresherrefresh="onRefresh" @refresherrestore="onRestore" @refresherabort="onAbort">
<view class="chat-main" :style="{paddingBottom:inputh+'px'}">
<!-- <view class="chat-ls" v-if="unshiftmsg.length==0">
<view class="chat-time">现在可以开始聊天了.</view>
</view> -->
<view class="chat-ls" v-for="(item,index) in unshiftmsg" :key="index" :id="'msg'+ index">
<view class="chat-time" v-if="item.fromtime != ''">{{changeTime(item.fromtime)}}</view>
<view class="msg-m msg-left" v-if="item.fromuser !== userid">
<view class="user-img" >
<image class="uimg" :src="item.headimg" @error="handleImageError($event,index)"></image>
<text class="uname">{{item.fromname}}</text>
</view>
<view class="message" v-if="item.type == 'txt'">
<!-- 文字 -->
<view class="msg-text">
<text selectable>{{item.content}}</text>
</view>
</view>
<view class="message" v-if="item.type == 'image'" @tap="previewImg(item.content)">
<!-- 图像 -->
<image :src="item.content" class="msg-img" mode="widthFix"></image>
</view>
<view class="messagevideo" v-if="item.type == 'video'">
<!-- 视频 -->
<myVideo :videoUrl="item.content"></myVideo>
</view>
<view class="message" v-if="item.type == 'audio'" @click="playVoice(item.content,item.ifaudio,index)">
<!-- 音频 -->
<view class="msg-text voice" :style="{width:item.time*40+'rpx'}">
<view class="voicel" v-if="item.ifaudio" >
<div class="bg voicePlay"></div>
</view>
<image v-else src="../../static/icon/horn.png" class="voice-img"></image>
{{item.time}}
</view>
</view>
<view class="message" v-if="item.type == 'product'">
<view v-if="item.send" class="msg-product" @click="gotoDetail(item)">
<view v-if="item.send.type==3" class="zx">
<view class="zxname">订单咨询</view>
<view class="zxview">查看订单</view>
</view>
<view class="msg-con">
<image class="img" :src="item.send.pic" mode="aspectFit"></image>
<view class="info">
<view class="name">
<text class="ntxt">{{item.send.name}}</text>
<text v-if="item.send.spData" v-for="(value, key) in item.send.spData" :key="key" class="txt">
{{ key }}: {{ value }}
</text>
</view>
<view class="xq">
<view class="list">
<view v-if="item.send.type==3" class="ord">
购买金额:¥ <text style="font-size: 30rpx;">{{item.send.price}}</text>{{(item.send.unit?'/'+item.send.unit:'')}}
</view>
<view v-else class="price">
¥{{item.send.price+(item.send.unit?'/'+item.send.unit:'')}}
</view>
<view v-if="item.send.quantity" class="qty">
{{item.send.quantity?'共('+item.send.quantity+(item.send.unit?item.send.unit:'件')+')':''}}
</view>
<div v-if="item.send.spData" v-for="(value, key) in item.send.spData" :key="key" class="qty">
{{ key }}: {{ value }}
</div>
</view>
<button class="btn" type="primary" v-if="item.send.type==1"></button>
<button class="btn" type="primary" v-if="item.send.type==2"></button>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="msg-m msg-right" v-if="item.fromuser == userid">
<view class="user-img" >
<image class="uimg" :src="item.headimg" @error="handleImageError($event,index)" ></image>
<!-- <text class="uname"></text> -->
<text class="uname">{{item.fromname}}</text>
</view>
<view v-if="item.type == 'txt'" class="message">
<view class="msg-text">
<text selectable>{{item.content}}</text>
</view>
</view>
<view v-if="item.type == 'image'" @tap="previewImg(item.content)" class="message">
<image :src="item.content" class="msg-img" mode="widthFix"></image>
</view>
<view v-if="item.type == 'video'" class="messagevideo">
<!-- 视频 -->
<myVideo :videoUrl="item.content"></myVideo>
</view>
<view v-if="item.type == 'audio'" @click="playVoice(item.content,item.ifaudio,index)" class="message">
<!-- 音频 -->
<view class="msg-text voice" :style="{width: item.time>2? item.time*40+'rpx' :'auto'}">
{{item.time}}
<view class="voicel" v-if="item.ifaudio" >
<div class="bg voicePlay"></div>
</view>
<image v-else src="../../static/icon/hornrw.png" class="voice-img"></image>
</view>
</view>
<view v-if="item.type == 'product'" class="message" >
<view v-if="item.send" class="msg-product" @click="gotoDetail(item)">
<view v-if="item.send.type==3" class="zx">
<view class="zxname">订单咨询</view>
<view class="zxview">查看订单</view>
</view>
<view class="msg-con">
<image class="img" :src="item.send.pic" mode="aspectFit"></image>
<view class="info">
<view class="name">
<text class="ntxt">{{item.send.name}}</text>
<text v-if="item.send.spData" v-for="(value, key) in item.send.spData" :key="key" class="txt">
{{ key }}: {{ value }}
</text>
</view>
<view class="xq">
<view class="list">
<view v-if="item.send.type==3" class="ord">
购买金额:¥ <text style="font-size: 30rpx;">{{item.send.price}}</text>{{(item.send.unit?'/'+item.send.unit:'')}}
</view>
<view v-else class="price">
¥{{item.send.price+(item.send.unit?'/'+item.send.unit:'')}}
</view>
<view class="qty">
{{item.send.quantity?'共('+item.send.quantity+(item.send.unit?item.send.unit:'件')+')':''}}
</view>
</view>
<button class="btn" type="primary" v-if="item.send.type==1"></button>
<button class="btn" type="primary" v-if="item.send.type==2"></button>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="popup" v-if="ifsend&&sendinfo">
<view class="tipcon" click="gotoXQ()">
<image class="img" :src="sendinfo.pic" mode="aspectFit"></image>
<view class="info">
<view class="name">
<text class="ntxt">{{sendinfo.name}}</text>
<text v-if="sendinfo.spData" v-for="(value, key) in sendinfo.spData" :key="key" class="txt">
{{ key }}: {{ value }}
</text>
</view>
<view class="xq">
<view class="list">
<view v-if="sendinfo.type==3" class="ord">
购买金额:¥ <text style="font-size: 30rpx;">{{sendinfo.price}}</text>{{(sendinfo.unit?'/'+sendinfo.unit:'')}}
</view>
<view v-else class="price">
¥{{sendinfo.price+(sendinfo.unit?'/'+sendinfo.unit:'')}}
</view>
<view class="qty">
{{sendinfo.quantity?'共('+sendinfo.quantity+(sendinfo.unit?sendinfo.unit:'件')+')':''}}
</view>
</view>
<button class="btn" type="primary" v-if="sendinfo.type==1" @click="sendServer()"></button>
<button class="btn" type="primary" v-if="sendinfo.type==2" @click="sendServer()"></button>
<button class="btn" type="primary" v-if="sendinfo.type==3" @click="sendServer()"></button>
</view>
<view class="close">
<uni-icons type="closeempty" color="#bebdbd" size="16" @click="close()" ></uni-icons>
</view>
</view>
</view>
</view>
<submit @inputs="inputs" @heights="heights"></submit>
<u-toast ref="uToast" />
</view>
</template>
<script>
import { myCache } from '../../utils/utils.js';
import dateTime from '@/common/dateTime.js';
import submit from '@/components/chat/submit.vue';
import myVideo from "@/components/myVideo.vue";
//音频播放
const innerAudioContext = uni.createInnerAudioContext();
export default {
components: {
submit,
myVideo
},
data() {
return {
text:"",
triggered: false,
userName: "",
userid: "",
userheadimg: "",
info:{},// 会话基本信息
imgurl:"",// uni.$http.baseUrl,
iftop:true,
msg: [], // 排序用,暂不使用
// 反转数据接收
unshiftmsg: [
// {
// fromuser: "11",
// fromname: "Madeline 老师 (女)",
// fromtime:'2025-06-20 10:00:00',
// headimg:require("@/static/image/i1.png"),
// content:'Hixxx我是普拉提教练小a周日上午10点的课您可以准时参加吧',
// type:'txt'
// },
], // chatrurn
imgMsg: [],
scrollToView: '',
oldTime: new Date(),
inputh: '90',
ifaudio:false, // 是否音频
socketTask: null, // WebSocket实例
isConnected: false, // WebSocket连接状态
heartbeatInterval: null, // 心跳包20秒连接一次
heartbeatTimeout: 20000, // 心跳间隔时间例如每20秒发送一次
// 是否需要发送 商品,课程,订单
ifsend: false,
sendinfo:{
// type:1,// 1 商品2 课程3订单
// id:63,
// orderId:"6455194061326336",
// name:"零基础教练培训",
// pic:"/static/image/i1.png",
// price:1000,
// unit: "元",
// brandName: "yoga",
// isCourse: 0,
// quantity:1,
// spData:{"颜色":"绿","尺寸":"80"}
}
}
},
onLoad(options) {
var user = myCache('user');
// 本人聊天信息
this.userName=user.nickName?user.nickName:"";
this.userid=user.userid?user.userid:"";
this.userheadimg=user.avatar?user.avatar:require("@/static/image/girl.png");
if(options.data){
// 会话信息
this.info=JSON.parse(decodeURIComponent(options.data));
console.log("chat",this.info)
// 会话标题
var title = this.info.chatName;
uni.setNavigationBarTitle({
title: title,
});
if(this.info.sendinfo){
this.ifsend=true;
this.sendinfo=this.info.sendinfo;
this.$forceUpdate();
}
else{
this.ifsend=false;
this.sendinfo=null;
this.$forceUpdate();
}
// 先获取聊天记录缓存
this.getchatstore();
}
},
onShow() {
// 跳转到最后一条数据 与前面的:id进行对照
setTimeout(() => {
console.log("onShow")
this.screendo(this.unshiftmsg.length - 1);
}, 100);
// 如果心跳包在发送,先停止,再启动
if(this.heartbeatInterval){
clearInterval(this.heartbeatInterval); // 停止心跳包发送
}
// socket接收实时消息
this.socketinit();
},
onBackPress(options) {
if (options.from === 'backbutton') {
// 来自顶部菜单的返回按钮
// 在这里处理你的逻辑
console.log('返回按钮被点击');
this.closeWebSocket();
uni.onSocketClose(function (res) {
console.log('WebSocket 已关闭!');
});
return false;
}
},
beforeDestroy() {
console.log('界面关闭socketbeforeDestroy');
// 在组件销毁前,确保关闭 WebSocket 连接
this.closeWebSocket();
clearInterval(this.heartbeatInterval); // 停止心跳包发送
},
methods: {
gotoDetail(item){
var send=item.send;
if(send){
if(send.type==1){
// 商品
uni.navigateTo({
url: `/pages/product/detail?id=${send.id}`
});
}
else if(send.type==2){
// 课程
uni.navigateTo({
url: `/pages/product/cdetail?id=${send.id}`
});
}
else if(send.type==3){
// 订单详情
uni.navigateTo({
url: `/pages/order/orderinfo?id=${send.orderId}`
});
}
}
},
// 关闭框
close(){
this.ifsend=false;
this.$forceUpdate();
},
// 发送服务信息
sendServer(){
let data = {
"fromname": this.userName,
"fromuser": this.userid,
"headimg": this.userheadimg,
"toname": this.info.chatName, // 接收人
"touser": this.info.friendId, // 接收人姓名
"content": this.sendinfo.id,
"time": 0,
"ifaudio":false,
"fromtime": new Date(),
"type": "product", // this.sendinfo.type==3?"5":"6" // 5订单 6 商品
"send":this.sendinfo
};
this.unshiftmsg.push(data);
var rindex=this.unshiftmsg.length-1;
// 消息发送
this.onSendWS(data,rindex);
},
// 发送消息跳转详情
gotoXQ(){
if(this.sendinfo.type==1){
// 1 商品
uni.navigateTo({
url: `/pages/product/detail?id=`+this.sendinfo.id
});
}
else if(this.sendinfo.type==2){
// 2 课程
uni.navigateTo({
url: `/pages/product/cdetail?id=`+this.sendinfo.id
});
}
else if(this.sendinfo.type==3){
// 3订单
uni.navigateTo({
url: `/pages/order/orderinfo?id=`+this.sendinfo.id
});
}
},
// 获取聊天记录
getchatstore(){
var that=this;
try{
// 先获取会话缓存
var data= myCache(this.info.chatId)?myCache(this.info.chatId):[];
console.log("data",data)
data.forEach((cell,i)=>{
cell["ifaudio"]=false;
//时间间隔处理
if (i < this.unshiftmsg.length - 1) {
//这里表示头部时间还是显示一下
let t = dateTime.spaceTime(this.oldTime, cell.fromtime);
if (t) {
this.oldTime = t;
}
cell.fromtime = t;
}
// 获取图片,为下面的预览做准备
if (cell.type == 'image') {
this.imgMsg.unshift(cell.content)
}
else if(cell.type=='txt'){
cell.content=decodeURIComponent(cell.content);
}
this.unshiftmsg.push(cell);
});
if(this.unshiftmsg.length<=0)
{
if(this.info.from=="yh"){
// 首次会话自动信息
var cont = 'Hi'+this.userName+',欢迎您!我是'+this.info.chatName+',请问有什么可以帮助您的呢?';
this.unshiftmsg = [
{
"fromname": this.info.chatName, // 发送人
"fromuser": this.info.friendId, // 发送人
"headimg": this.info.chatAvatar, // 发送人
"toname": this.userName, // 接收人
"touser": this.userid, // 接收人姓名
"content": cont,
"minId":this.info.minId,
"time": 0,
"ifaudio":false,
"fromtime": new Date(),
"type": 'txt'
}
];
this.$forceUpdate();
}
else{
// 首次会话自动信息
var cont = 'Hi'+this.userName+',欢迎您!我是'+this.info.chatName+',请问有什么可以帮助您的呢?';
this.unshiftmsg = [
{
"fromname": this.info.chatName, // 发送人
"fromuser": this.info.friendId, // 发送人
"headimg": this.info.chatAvatar, // 发送人
"toname": this.userName, // 接收人
"touser": this.userid, // 接收人姓名
"content": cont,
"minId":this.info.minId,
"time": 0,
"ifaudio":false,
"fromtime": new Date(),
"type": 'txt'
}
];
this.$forceUpdate();
}
// 如果是第一次接收消息没有缓存且有minId则拉取离线消息
if(this.info.minId){
this.readUp(1);
}
}
else{
// 跳转到最后一条数据 与前面的:id进行对照
setTimeout(() => {
that.screendo(that.unshiftmsg.length-1);
}, 100);
// 已经有缓存,则拉取离线消息
this.info.minId=this.unshiftmsg[this.unshiftmsg.length-1].id;
this.$forceUpdate();
// 请求服务器加载加载拉取离线聊天记录
if(this.info.minId&&this.info.minId>0){
this.readUp(1);
}
}
}
catch(err){
console.log(err);
}
},
// 定时心跳包
startHeartbeat() {
console.log("startHeartbeat")
this.heartbeatInterval = setInterval(() => {
if (this.socketTask) {
this.socketTask.send({
data: JSON.stringify({
'cmd': 1,//心跳
'data': {
'accessToken':uni.getStorageSync("token")
},
}) // 发送心跳包数据
});
}
}, this.heartbeatTimeout);
},
// ws接收消息
socketinit(){
var that = this;
if (!this.isConnected) {
this.socketTask=uni.connectSocket({
url: "wss://www.sanduolantoyoga.com/yoga-imserver/",
header: {
// 'content-type': 'application/json',
Authorization: uni.getStorageSync("token"),
},
success: (res) => {
console.log(res, 'socket连接成功success');
},
fail: (res) => {
console.log(res, 'socket连接失败')
},
complete: (res) => {
console.log(res,'socket连接成功complete');
}
});
uni.onSocketOpen(res => {
console.log('WebSocket连接已打开');
that.isConnected = true;
// 发送登录心跳包
uni.sendSocketMessage({
data: JSON.stringify({
"cmd": 0,//心跳
"data": {
"accessToken":uni.getStorageSync("token"),
},
}), // 发送心跳包数据 // 发送的消息内容
success(re) {
console.log(re);
console.log('消息发送成功!')
},
fail(err) {
console.log(err);
console.log('消息发送失败!')
}
});
// 发送心跳包
this.startHeartbeat();
});
uni.onSocketMessage(res => {
console.log('收到WebSocket服务器消息');
if(res.data){
let data=JSON.parse(res.data);
console.log(data);
if(data.data){
data=data.data;
if(data){
// 是发送者发送来的消息
if(data.recvId&&data.recvId.toString()==that.userid.toString()&&data.sendId.toString()==this.info.friendId.toString()){
// 加入聊天记录
// 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 5 订单 6 商品 10, "撤回" 11, "已读 "12, "消息已读回执 " 30,"加载中标记"
if(data.type==0||data.type==1||data.type==2||data.type==3||data.type==4||data.type==5||data.type==6){
if(data.type==0){
data.content=decodeURIComponent(data.content);
}
// 获取图片,为下面的预览做准备
if(data.type == 1) {
this.imgMsg.unshift(data.content)
}
let mdata = {
"fromname": this.info.chatName,
"fromuser": this.info.friendId,
"headimg": this.info.chatAvatar,
"toname": this.userName,
"touser": this.userid,
"content": data.content,
"time": data.type==3?5:0,
"ifaudio":data.type==3? true:false,
"fromtime": data.sendTime,
"type": data.type,
"id": data.id,
"recvId": data.recvId,
"sendId": data.sendId
};
this.setMsglist(mdata)
// 接收到socket信息后更新聊天列表记录
var chatlastinfo={
id: this.info.chatId,
content:data.content,
type:data.type,
minId: data.id,
datetime: data.sendTime,
name: this.info.chatName,
userid: this.userid,
fromuser: this.info.friendId,
img: this.info.chatAvatar,
sort:"privatechat"
};
this.updateChatList(chatlastinfo);
// 已读操作
this.readed();
}
else{
// 10, "撤回" 11, "已读 " 12, "消息已读回执 " 30,"加载中标记"
}
}
}
}
}
});
uni.onSocketClose(res => {
console.log('WebSocket连接已关闭');
that.isConnected = false;
clearInterval(that.heartbeatInterval); // 停止心跳包发送
});
uni.onSocketError(err => {
console.error('WebSocket连接打开失败请检查', err);
clearInterval(that.heartbeatInterval); // 停止心跳包发送
});
}
},
// 关闭WebSocket连接
closeWebSocket() {
if (this.socket) {
uni.closeSocket();
this.socket = null;
this.isConnected = false;
}
},
async setMsglist(data){
data.send=data.type==6?await this.getProduct(data.content):(data.type==5?await this.getOrder(data.content):null);
data.type=data.type==0?'txt':(data.type==1?'image':data.type==3?'audio':(data.type==4?'video':(data.type==5?'order':(data.type==6?'product':'')))),
console.log("setMsglist",data)
this.unshiftmsg.push(data);
this.$forceUpdate();
setTimeout(() => {
this.screendo(this.unshiftmsg.length-1);
}, 100);
// 缓存聊天
myCache(this.info.chatId,this.unshiftmsg);
},
async getProduct(id){
console.log("getProduct",id)
var rets=null;
const {data: res} = await uni.$http.post("/api/message/private/getProductForIm",{"productId":id});
if(res.data){
var data=res.data;
rets={
type:data.isCourse==0?1:2,// 1 商品2 课程3订单
id:data.id,
name:data.name,
pic:data.pic,
price:data.price,
unit: data.unit,
brandName:data.brandName,
isCourse:data.isCourse
}
console.log(rets)
return rets;
}
else{
return rets;
}
},
async getOrder(id){
var rets=null;
const {data: res} = await uni.$http.post("/api/message/private/getOrderForIm",{"orderItemId":id});
if(res.data){
var data=res.data;
rets={
type:3,// 1 商品2 课程3订单
id:data.id,
orderId:data.orderId,
name:data.productName,
pic:data.pic?data.pic:'/static/image/nopic.png',
price:data.totalAmount,
quantity:data.quantity,
spData: data.spData? JSON.parse(data.spData):null
}
return rets;
}
else{
return rets;
}
},
// 已读推送
async readed() {
const {data: res} = await uni.$http.put('/api/message/private/readed?friendId='+this.info.friendId);
},
// 已读推送
async readUp(ii) {
const {data: res} = await uni.$http.put('/api/message/private/readed?friendId='+this.info.friendId);
this.getList(ii);
},
// 加载对话
async getList(ii) {
var that=this;
const {data: res} = await uni.$http.get('/api/message/private/pullOfflineMessage',{minId: this.info.minId});
this.triggered = false;
if(res.data&&res.data.length>0){
const gotonum=res.data.length;
var type=0;
res.data.forEach((cell,i)=>{
type=cell.type;
cell["ifaudio"]=false;
//时间间隔处理
if (i < this.unshiftmsg.length - 1) {
//这里表示头部时间还是显示一下
let t = dateTime.spaceTime(this.oldTime, cell.fromtime);
if (t) {
this.oldTime = t;
}
cell.fromtime = t;
}
// 获取图片,为下面的预览做准备
if (cell.type == 1) {
this.imgMsg.unshift(cell.content)
}
else if(cell.type==0){
cell.content=decodeURIComponent(cell.content);
}
// // 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 5 订单 6 商品 10, "撤回" 11, "已读 "12, "消息已读回执 " 30,"加载中标记"
let mdata = {
"fromname": this.userName,
"fromuser": this.userid,
"headimg": cell.headImage?cell.headImage:'/static/image/kfr.png',
"toname": this.info.chatName, // 接收人
"touser": this.info.friendId, // 接收人姓名
"content": cell.content,
"time": cell.type==3?5:0,
"ifaudio":cell.type==3? true:false,
"fromtime": cell.sendTime,
"type": data.type==0?'txt':(data.type==1?'image':data.type==3?'audio':(data.type==4?'video':(data.type==5?'order':(data.type==6?'product':'')))),
"id": cell.id,
"recvId": cell.recvId,
"sendId": cell.sendId,
};
this.unshiftmsg.unshift(mdata);
});
if(ii==2){
// 跳转到加载数据的第一条 与前面的:id进行对照
setTimeout(() => {
that.screendo(gotonum -1);
}, 100);
}
else{
// 跳转到最后一条数据 与前面的:id进行对照
setTimeout(() => {
that.screendo(that.unshiftmsg.length-1);
}, 100);
}
// 缓存聊天
myCache(this.info.chatId,this.unshiftmsg);
this.info.minId=this.unshiftmsg[this.unshiftmsg.length-1].id;
this.$forceUpdate();
// 离线加载后更新聊天列表记录
var chatlastinfo={
id: this.info.chatId,
content:this.unshiftmsg[this.unshiftmsg.length-1].content,
type: type,
minId: this.unshiftmsg[this.unshiftmsg.length-1].id,
datetime: this.unshiftmsg[this.unshiftmsg.length-1].sendTime,
name: this.info.chatName,
userid: this.userid,
fromuser: this.info.friendId,
img: this.info.chatAvatar,
sort:"privatechat"
};
this.updateChatList(chatlastinfo);
}
},
screendo(scrindex){
this.scrollToView = '';
// 跳转到最后一条数据 与前面的:id进行对照
this.$nextTick(function() {
this.scrollToView = 'msg' + scrindex
});
},
// 自定义下拉刷新控件被下拉
onPulling(e) {
var that=this;
if (!this.triggered) {
//下拉刷新先变true再变false才能关闭
this.triggered = true;
//关掉圈圈,需要先执行完刷新操作
setTimeout(() => {
that.triggered = false;
}, 2000);
}
},
// 自定义下拉刷新被触发
onRefresh(event){
// 加载聊天记录
this.readUp(2);
},
// 自定义下拉刷新被复位
onRestore() {
this.triggered = 'restore'; // 需要重置
console.log("onRestore");
},
// 自定义下拉刷新被中止
onAbort() {
this.triggered = false;
console.log("onAbort");
},
changeTime(date) {
return dateTime.dateTime1(date);
},
// 进行图片的预览
previewImg(e) {
let index = 0;
for (let i = 0; i < this.imgMsg.length; i++) {
if (this.imgMsg[i] == e) {
index = i;
}
}
// 预览图片
uni.previewImage({
current: index,
urls: this.imgMsg,
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
},
//音频播放
playVoice(e,ifplay,index) {
var that=this;
// 先关闭停止所有
innerAudioContext.src = '';
innerAudioContext.stop();
that.unshiftmsg.forEach((cell,i)=>{
cell.ifaudio=false;
});
ifplay=!ifplay;
this.unshiftmsg[index].ifaudio=ifplay;
this.$forceUpdate();
if(ifplay){
innerAudioContext.src = e;
innerAudioContext.play(() => {
console.log('开始播放');
});
// 监听音频播放结束事件
innerAudioContext.onEnded((res) => {
console.log('音频播放结束');
that.unshiftmsg[index].ifaudio=!ifplay;
that.$forceUpdate();
// 在这里执行你想要的操作
});
// innerAudioContext.onPlay(() => {
// console.log('开始播放');
// });
}
else{
innerAudioContext.src = '';
innerAudioContext.stop();
}
},
//地图定位
covers(e) {
let map = [{
latitude: e.latitude,
longitude: e.longitude,
iconPath: '../../static/image/head.png'
}]
return (map);
},
//跳转地图信息
openLocation(e) {
uni.openLocation({
latitude: e.latitude,
longitude: e.longitude,
name: e.name,
address: e.address,
success: function() {
console.log('success');
}
});
},
fullscreenchange(e){
if(!e.detail.fullScreen){ // 退出全屏,锁定竖屏
plus.screen.lockOrientation('portrait-primary');
}
},
//接受输入内容
async inputs(e) {
console.log("inputs");
console.log(e);
var rindex=this.unshiftmsg.length-1;
let data = {
"fromname": this.userName,
"fromuser": this.userid,
"headimg": this.userheadimg,
"toname": this.info.chatName, // 接收人
"touser": this.info.friendId, // 接收人姓名
"content": e.type=='audio'?e.message.voice:e.message,
"time": e.type=='audio'?e.message.time:0,
"ifaudio":false,
"fromtime": new Date(),
"type": e.type
};
if(e.type!=='video'){
this.unshiftmsg.push(data);
rindex=this.unshiftmsg.length-1;
// 跳转到最后一条数据 与前面的:id进行对照
this.screendo(this.unshiftmsg.length - 1);
}
// 发送给服务器消息
var that = this;
if(e.type=='txt'){
// 文本
// 消息发送
this.onSendWS(data,rindex);
}
else if(e.type=='image'){
// 图片
// 先上传在传送消息
var token= uni.getStorageSync("token");
console.log('先上传在传送消息');
uni.showLoading({
title: '图片上传中...'
});
uni.uploadFile({
url: uni.$http.baseUrl+"/api/image/upload",
filePath: e.message,
name: 'file',
header: {
'Authorization': token
},
success: res => {
console.log(res);
uni.hideLoading();
var rdata=JSON.parse(res.data);
if(rdata.data&&rdata.data.originUrl){
var url=rdata.data&&rdata.data.originUrl?rdata.data.originUrl:'';
data.content= url;
// 图片放入集合
if (e.type == 'image'&&url) {
this.imgMsg.push(url);
}
// 消息发送
this.onSendWS(data,rindex);
}
else{
this.$refs.uToast.show({
title:rdata.msg?rdata.msg:"图片上传失败...",
type: "error",
duration: 2000,
});
}
},
fail: res => {
uni.hideLoading();
console.log(res)
}
});
}
else if(e.type=='audio'){
// 音频
// 先上传在传送消息
var token= uni.getStorageSync("token");
console.log('先上传在传送消息');
uni.showLoading({
title: '音频上传中...'
});
uni.uploadFile({
url: uni.$http.baseUrl+"/api/file/upload",
filePath: e.message.voice,
name: 'file',
header: {
'Authorization': token
},
success: res => {
console.log(res);
uni.hideLoading();
var rdata=JSON.parse(res.data);
console.log(rdata);
if(rdata.data&&rdata.data.originUrl){
var url=rdata.data&&rdata.data.originUrl?rdata.data.originUrl:'';
data.content= url;
console.log(data);
// 消息发送
this.onSendWS(data,rindex);
}
else{
this.$refs.uToast.show({
title:rdata.msg?rdata.msg:"音频上传失败...",
type: "error",
duration: 2000,
});
}
},
fail: res => {
uni.hideLoading();
console.log(res)
}
});
}
else if(e.type=='video'){
// 视频
// 先上传在传送消息
var token= uni.getStorageSync("token");
console.log('先上传在传送消息');
uni.showLoading({
title: '视频上传中...'
});
uni.uploadFile({
url: uni.$http.baseUrl+"/api/file/upload",
filePath: e.message,
name: 'file',
header: {
'Authorization': token
},
success: res => {
uni.hideLoading();
console.log(res);
var rdata=JSON.parse(res.data);
console.log(rdata);
if(rdata.data){
var url=rdata.data;
data.content= url;
// 信息发送聊天框
this.unshiftmsg.push(data);
rindex=this.unshiftmsg.length-1;
// 跳转到最后一条数据 与前面的:id进行对照
this.screendo(this.unshiftmsg.length - 1);
// 消息发送
this.onSendWS(data,rindex);
}
else{
this.$refs.uToast.show({
title:rdata.msg?rdata.msg:"视频上传失败...",
type: "error",
duration: 2000,
});
}
},
fail: res => {
uni.hideLoading();
console.log(res)
}
});
}
},
// 消息发送
async onSendWS(datamsg,rindex){
var message=JSON.stringify(datamsg);
var msssagebf=JSON.parse(message);
if(msssagebf.type=='txt'){
msssagebf.content=encodeURIComponent(msssagebf.content);
}
var mtype= '0'; // 消息类型 0:文字 1:图片 2:文件 3:语音 4:视频 5订单 6 商品
if(msssagebf.type=='txt'){
mtype='0';
}
else if(msssagebf.type=='image'){
mtype='1';
}
else if(msssagebf.type=='audio'){
mtype='3';
}
else if(msssagebf.type=='video'){
mtype='4';
}
else if(msssagebf.type=='product'){
// 发送服务
if(this.sendinfo.type==3){
mtype='5';// 5订单 6 商品
}
else{
mtype='6';// 5订单 6 商品
}
}
var param={
"recvId": this.info.friendId,
"content": msssagebf.content,
"type": mtype
}
// 发送消息
const {data: res} = await uni.$http.post('/api/message/private/send',param);
if(res.data){
var rrdata=res.data;
if(rrdata.type==0){
rrdata.content=decodeURIComponent(rrdata.content);
}
this.unshiftmsg[this.unshiftmsg.length-1]["content"]=rrdata.content;
this.unshiftmsg[this.unshiftmsg.length-1]["id"]=rrdata.id;
this.unshiftmsg[this.unshiftmsg.length-1]["recvId"]=rrdata.recvId; // 接收人的id
this.unshiftmsg[this.unshiftmsg.length-1]["sendId"]=rrdata.sendId; // 发送人的id
this.unshiftmsg[this.unshiftmsg.length-1]["fromtime"]=rrdata.sendTime;
this.$forceUpdate();
// 缓存聊天
myCache(this.info.chatId,this.unshiftmsg);
// 更新聊天列表记录
var chatlastinfo={
id:this.info.chatId,
content:rrdata.content,
type:mtype,
minId: rrdata.id,
datetime:rrdata.sendTime,
name: this.info.chatName,
userid: this.userid,
fromuser: this.info.friendId,
img: this.info.chatAvatar,
sort:"privatechat",
send:this.sendinfo
};
this.updateChatList(chatlastinfo);
if(mtype=='5'||mtype=='6'){
// 关闭发送服务窗口
this.ifsend=false;
this.sendinfo=null;
this.$forceUpdate();
}
}
else{
this.unshiftmsg.pop();
uni.showModal({
title: '提示',
content: res.msg?res.msg :'抱歉!信息发送失败..',
cancelText: '取消',
confirmText: '确定',
success: ress => {
}
});
}
},
updateChatList(chatlastinfo){
// 更新聊天列表记录
var chatlist = myCache("chatlist");
if(chatlist&&chatlist.length>0){
var ifexist=0;
chatlist.forEach((cell,i)=>{
if(cell.id==this.info.chatId){
ifexist++;
chatlist[i]=chatlastinfo;
}
});
if(ifexist==0){
// 新增的添加
chatlist.unshift(chatlastinfo);
}
// 重新保存聊天记录
myCache("chatlist",chatlist);
}
else{
chatlist=[];
chatlist.push(chatlastinfo);
myCache("chatlist",chatlist);
}
},
//输入框高度
heights(e) {
this.inputh = e;
this.goBottom();
},
// 滚动到底部
goBottom() {
console.log("goBottom")
this.scrollToView = '';
this.screendo(this.unshiftmsg.length - 1);
},
handleImageError(e,index){
console.log(e,index);
this.unshiftmsg[index]["headimg"]= require("@/static/image/girl.png");
this.$forceUpdate();
},
}
}
</script>
<style lang="scss">
page {
height: 100%;
}
.content {
height: 100%;
background-color: rgba(244, 244, 244, 1);
position: relative;
}
::v-deep .uni-noticebar{
margin-bottom: 0 !important;
padding: 10rpx 12rpx !important;
border-radius: 10rpx;
}
.chat {
height: 100%;
.chat-main {
padding-left: 20rpx;
padding-right: 20rpx;
padding-top: 20rpx;
// padding-bottom: 120rpx; //获取动态高度
display: flex;
flex-direction: column;
}
.chat-ls {
.chat-time {
font-size: 24rpx;
color: rgba(39, 40, 50, 0.3);
line-height: 34rpx;
padding: 10rpx 0rpx;
text-align: center;
}
.msg-m {
display: flex;
padding: 20rpx 0;
.user-img {
flex: none;
width: 92rpx;
height: 90rpx;
border-radius: 20rpx;
text-align: center;
.uimg{
width: 70rpx;
height: 70rpx;
margin: 0 auto;
border-radius: 35rpx;
}
.uname{
height: 30rpx;
display: block;
margin: 0 auto;
line-height: 30rpx;
color: rgba(39, 40, 50, 0.5);
font-size: 24rpx;
}
}
.message {
flex: none;
max-width: 480rpx;
}
.messagevideo {
max-width: 480rpx;
height: 300rpx;
}
.msg-text {
font-size: 32rpx;
color: rgba(39, 40, 50, 1);
line-height: 44rpx;
padding: 18rpx 24rpx;
}
.msg-img {
max-width: 400rpx;
border-radius: 20rpx;
}
.msg-video{
width: 400rpx;
height: 300rpx;
border-radius: 20rpx;
}
.msg-map {
background: #fff;
width: 464rpx;
height: 284rpx;
overflow: hidden;
margin: 0 20rpx;
.map-name {
font-size: 32rpx;
color: rgba(39, 40, 50, 1);
line-height: 44rpx;
padding: 18rpx 24rpx 0 24rpx;
//下面四行是单行文字的样式
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
}
.map-address {
font-size: 24rpx;
color: rgba(39, 40, 50, 0.4);
padding: 0 24rpx;
//下面四行是单行文字的样式
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
}
.map {
padding-top: 8rpx;
width: 464rpx;
height: 190rpx;
}
}
.voice {
// width: 200rpx;
min-width: 100rpx;
max-width: 400rpx;
}
.voice-img {
width: 36rpx;
height: 36rpx;
}
}
.msg-left {
flex-direction: row;
.feed-imgy{
display: flex;
flex-direction: column;
justify-content: center;
align-self: center;
margin-right: 0rpx;
width: 95rpx;
height: 75rpx;
}
.feed-img{
display: flex;
flex-direction: column;
justify-content: center;
align-self: center;
margin-right: 0rpx;
width: 75rpx;
height: 75rpx;
}
.msg-text {
margin-left: 16rpx;
background-color: #fff;
border-radius: 0rpx 20rpx 20rpx 20rpx;
}
.ms-img {
margin-left: 16rpx;
}
.msg-video{
margin-left: 16rpx;
}
.msh-map {
margin-left: 16rpx;
border-radius: 0rpx 20rpx 20rpx 20rpx;
}
.msg-img {
margin: 0 0 0 20rpx;
}
.voice {
text-align: left;
display: flex;
}
.voice-img {
transform: rotate(180deg);
width: 36rpx;
height: 36rpx;
padding-bottom: 4rpx;
margin-right: 10rpx;
}
.voicel{
height: 32rpx;
width: 32rpx;
}
.bg {
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAYCAYAAAAF6fiUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEM0NzgwODc1MDY0MTFFRjk1QjhFRUUxQjYyOUQ5NDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEM0NzgwODg1MDY0MTFFRjk1QjhFRUUxQjYyOUQ5NDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowQzQ3ODA4NTUwNjQxMUVGOTVCOEVFRTFCNjI5RDk0NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowQzQ3ODA4NjUwNjQxMUVGOTVCOEVFRTFCNjI5RDk0NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqxjhsEAAANzSURBVHjazJlLaNRQFIaTVIcRQUELoggVKYIgQvGFr40giLMRBAtjXblwUSmIK1vBTQUREUFB8NGdGwUXgoIVFwq6EGSkOAguXKiUQQq6kKK0Gv+LJ+HkTpLJfYUc+DnJ3M436Tn3eeKHYeiZ2NDQkGfZfCj03Nka6DzUgqZMYa1WS45HzIf15C/xqmeuE7ATOs3up1zxRefslYSgggn465j/GLpJ13ehfS75SEIu36/AFCQ6wQHoBbTgIOBZfBGow9AvaIXBb8d89PYFFpcEn7e5GAG+wXfPQc+g91DNQQKy+A3oB1SnkWDMR9BrbG0oxLeVgNAgCeLhF6FN0CuLiS3CP07+BDTgko/kbHC9BugG6w20ja63QxNSYk0tj/8EatP1uOYuKMFHoCdYW09+kDKnT0Kz0KjGKChik9AsxPkz0FnWvtIgsar8y2wUBDp8BDrBR+zS+CP4PCgyApZDa6Eb+ELDQQJiPs3DkV2FOnQ9atDjVfkPyS+DduvykQQtfpAypM7A3aPbB0iC7bNCgi+dRW6RP2owDanyf0Lv6HqPKl+KTxcf8czlBxnz2gjcPGXtiIOdSRb/Ofmt1KY7DanyZ8gP2uIjMYX4eXPeNPm9jg5Eafwv7IS+rkT+N/Kry+bnJeA3+T5HCUjjhxa3oCr8UOM3rfDzEnCQ/Fu2Q7K5be3i0+IWWadEfj/572Xzg4zywhW4VWwhs128y+LvJ9+mxbEs/mbyn2zxafHtyU87B4yzPe1JgOZZ8x8LwU/waTGL7BT5RwZTkSq/Rge06NCmxJfi08Wn8kQmP20ErKc56xIvpQJUx72NBMR8L1kKbkIb6fq6FKDQIb9BI1v8by91+YiPFj+1GgpYP4I9x+593IcZ05VOEsScOMfuxUuMr/Sg4uHHWNtSjUqlCv81HZDuQ8OqfPFChl7CxHx8NsbiE/Px+XChBKiYhXL0IPUMsYB9lopiddpthI74O9i0sIXVbbT5CPIAi02Cj7a2y2KcrjXp4UXpdpfUtmihIJfHjxbQp5rBL8xPC77NXY2JXaOeOS1t3fooAa74t9loaNrgI8gd1vsL8f0KvpSPdj4u3wuLncxFuj4mbSWVTH4pz3aSMR9/k8mv4jthz3HwD7HgXDAJfkaHTPDzgl+VKahs+wjdgT54/0vUzvhUos61fwIMANiWariLn8/jAAAAAElFTkSuQmCC);
width: 32rpx;
height: 32rpx;
background-size: 400%;
}
.msg-product{
display: flex;
flex-direction: column;
width: 100%;
background-color: #FFFFFF;
padding: 10rpx;
border-radius: 16rpx;
width: 480rpx;
margin-left: 12rpx;
.zx{
display: flex;
justify-content: space-between;
width: 100%;
font-size: 28rpx;
margin: 10rpx;
.zxview{
color: darkgrey;
font-size: 26rpx;
margin-right: 20rpx;
}
}
.msg-con{
display: flex;
justify-content: space-between;
width: 100%;
padding: 10rpx;
border-radius: 16rpx;
}
.img{
width: 120rpx;
height: 120rpx;
}
.info{
display: flex;
flex-direction: column;
flex: 1;
padding: 6rpx 8rpx;
position: relative;
margin-left: 10rpx;
background-color: #f4f4f4;
border-radius: 0 10rpx 10rpx 0;
.name{
width: 330rpx;
// white-space: nowrap; /* 防止文本换行 */
// overflow: hidden; /* 隐藏溢出的内容 */
// text-overflow: ellipsis; /* 溢出部分显示省略号 */
.txt{
font-size: 26rpx;
color: darkgrey;
margin-left: 6rpx;
}
.ntxt{
font-size: 28rpx;
color: #000;
}
}
.sku{
display: flex;
flex-direction: row;
.txt{
font-size: 26rpx;
color: darkgrey;
margin-right: 6rpx;
}
}
.xq{
width: 100%;
display: flex;
flex-direction: row;
.list{
display: flex;
flex: 1;
}
.price{
display: flex;
align-items: center;
font-size: 28rpx;
color: #ff007f;
}
.ord{
display: flex;
align-items: center;
font-size: 26rpx;
color: #232323;
}
.qty{
display: flex;
align-items: center;
font-size: 26rpx;
color: darkgrey;
margin-left: 8rpx;
}
.btn{
font-size: 26rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FCFCFD;
width: 110rpx;
height: 50rpx;
line-height: 50rpx;
background: #ff007f;
box-shadow: 0rpx 10rpx 30rpx 2rpx rgba(255,0,127,0.2);
border-radius: 60rpx;
opacity: 1;
margin-right: 10rpx;
margin-top: 10rpx;
margin-bottom: 10rpx;
padding-left:0 !important;
padding-right:0 !important;
&::after{
border:none;
}
}
}
}
}
}
.msg-right {
flex-direction: row-reverse;
.feed-imgy{
display: flex;
flex-direction: column;
justify-content: center;
align-self: center;
margin-right: 0rpx;
width: 95rpx;
height: 75rpx;
}
.feed-img{
display: flex;
flex-direction: column;
justify-content: center;
align-self: center;
margin-right: 0rpx;
width: 75rpx;
height: 75rpx;
}
.msg-text {
margin-right: 16rpx;
background-color: #00a89b;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
font-size: 32rpx;
color: #FFFFFF;
line-height: 48rpx;
border-radius: 20rpx 0rpx 20rpx 20rpx;
}
.ms-img {
margin-right: 16rpx;
}
.msg-img {
margin: 0 20rpx 0 0;
}
.msg-video{
margin: 0 20rpx 0 0;
}
.msh-map {
margin-left: 16rpx;
border-radius: 20rpx 0rpx 20rpx 20rpx;
}
.voice {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
}
.voice-img {
display: block;
width: 36rpx;
height: 36rpx;
margin-left: 10rpx;
}
.voicel{
height: 32rpx;
width: 32rpx;
}
.bg {
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAYCAYAAAAF6fiUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6REJBQzQ1RjQ1MDYzMTFFRjk5QjZEQkI5MDlENzE3RTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6REJBQzQ1RjU1MDYzMTFFRjk5QjZEQkI5MDlENzE3RTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpEQkFDNDVGMjUwNjMxMUVGOTlCNkRCQjkwOUQ3MTdFNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpEQkFDNDVGMzUwNjMxMUVGOTlCNkRCQjkwOUQ3MTdFNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pm5p+OoAAAKmSURBVHja1Jk/SBxBFMbdy6mHSEARNYIkhU0ICCEkEEynEYmkUEiTxmBtZZHCgGVsAgEhQozYaAo7G0GwjgemC1ZBgzbaKKnEIsb1HbwjH8PM7szdfEQffMzyzexvhn2zM/snSdO0wSOmRfdFc6JfDfGDzb++UUlAjmbTfzHi0T5UbP61Vl6DV3BxZggDYPNRyU1LQDtcnC9GXY/ojeh2HZ2z+ahbZD4lAZt6cQ4Mv1v0W+tm6+icza+qSOZTEvAAZudjo+5Q/SNRX40ds/m47JSIfFoC1nSQ24Y/r/4fUZdR1xHQMZtfVSOZH7LndPgmoEl0oQMdA/8OzNrXxjlzokvRgsfA2HxUM5nvUsmXbzt5CGZJE/jv1d832k8GPsmw+TgDEyLfd8PP5NsAM9q4bPi76r8FrwXgHzwHyOa7loDY/Kw73JtvAyzpCcvgtQLoKfgT6p0GDJDNtyWAwXepEMIvWF6O27Q8Aa8bjo/h+JGWWwEv32y+Ldh8jMsQvi0B1Y9DicUz/b9aNod8/SDzs/pk8V2Ry7cl4FTLTvCORBd63Av+Ny2HAwbF5tuCzXdFLt+WgD0t+8E7F/3Q40Hw17WuRbTqOSg23zbrGXyfyOdbNoYB2LBaLU8vx0b7UWj/0WOTYvNdGzGD76NMvu0OKGvWKjEO/ifY0KbB3xBN6eZ25jEr2HxXxOQnAf1m8x1ZW9SM7Rr+O8hmfx2z4jOZ71IsfoH9LegeDPSFUfcd3mSf1NjxXTI/64UsBj/av4WC47Y5EK3o8VejbkD0U1QUPa9xOTgk812bcSx+GrgM1fRLsvIl8Vxny4albqjOW5HNz+ubyY/2S/IZLBULhAGz+Tf+n7D5Ne8lYRBsPmXzjKWixyq1rOVD0Q7hZYXNz9oP/ntcCTAAHScbp0OSlTgAAAAASUVORK5CYII=);
width: 32rpx;
height: 32rpx;
background-size: 400%;
}
.msg-product{
display: flex;
flex-direction: column;
width: 100%;
background-color: #FFFFFF;
padding: 10rpx;
border-radius: 16rpx;
width: 480rpx;
margin-right: 12rpx;
.zx{
display: flex;
justify-content: space-between;
width: 100%;
font-size: 28rpx;
margin: 10rpx;
.zxview{
color: darkgrey;
font-size: 26rpx;
margin-right: 20rpx;
}
}
.msg-con{
display: flex;
justify-content: space-between;
width: 100%;
padding: 10rpx;
border-radius: 16rpx;
}
.img{
width: 120rpx;
height: 120rpx;
}
.info{
display: flex;
flex-direction: column;
flex: 1;
padding: 6rpx 8rpx;
position: relative;
margin-left: 10rpx;
background-color: #f4f4f4;
border-radius: 0 10rpx 10rpx 0;
.name{
width: 330rpx;
// white-space: nowrap; /* 防止文本换行 */
// overflow: hidden; /* 隐藏溢出的内容 */
// text-overflow: ellipsis; /* 溢出部分显示省略号 */
.txt{
font-size: 26rpx;
color: darkgrey;
margin-left: 6rpx;
}
.ntxt{
font-size: 28rpx;
color: #000;
}
}
.sku{
display: flex;
flex-direction: row;
.txt{
font-size: 26rpx;
color: darkgrey;
margin-right: 6rpx;
}
}
.xq{
width: 100%;
display: flex;
flex-direction: row;
.list{
display: flex;
flex: 1;
}
.price{
display: flex;
align-items: center;
font-size: 28rpx;
color: #ff007f;
}
.ord{
display: flex;
align-items: center;
font-size: 26rpx;
color: #232323;
}
.qty{
display: flex;
align-items: center;
font-size: 26rpx;
color: darkgrey;
margin-left: 8rpx;
}
.btn{
font-size: 26rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FCFCFD;
width: 110rpx;
height: 50rpx;
line-height: 50rpx;
background: #ff007f;
box-shadow: 0rpx 10rpx 30rpx 2rpx rgba(255,0,127,0.2);
border-radius: 60rpx;
opacity: 1;
margin-right: 10rpx;
margin-top: 10rpx;
margin-bottom: 10rpx;
padding-left:0 !important;
padding-right:0 !important;
&::after{
border:none;
}
}
}
}
}
}
}
}
.voicePlay {
animation-name: voicePlay;
animation-duration: 1s;
animation-direction: normal;
animation-iteration-count: infinite;
animation-timing-function: steps(3);
}
@keyframes voicePlay {
0% {
background-position: 0;
}
100% {
background-position: 100%;
}
}
.popup{
position: fixed;
bottom: 180rpx;
/* #ifdef H5 */
bottom: 100rpx;
/* #endif */
left: 0;
width: 100%;
padding: 18rpx;
border-radius: 16rpx;
.tipcon{
display: flex;
justify-content: space-between;
width: 100%;
background-color: #FFFFFF;
padding: 16rpx;
border-radius: 16rpx;
.img{
width: 100rpx;
height: 100rpx;
}
.info{
display: flex;
flex-direction: column;
flex: 1;
margin-left: 16rpx;
position: relative;
.name{
width: 550rpx;
// white-space: nowrap; /* 防止文本换行 */
// overflow: hidden; /* 隐藏溢出的内容 */
// text-overflow: ellipsis; /* 溢出部分显示省略号 */
margin-right: 50rpx;
.txt{
font-size: 26rpx;
color: darkgrey;
margin-left: 6rpx;
}
.ntxt{
font-size: 28rpx;
color: #000;
}
}
.sku{
display: flex;
flex-direction: row;
.txt{
font-size: 26rpx;
color: darkgrey;
margin-right: 6rpx;
}
}
.xq{
width: 100%;
display: flex;
flex-direction: row;
.list{
display: flex;
flex: 1;
align-items: flex-end;
}
.price{
font-size: 28rpx;
color: #ff007f;
}
.ord{
display: flex;
align-items: center;
font-size: 26rpx;
color: #232323;
}
.qty{
font-size: 26rpx;
color: darkgrey;
margin-left: 6rpx;
}
.btn{
font-size: 26rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FCFCFD;
width: 150rpx;
height: 50rpx;
line-height: 50rpx;
background: #ff007f;
box-shadow: 0rpx 10rpx 30rpx 2rpx rgba(255,0,127,0.2);
border-radius: 10rpx;
opacity: 1;
margin-right: 10rpx;
padding-left:0 !important;
padding-right:0 !important;
&::after{
border:none;
}
}
}
.close{
position: absolute;
top: 0;
right: 6rpx;
}
}
}
}
</style>