Files
ZhHealth/pages/im/chat.nvue
2022-01-12 16:50:50 +08:00

1209 lines
31 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="detail-main" :style="{height: mainHeight + 'px'}">
<view class="custom-nav">
<view class="bar-box" :style="'height: ' + (heightNum + 'px')"></view>
<view class="head-box">
<view class="flex-1 back-box" @click="goBack">
<image class="back-icon" src="../../static/icon/back.png"></image>
</view>
<view class="flex-1 flex-2 nav-title">
<text>{{currentInfo.userName}}</text>
</view>
<view class="flex-1 btn-text"></view>
</view>
</view>
<view class="message-box">
<list class="scroll-view_H" scroll-y="true" :scroll-top="scrollTop"
:style="{height: scrollHeight + 'px'}" @scroll="scrollWatch">
<refresh v-if="hasMore" @refresh="onrefresh" class="refresh-box" @pullingdown="onpullingdown"
:display="refreshing ? 'show' : 'hide'">
<text class="loading-text">加载中...</text>
<loading-indicator class="loading-style"></loading-indicator>
</refresh>
<cell v-for="(item, index) in list" :key="item.id" :id="'into' + index">
<view class="left-bg" v-if="item.messageDirection === 2">
<view class="message-left flex">
<image class="head-img" :src="currentInfo.userPortrait"></image>
<view>
<text v-if="!item.content.imageUri && !item.content.latitude && !item.content.remoteUrl"
class="left-info">{{item.content.content || ''}}</text>
<image style="width: 300upx;margin-left: 10upx;border-radius: 10upx"
v-if="item.content.imageUri" :src="item.content.imageUri"
@click="previewImg(item.content.imageUri)" mode="aspectFill"></image>
<view v-if="item.content.latitude" class="map-box" style="margin-left: 10upx">
<text class="map-text">{{item.content.poi}}</text>
<map class="map-style" :latitude="item.content.latitude"
:longitude="item.content.longitude" :markers="handleCovers(item)"></map>
<cover-view class="map-cover" @click="gotoLocationDetail(item)"></cover-view>
</view>
<view class="chat-box-right" style="background-color: #FFFFFF" v-if="item.content.remoteUrl && index !== chatStatus"
@click="openChat(item.content.remoteUrl, index)">
<image class="gif-icon" src="../../static/icon/msg.png"></image>
<text class="chat-text">{{handleDuration(item.content.duration)}}</text>
</view>
<view class="chat-box-right" style="background-color: #FFFFFF" v-if="item.content.remoteUrl && index === chatStatus"
@click="closeChat(item.content.remoteUrl, index)">
<image class="gif-icon" src="../../static/icon/msg-yellow.png"></image>
<text class="chat-text"
style="color: #FFD100;">{{handleDuration(item.content.duration)}}</text>
</view>
</view>
</view>
</view>
<view class="time-box" v-if="item.receivedTimeVal">
<text class="time-box-text">{{item.receivedTimeVal}}</text>
</view>
<view class="right-bg" v-if="item.messageDirection === 1">
<view class="message-right flex">
<view>
<view v-if="item.content.latitude" class="map-box" style="margin-right: 10upx">
<text class="map-text">{{item.content.poi}}</text>
<map class="map-style" :latitude="item.content.latitude"
:longitude="item.content.longitude" :markers="handleCovers(item)"></map>
<cover-view class="map-cover" @click="gotoLocationDetail(item)"></cover-view>
</view>
<text v-if="!item.content.imageUri && !item.content.latitude && !item.content.remoteUrl"
class="right-info">{{item.content.content || ''}}</text>
<view class="chat-box-right" v-if="item.content.remoteUrl && index !== chatStatus"
@click="openChat(item.content.remoteUrl, index)">
<image class="gif-icon" src="../../static/icon/msg.png"></image>
<text class="chat-text">{{handleDuration(item.content.duration)}}</text>
</view>
<view class="chat-box-right" v-if="item.content.remoteUrl && index === chatStatus"
@click="closeChat(item.content.remoteUrl, index)">
<image class="gif-icon" src="../../static/icon/msg-white.png"></image>
<text class="chat-text"
style="color: #FFFFFF;">{{handleDuration(item.content.duration)}}</text>
</view>
<image style="width: 300upx;margin-right: 10upx;border-radius: 10upx"
v-if="item.content.imageUri" :src="item.content.imageUri"
@click="previewImg(item.content.imageUri)" mode="aspectFill"></image>
</view>
<image class="head-img" :src="userInfo.headimg"></image>
</view>
</view>
</cell>
</list>
</view>
<view class="space-box"></view>
<view class="footer-bg">
<view class="footer-content">
<view class="input-box">
<image v-if="!isTalk" @click="openTalk"
style="width: 48upx;height: 48upx;margin-right: 20upx;margin-bottom: 10upx;"
src="../../static/message/talk-icon.png" mode=""></image>
<image v-if="isTalk" @click="isTalk = false"
style="width: 48upx;height: 48upx;margin-right: 20upx;margin-bottom: 10upx;"
src="../../static/message/keybord-icon.png" mode=""></image>
<view>
<view v-if="!isTalk" class="input-bg"><textarea cursor-spacing="30" class="input-style"
type="text" v-model="txtMsgVal" @input="handleInput" auto-height auto-blur /></view>
<text @touchstart="talkStart" @touchmove="talkMoveHandle" @touchend="talkEnd" v-if="isTalk"
class="long-btn">按住 说话</text>
</view>
<image @click="emojiHandle"
style="width: 48upx;height: 48upx;margin-right: 20upx;margin-bottom: 10upx;"
src="../../static/message/face-icon.png" mode=""></image>
<image v-if="!isSend" @click="showPlusHandle"
style="width: 48upx;height: 48upx;margin-bottom: 10upx;" src="../../static/message/add-icon.png"
mode=""></image>
<text @click="sendTxtMsg" style="margin-bottom: 5upx;" v-if="isSend" class="send-btn">发送</text>
</view>
<scroll-view v-if="isEmoji" class="emoji-box" scroll-y="true">
<view class="emoji-bg">
<text class="emoji-item" v-for="(item, index) in emojiList" :key="index"
@click="selectEmoji(item)">{{item.emoji}}</text>
</view>
</scroll-view>
<view class="plus-box" v-if="showPlus">
<view class="plus-item" @click="uploadPic">
<view class="plus-bg">
<image style="width: 48upx;height: 48upx;" src="../../static/message/photo-icon.png"
mode=""></image>
</view>
<text class="plus-text">照片</text>
</view>
<view class="plus-item" @click="chooseLocation">
<view class="plus-bg">
<image style="width: 48upx;height: 48upx;" src="../../static/message/address-icon.png"
mode=""></image>
</view>
<text class="plus-text">位置</text>
</view>
</view>
</view>
<view class="ios-bottom" v-if="isIphoneX"></view>
</view>
<view class="modal-box" :style="{height: mainHeight + 'px'}" v-if="showTip">
<view class="alert-content">
<text class="tip-text">{{tipContent}}</text>
<view class="close-btn" @click="showTip = false"><text class="close-btn-text">确定</text></view>
</view>
</view>
<view class="chat-record-box" :style="{height: mainHeight + 'px'}" @touchmove.stop="" v-if="showChatBg">
<view class="record-content">
<image style="width: 180upx;height: 180upx" src="../../static/icon/record-icon.png" mode=""></image>
<view class="record-btn-box" :style="{marginBottom: isIphoneX ? '68upx' : 0}">
<text class="record-tip">松开发送,上滑取消</text>
<text v-if="!isCancle" class="record-cancle">取消</text>
<text v-if="isCancle" class="record-cancle-red">取消</text>
<view class="record-btn">
<image class="record-btn-icon" src="../../static/icon/msg.png" mode=""></image>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* 配置好api就可以了
* 其他配置文件都有了
* nvue样式都是独立的
* 第三方用的是 融云 IM初始化在App.vue
*/
let recorderManager = uni.getRecorderManager();
let innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
import api from '@/public/im' // api路径
import emojiList from '../../utils/emojiData.js'
import * as RongIMLib from '@rongcloud/imlib-uni'
import util from '../../utils/index.js'
const dom = weex.requireModule('dom')
export default {
data() {
return {
emojiList: emojiList,
list: [],
isTalk: false,
showChatBg: false,
showPlus: false,
heightNum: 0,
titleTxt: '',
btnText: '',
showTip: false,
isIphoneX: false,
voicePath: '',
uploadInfo: {},
targetId: '',
chatUserId: '',
txtMsgVal: '',
isSend: false,
currentInfo: {},
userInfo: {},
isEmoji: false,
imgList: [],
scrollTop: 100,
scrollHeight: 0,
mainHeight: 0,
chatStatus: '',
innerAudioContext: '',
scrollTopNow: 0,
isCancle: false,
refreshing: false,
listParams: {
timestamp: 0,
count: 15
},
hasMore: true,
}
},
onLoad(options) {
uni.getSystemInfo({
success: (res) => {
this.mainHeight = res.windowHeight;
let height = res.windowHeight - res.statusBarHeight - 88
if (res.platform === 'ios') {
height = height - 34;
}
this.scrollHeight = height;
}
});
this.userInfo = JSON.parse(uni.getStorageSync('userInfo'));
this.targetId = options.targetId;
this.chatUserId = options.chatUserId;
let self = this;
recorderManager.onStop(function(res) {
if (self.isCancle) {
self.isCancle = false;
return false
}
const tempFilePaths = res.tempFilePath;
let temp = Date.parse(new Date());
let info = JSON.parse(JSON.stringify(self.uploadInfo));
info.key = info.dir + '/' + temp + '.mp3';
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
innerAudioContext.volume = 0;
innerAudioContext.src = tempFilePaths;
innerAudioContext.onPlay(() => {
if (innerAudioContext.duration < 1) {
uni.showToast({
title: '时间太短了!',
icon: 'none'
})
innerAudioContext.stop();
return false;
}
uni.showLoading({
title: '正在发送...'
})
uni.uploadFile({
url: info.host, //仅为示例,非真实的接口地址
filePath: tempFilePaths,
name: 'file',
formData: info,
success: (uploadFileRes) => {
uni.hideLoading()
const url = info.host + '/' + info.key;
self.sendChatMsg(url, innerAudioContext.duration);
}
});
innerAudioContext.stop();
});
});
this.heightNum = uni.getSystemInfoSync().statusBarHeight;
wx.getSystemInfo({
success: res => {
if (res.safeArea.top > 44) { //x及以上的异形屏top为44非异形屏为20
this.isIphoneX = true;
}
}
})
this.getInfo();
this.getOss();
this.getMsgListInit();
this.watchMsg();
},
onHide() {
this.showPlus = false;
},
methods: {
dataTimeHandle() {
let timestamp = 0;
// 判断是否在2分钟内
this.list.forEach((item, index) => {
if (item.sentTime - timestamp > 120000) {
timestamp = item.sentTime;
this.$set(this.list[index], 'receivedTimeVal', util.handleTimeCustom(timestamp))
}
})
},
onrefresh() {
this.getMsgList();
},
onpullingdown() {
this.scrollOldHeight = this.scrollTopNow;
// console.log(this.scrollOldHeight, '最后的距离')
},
scrollWatch(e) {
// console.log(e.contentSize.height, '------滑动监听-----')
// console.log(e.detail.scrollHeight, '-----滑动总距离-------')
// console.log(e.detail.scrollTop, '-----滑动中距离-------')
this.scrollTopNow = e.contentSize.height;
},
scrollHandle() {
this.showPlus = false;
this.isEmoji = false;
this.scrollTop = this.scrollTopNow;
setTimeout(() => {
this.scrollTop = this.scrollTopNow + 1000;
}, 0)
},
updateImgList() {
this.imgList = [];
this.list.forEach((item, index) => {
if (item.content.imageUri) {
this.imgList.push(item.content.imageUri)
}
})
},
clearRead() {
const im = getApp().globalData.im;
var conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
conversation.read().then(function() {
console.log('清除未读数成功'); // im.watch conversation 将被触发
});
},
watchMsg() {
const im = getApp().globalData.im;
var conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
let that = this;
// 添加事件监听
im.watch({
// 监听会话列表变更事件, 触发时机:会话状态变化(置顶、免打扰)、会话未读数变化(未读数增加、未读数清空)、会话 @ 信息、会话最后一条消息变化
conversation(event) {
// 假定存在 getExistedConversationList 方法,以获取当前已存在的会话列表数据
const conversationList = getExistedConversationList()
// 发生变更的会话列表
const updatedConversationList = event.updatedConversationList;
// 通过 im.Conversation.merge 计算最新的会话列表
const latestConversationList = im.Conversation.merge({
conversationList,
updatedConversationList
})
},
// 监听消息通知
message(event) {
// 新接收到的消息内容
const message = event.message;
that.list.push(message);
that.scrollHandle();
that.updateImgList();
that.clearRead();
},
// 监听 IM 连接状态变化
status(event) {
console.log('connection status:', event.status);
},
// 监听聊天室 KV 数据变更
chatroom(event) {
/**
* 聊天室 KV 存储数据更新
* @example
* [
* {
* "key": "name",
* "value": "我是小融融",
* "timestamp": 1597591258338,
* "chatroomId": "z002",
* "type": 1 // 1: 更新( 含:修改和新增 、2: 删除
* },
* ]
*/
const updatedEntries = event.updatedEntries
},
expansion(event) {
/**
* 更新的消息拓展数据
* @example {
* expansion: { key: 'value' }, // 设置或更新的扩展值
* messageUId: 'URIT-URIT-ODMF-DURR' // 设置或更新扩展的消息 uid
* }
*/
const updatedExpansion = event.updatedExpansion;
/**
* 删除的消息拓展数据
* @example {
* deletedKeys: ['key1', 'key2'], // 设置或更新的扩展值
* messageUId: 'URIT-URIT-ODMF-DURR' // 设置或更新扩展的消息 uid
* }
*/
const deletedExpansion = event.deletedExpansion;
},
// 监听离线消息拉取完成
pullFinished() {
console.log('拉取离线消息完成')
that.scrollHandle();
}
});
},
handleDuration(duration) {
return duration.toFixed(0) + '秒'
},
openChat(url, index) {
this.chatStatus = index;
this.innerAudioContext = uni.createInnerAudioContext();
this.innerAudioContext.autoplay = true;
this.innerAudioContext.volume = 1;
this.innerAudioContext.src = url;
this.innerAudioContext.seek = 3;
this.innerAudioContext.onSeeking(() => {
uni.showLoading({
title: '加载中...'
})
})
this.innerAudioContext.onWaiting(() => {
uni.showLoading({
title: '加载中...'
})
})
this.innerAudioContext.onPlay(() => {
console.log('开始播放');
uni.hideLoading();
});
this.innerAudioContext.onEnded(() => {
this.chatStatus = '';
})
},
closeChat(url) {
this.chatStatus = '';
this.innerAudioContext.stop();
},
gotoLocationDetail(info) {
uni.openLocation({
latitude: info.content.latitude,
longitude: info.content.longitude,
success: function() {
console.log('success');
}
});
},
handleCovers(info) {
return [{
id: 1,
latitude: info.content.latitude,
longitude: info.content.longitude,
iconPath: '/static/icon/location-icon.png',
width: 25,
height: 25
}]
},
chooseLocation() {
uni.chooseLocation({
success: (res) => {
const im = getApp().globalData.im;
let conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
let latitude = res.latitude;
let longitude = res.longitude;
let poi = res.name;
let content = ''; // 位置图片 base64
conversation.send({
messageType: RongIMLib.MESSAGE_TYPE.LOCATION, // 'RC:LBSMsg'
content: {
latitude: latitude,
longitude: longitude,
poi: poi,
content: content
}
}).then((message) => {
console.log('发送位置消息成功', message);
this.showPlus = false;
this.list.push(message);
this.scrollHandle();
});
}
});
},
previewImg(url) {
uni.previewImage({
urls: this.imgList,
current: url
});
},
emojiHandle() {
this.showPlus = false;
this.isEmoji = !this.isEmoji;
this.isTalk = false;
uni.hideKeyboard();
},
selectEmoji(info) {
this.txtMsgVal += info.emoji;
this.isSend = true;
},
getInfo() {
util.getImUserInfo(this.targetId).then(res => {
this.currentInfo = res;
})
},
getMsgList() {
uni.hideKeyboard()
const im = getApp().globalData.im;
let conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
this.refreshing = true;
conversation.getMessages(this.listParams).then(result => {
this.refreshing = false;
if (this.listParams.timestamp === 0) {
this.list = result.list;
} else {
this.list = result.list.concat(this.list);
}
if (result.hasMore) {
this.listParams.timestamp = this.list[0].sentTime;
this.hasMore = true;
} else {
this.hasMore = false;
}
this.dataTimeHandle();
this.updateImgList();
// 调整滑动位置
this.showPlus = false;
this.isEmoji = false;
// this.scrollTop = 200;
setTimeout(() => {
// this.scrollTop = this.scrollTopNow - this.scrollHeight;
console.log(this.scrollTop, '--------调整位置--------')
}, 100)
});
},
getMsgListInit() {
const im = getApp().globalData.im;
let conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
conversation.getMessages(this.listParams).then(result => {
this.list = result.list;
if (result.hasMore) {
this.listParams.timestamp = this.list[0].sentTime;
this.hasMore = true;
} else {
this.hasMore = false;
}
this.dataTimeHandle();
this.updateImgList();
this.clearRead();
this.scrollTop = 1000;
setTimeout(() => {
this.scrollTop = this.scrollTopNow + 1000;
}, 100)
});
},
handleInput(val) {
if (this.txtMsgVal) {
this.isSend = true;
} else {
this.isSend = false;
}
},
uploadPic() {
uni.chooseImage({
sizeType: 'compressed',
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
uni.showLoading({
title: '加载中...'
})
tempFilePaths.forEach((item, index) => {
let info = JSON.parse(JSON.stringify(this.uploadInfo));
let temp = Date.parse(new Date()) + index;
info.key = info.dir + '/' + temp + '.png';
uni.uploadFile({
url: this.uploadInfo.host, //仅为示例,非真实的接口地址
filePath: tempFilePaths[index],
name: 'file',
formData: info,
success: (uploadFileRes) => {
const url = info.host + '/' + info.key;
this.sendPhotoMsg(url);
if (index === tempFilePaths.length - 1) {
uni.hideLoading();
}
}
});
})
}
});
},
sendPhotoMsg(url) {
this.showPlus = false;
const im = getApp().globalData.im;
var conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
uni.showLoading()
conversation.send({
messageType: RongIMLib.MESSAGE_TYPE.IMAGE, // 'RC:ImgMsg'
content: {
content: '', // // 压缩后的 base64 略缩图, 用来快速展示图片
imageUri: url // 上传到服务器的 url. 用来展示高清图片
}
}).then(message => {
uni.hideLoading()
console.log('发送图片消息成功', message);
this.list.push(message);
this.updateImgList();
this.scrollHandle();
});
},
sendTxtMsg() {
if (!this.txtMsgVal) {
return false;
}
const im = getApp().globalData.im;
const conversation = im.Conversation.get({
// targetId
targetId: this.targetId,
// 会话类型RongIMLib.CONVERSATION_TYPE.PRIVATE | RongIMLib.CONVERSATION_TYPE.GROUP
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
uni.showLoading()
// 向会话内发消息
conversation.send({
// 消息类型,其中 RongIMLib.MESSAGE_TYPE 为 IMLib 内部的内置消息类型常量定义
messageType: RongIMLib.MESSAGE_TYPE.TEXT, // 'RC:TxtMsg'
// 消息内容
content: {
content: this.txtMsgVal // 文本内容
}
}).then(message => {
uni.hideLoading()
this.txtMsgVal = ''
this.showPlus = false;
this.isEmoji = false;
this.isSend = false;
console.log('发送文字消息成功', message);
this.list.push(message);
this.scrollHandle();
}).catch(error => {
console.log('发送文字消息失败', error.code, error.msg);
});
},
sendChatMsg(url, duration) {
const im = getApp().globalData.im;
var conversation = im.Conversation.get({
targetId: this.targetId,
type: RongIMLib.CONVERSATION_TYPE.PRIVATE
});
uni.showLoading()
conversation.send({
messageType: RongIMLib.MESSAGE_TYPE.HQ_VOICE, // 'RC:HQVCMsg'
content: {
remoteUrl: url, // 音频 url, 建议格式: aac
duration: duration, // 音频时长
type: 'mp3'
}
}).then((message) => {
uni.hideLoading()
console.log('发送语音消息成功', message);
this.list.push(message);
this.scrollHandle();
});
},
getOss() {
api.getOss().then(res => {
this.uploadInfo = res.datas;
})
},
openTalk() {
this.isTalk = true;
this.isEmoji = false;
uni.hideKeyboard()
},
talkStart() {
recorderManager.start({
duration: 60000
});
this.showChatBg = true;
uni.vibrateShort({
success: function() {
}
});
},
talkEnd() {
recorderManager.stop();
this.showChatBg = false;
},
talkMoveHandle(e) {
const num = e.changedTouches[0].pageY;
if (num < -30 && num > -100) {
this.isCancle = true;
} else {
this.isCancle = false;
}
},
playVoice() {
if (this.voicePath) {
innerAudioContext.src = this.voicePath;
innerAudioContext.play();
}
},
showPlusHandle() {
this.isEmoji = false;
this.showPlus = !this.showPlus;
uni.hideKeyboard();
},
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.time-box {
align-items: center;
margin-bottom: 20upx;
}
.time-box-text {
font-size: 24upx;
}
.refresh-box {
flex-direction: row;
align-items: center;
justify-content: center;
}
.loading-text {
font-size: 24upx;
color: #FFD100;
text-align: center;
padding: 30upx;
}
.loading-style {
color: yellow;
}
.record-content {
position: absolute;
bottom: 0;
height: 700upx;
width: 750upx;
align-items: center;
justify-content: space-between;
}
.record-btn-box {
align-items: center;
justify-content: space-between;
}
.record-btn {
width: 700upx;
height: 120upx;
background-color: #C0C0C0;
justify-content: center;
align-items: center;
border-radius: 60upx;
}
.record-btn-icon {
width: 40upx;
height: 40upx;
}
.record-cancle,
.record-cancle-red {
background-color: #333333;
width: 700upx;
height: 100upx;
color: #C0C0C0;
align-items: center;
justify-content: center;
font-size: 30upx;
text-align: center;
line-height: 100upx;
margin-bottom: 30upx;
border-radius: 50upx;
}
.record-cancle-red {
background-color: #F03;
color: #FFFFFF;
}
.record-tip {
text-align: center;
color: #C0C0C0;
font-size: 28upx;
margin-bottom: 30upx;
}
.chat-record-box {
position: fixed;
top: 0;
left: 0;
width: 750upx;
background-color: rgba($color: #000000, $alpha: .7);
z-index: 10
}
.map-box {
width: 400upx;
height: 300upx;
background-color: #FFFFFF;
border-radius: 10upx;
}
.map-cover {
position: absolute;
bottom: 0;
left: 0;
width: 400upx;
height: 300upx;
background-color: rgba($color: #000000, $alpha: 0);
}
.chat-box-left {
flex-direction: row;
align-items: center;
justify-content: center;
width: 200upx;
flex-wrap: wrap;
padding: 16upx 24upx;
background-color: #FFFFFF;
border-radius: 20upx;
margin-left: 14upx;
font-size: 28upx;
font-weight: 400;
color: #1A1A1A;
line-height: 40upx;
}
.chat-box-right {
flex-direction: row;
align-items: center;
justify-content: center;
width: 200upx;
flex-wrap: wrap;
padding: 16upx 24upx;
background-color: #FFD100;
border-radius: 20upx;
margin-left: 14upx;
font-size: 28upx;
font-weight: 400;
color: #1A1A1A;
line-height: 40upx;
margin-right: 10upx;
}
.chat-text {
font-size: 26upx;
}
.gif-icon {
width: 30upx;
height: 30upx;
margin-right: 10upx;
}
.map-text {
font-size: 24upx;
padding: 12upx 10upx;
}
.bar-box {
background-color: #FFFFFF;
}
.modal-box {
position: fixed;
width: 750upx;
background-color: rgba($color: #000000, $alpha: .4);
align-items: center;
justify-content: center;
}
.alert-content {
width: 640upx;
height: 480upx;
background-color: #FFFFFF;
border-radius: 24upx;
padding: 64upx 48upx;
}
.close-btn {
width: 512upx;
height: 80upx;
background: #FFD100;
border-radius: 12upx;
align-items: center;
justify-content: center;
}
.close-btn-text {
color: #1A1A1A;
font-size: 30upx;
}
.tip-text {
font-size: 34upx;
line-height: 48upx;
margin-bottom: 52upx;
font-weight: 500;
}
.space-box {
height: 88upx;
}
.emoji-bg {
flex-direction: row;
flex-wrap: wrap;
}
.emoji-box {
height: 400upx;
width: 750upx;
flex-direction: row;
padding-left: 20upx;
padding-top: 20upx;
}
.emoji-item {
margin-right: 20upx;
margin-bottom: 20upx;
}
.send-btn {
padding: 0 20upx;
height: 60upx;
color: #FFFFFF;
background-color: #FFD100;
font-size: 26upx;
border-radius: 6upx;
text-align: center;
line-height: 60upx;
}
.talk-box {
position: fixed;
top: 0;
left: 0;
width: 750upx;
height: 100vh;
background-color: rgba($color: #000000, $alpha: .7);
}
.plus-box {
height: 434upx;
flex-direction: row;
padding: 60upx 30upx;
}
.plus-bg {
justify-content: center;
align-items: center;
width: 116upx;
height: 116upx;
background: #FFFFFF;
border-radius: 20upx;
margin-bottom: 6upx;
}
.plus-text {
text-align: center;
font-size: 22upx;
color: #999999;
line-height: 32upx;
}
.plus-item {
margin-right: 76upx;
}
.input-style,
.long-btn {
background-color: #FFFFFF;
width: 500upx;
padding: 10upx;
border-radius: 8upx;
margin-right: 20upx;
height: 72upx;
font-size: 28upx;
line-height: 36upx;
}
.input-bg {
flex-direction: row;
align-items: center;
justify-content: center;
padding:10upx;
background-color: #FFFFFF;
border-radius: 8upx;
width: 500upx;
margin-right: 20upx;
}
.input-style {
padding: 0;
width: 480upx;
margin-right: 0;
padding-top: 6upx;
}
.long-btn {
text-align: center;
line-height: 72upx;
padding: 0;
color: #1A1A1A;
}
.input-box {
flex-direction: row;
align-items: flex-end;
padding: 8upx 20upx;
}
.emoji-box {
width: 750upx;
flex-direction: column;
}
.detail-main {
justify-content: space-between;
background-color: #F7F7F7;
}
.footer-bg {
background-color: #F0F0F0;
width: 750upx;
position: fixed;
bottom: 0;
left: 0;
}
.ios-bottom {
height: 68upx;
background-color: #F7F7F7;
}
.message-box {}
.left-bg {
padding-left: 30upx;
width: 750upx;
flex-direction: row;
justify-content: flex-start;
margin-top: 20upx;
}
.right-bg {
padding-right: 30upx;
width: 750upx;
flex-direction: row;
justify-content: flex-end;
}
.message-left,
.message-right {
width: 500upx;
flex-direction: row;
margin-bottom: 40upx;
}
.head-img {
width: 72upx;
height: 72upx;
border-radius: 72upx;
background-color: #C0C0C0;
}
.message-right {
justify-content: flex-end;
}
.left-info {
width: 400upx;
flex-wrap: wrap;
padding: 16upx 24upx;
background-color: #FFFFFF;
border-radius: 20upx;
margin-left: 14upx;
font-size: 28upx;
font-weight: 400;
color: #1A1A1A;
line-height: 40upx;
}
.right-info {
width: 400upx;
padding: 16upx 24upx;
background-color: #FFD100;
border-radius: 20upx;
margin-right: 14upx;
font-size: 28upx;
font-weight: 400;
color: #1A1A1A;
line-height: 40upx;
}
.custom-nav {
width: 750upx;
}
.back-icon {
width: 18upx;
height: 36upx;
}
.head-box {
height: 88upx;
background-color: #FFFFFF;
font-size: 36upx;
line-height: 50upx;
flex-direction: row;
justify-content: space-between;
align-items: center;
color: #000000;
padding: 0 32upx;
font-weight: 600;
}
.message-icon {
width: 42upx;
height: 40upx;
}
.flex-1 {
flex-direction: row;
flex: 1;
text-align: center;
color: #333333;
font-size: 33upx;
font-weight: 500;
}
.flex-2 {
flex: 2;
align-items: center;
justify-content: center;
}
.message-box {
align-items: center;
justify-content: flex-end;
position: relative;
}
.red-dot {
position: absolute;
top: 0;
right: 0;
margin-top: -6upx;
margin-right: -6upx;
width: 12upx;
height: 12upx;
background: #E60012;
border-radius: 50%;
}
.back-box {
align-items: center;
justify-content: flex-start;
}
.left-icon {
width: 18upx;
height: 34upx;
}
.btn-text {
flex-direction: row;
justify-content: flex-end;
font-size: 24upx;
font-weight: 400;
color: #1A1A1A;
line-height: 34upx;
text-align: right;
}
.nav-title {
font-size: 32upx;
font-weight: bold;
color: #030303;
}
</style>