Files
im-system/im-uniapp/wx/chatWindow/index.vue
2023-11-16 10:52:39 +08:00

1100 lines
27 KiB
Vue
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>
<watermark></watermark>
<uni-popup ref="popup" type="center">
<view class="popsendCard" :style="'height:' + windowHeight + 'px'">
<sendCard @click="sendCardclick"></sendCard>
</view>
</uni-popup>
<uni-popup ref="popupfavorites" type="center" background-color="#fff" style="background-color: #fff;">
<scroll-view scroll-y :style="'height:' + windowHeight + 'px'">
<favorites type="2" @clickitem="clickitem"></favorites>
</scroll-view>
</uni-popup>
<view class="zfb-tk-main">
<uni-list class="zfb-tk-conent" :border="false" style="background: none;">
<chatItem v-for="(v, index) in chatWindowData" :key="'key' + index" :talkTo="talkTo" :itemKey="index"
:item="v" @tryagin="tryagin" @longpressItem="longpressItem" :longTapItemKey="longTapItemKey">
</chatItem>
</uni-list>
<view class="autodownView"></view>
</view>
<view :style="'height: ' + keyboardHeight + 'px'"></view>
<view v-if="showtool || showEmojitool" :style="'height:558rpx'"></view>
<view class="zfb-tk-send-tool" :style="'transform: translateY(-' + keyboardHeight + 'px)'">
<view class="zfb-tk-send-tool-c">
<view class="zfb-tk-send-tool-icon wxfont" @click="changeShowVice"
:class="showVice ? 'jianpan' : 'yuyin2'"></view>
<view class="zfb-tk-send-tool-vioce" v-if="showVice">
<view class="zfb-tk-send-tool-vioce-item" @longpress="startRecord" @touchend="endRecord">按住说话</view>
</view>
<view v-else class="zfb-tk-send-tool-input-box" @click="msgFocus = true"><textarea
@focus="showtool = false" :focus="msgFocus" class="zfb-tk-send-tool-input"
:adjust-position="false" v-model="msg" placeholder="" hold-keyboard confirm-type="send"
@confirm="sendMsg(msg, 'TEXT')" :maxlength="-1" auto-height /></view>
<view @click="changeEmojiTool" class="zfb-tk-send-tool-more wxfont biaoqing"></view>
<view v-if="msg !== ''" class="zfb-tk-send-tool-text" @touchend.prevent="sendMsg(msg, 'TEXT')"
:style="{ background: msg !== '' ? '#1BC418' : '#F7F7F7', color: msg !== '' ? '#fff' : '#ddd', 'border-color': msg !== '' ? '#1BC418' : '#ddd' }">
发送</view>
<view v-else @click="changeTool" class="zfb-tk-send-tool-more wxfont gengduo"></view>
</view>
<view v-if="showtool" class="zfb-tk-send-tools">
<template v-for="(v, i) in toolist">
<view class="zfb-tk-send-tools-item" @click="toolClick(v)" v-if="v.show">
<view class="zfb-tk-send-tools-icon">
<view class="wxfont" :class="v.icon"></view>
</view>
<view class="zfb-tk-send-tools-text">{{ v.title }}</view>
</view>
</template>
</view>
<scroll-view :scroll-y="true" v-if="showEmojitool" class="wxemojitool">
<view class="wxemojitool-content">
<view class="wxemojitool-item" @click="addMsg(v)" v-for="(v, i) in emojilist" :key="i">{{ v }}
</view>
</view>
</scroll-view>
</view>
<zmm-upload-image chooseType="chooseMedia" :show="false" ref="upload" @allComplete="upLoadallComplete"
@oneComplete="upLoadoneComplete"></zmm-upload-image>
<!-- #ifndef H5 -->
<view class="zfb-tk-recorder" v-show="showRecorder">
<zmm-recorder :show="showRecorder" ref="rec" @recorderStop="recorderStop"></zmm-recorder>
</view>
<!-- #endif -->
</view>
</template>
<script>
// #ifdef APP-PLUS
const TUICalling = uni.requireNativePlugin('TUICallingUniPlugin-TUICallingModule');
// #endif
let observer = null;
import favorites from '../favorites/index.vue';
import chatItem from './chat-item.vue';
import sendCard from './sendCard.vue';
import config from "@/common/config.js"
import customHttp from "@/common/customHttp.js"
export default {
components: {
chatItem,
sendCard,
favorites
},
data() {
return {
isBottomHeight: '',
clickToSubmitSure: null,
autodown: true,
emojilist: ['😁', '😂', '😃', '😄', '😅', '😆', '😉', '😊', '😋', '😌', '😍', '😏', '😒', '😓', '😔', '😖',
'😘', '😚', '😜', '😝', '😞', '😠', '😡', '😢', '😣', '😤', '😥', '😨', '😩', '😪', '😫', '😭',
'😰', '😱', '😲', '😳', '😵', '😷', '😸', '😹', '😺', '😻', '😼', '😽', '😾', '😿', '🙀', '🙅',
'🙆', '🙇', '🙈', '🙉', '🙊', '🙋', '🙌', '🙍', '🙎', '🙏'
],
showRecorder: false,
showVice: false,
toolist: [{
title: '相册',
icon: 'tupian',
show: true
},
{
title: '拍摄',
icon: 'xiangji',
show: false
},
{
title: '位置',
icon: 'dingwei',
show: false
},
{
title: '语音',
icon: 'yrecord',
show: false
},
{
title: '名片',
icon: 'mingpian',
show: false
},
{
title: '收藏',
icon: 'shoucang',
show: false
}
],
msgFocus: false,
showtool: false,
showEmojitool: false,
msg: '',
timer: '',
talkTo: '',
keyboardHeight: 0,
windowHeight: 0,
longTapItemKey: '',
// chatWindowData:[],
localData: {},
showtitleNViewBtns: true,
list: []
};
},
computed: {
userinfo() {
return this.$store.state.userInfo;
},
chatListInfo() {
return this.$store.state.chatlist[this.talkTo.userId];
},
chatDataState() {
return this.$store.state.chatDataState;
},
chatDataUserId() {
return this.$store.state.chatDataUserId;
},
chatWindowData() {
this.$store.dispatch('getchatDatalist');
if (this.$store.state.chatDatalist[this.talkTo.userId]) {
return this.$store.state.chatDatalist[this.talkTo.userId].list;
}
}
},
watch: {
chatDataState: {
deep: true,
immediate: true,
handler(v) {
if (this.chatDataUserId == this.talkTo.userId) {
this.scrolltoBottom();
this.clickToSubmitSure();
}
}
},
keyboardHeight: {
deep: true,
immediate: true,
handler(v) {
if (v > 0) {
this.showEmojitool = false;
}
}
}
},
onLoad(e) {
// // 监听接收聊天信息
uni.$on('onP2PMessage', this.onMessage)
this.toolist.push({
title: '音视频',
icon: 'yspin',
show: true
});
this.talkTo = e;
console.log(this.talkTo)
// 根据Id
this.$store
.dispatch('createChatObj', {
userId: this.talkTo.userId,
windowType: this.talkTo.windowType
})
.then(res => {
this.localData = res.data;
console.log(res.data)
if (e.windowType == 'SINGLE') {
uni.setNavigationBarTitle({
title: this.localData.fromInfo.nickName
});
}
this.$store.dispatch('getchatDatalist');
this.$store.dispatch('getChatList');
if (this.localData.fromInfo && this.localData.fromInfo.userType == 'normal') {
this.toolist.push({
title: '音视频',
icon: 'yspin'
});
} else {
this.$fc.setTitleNViewBtns(0, '');
this.showtitleNViewBtns = false;
}
if (this.localData.groupInfo && this.localData.groupInfo.userId) {
this.$fc.setTitleNViewBtns(0, '\ue623');
this.showtitleNViewBtns = true;
}
this.scrolltoBottom();
});
this.clickToSubmitSure = this.$fc.debounce(
() => {
observer = uni.createIntersectionObserver(this);
observer.relativeTo('.zfb-tk-main').observe('.autodownView', res => {
var isBottomH = res.intersectionRect.top + res.intersectionRect.height;
if (!this.isBottomHeight) {
this.isBottomHeight = res.relativeRect.height + res.relativeRect.top - 56;
}
if (parseInt(isBottomH) < parseInt(this.isBottomHeight) + 40) {
this.autodown = true;
} else {
this.autodown = false;
}
});
},
100,
false
);
},
onPageScroll() {
this.clickToSubmitSure();
},
onReady() {},
onShow() {
if (this.chatListInfo && this.chatListInfo.nickName) {
uni.setNavigationBarTitle({
title: this.chatListInfo.nickName
});
}
},
mounted() {
// #ifdef APP-PLUS
uni.onKeyboardHeightChange(res => {
this.keyboardHeight = res.height;
});
// #endif
},
onUnload() {
if (observer) {
observer.disconnect();
}
if (this.chatListInfo) {
this.chatListInfo.num = 0;
this.$store.dispatch('updateChatListInfoById', {
userId: this.talkTo.userId,
data: this.chatListInfo
});
}
},
methods: {
onMessage(message) {
//判断当前是单聊还是群聊
if (this.talkTo.windowType != 'SINGLE') {
return;
}
//如果是单聊,则判断当前消息发送人是不是当前窗口的聊天对象
if (this.talkTo.userId != message.fromId) {
return;
}
console.log("message 聊天页收到回调")
console.log(message)
//如果当前消息发送人和当前窗口的聊天对象一致,则发送已读回执
console.log("########### 此时需要发送已读回执 ###########")
this.$store.dispatch('sendP2PMessageReciveAck', message)
},
addMsg(e) {
this.msg += e;
},
clickitem(e, i) {
//发送收藏
this.sendMsg(e.content, e.collectType);
this.closepopup('popupfavorites');
},
longpressItem(e, i) {
this.longTapItemKey = i;
},
startRecord() {
this.$refs['rec'].startRecord();
this.showRecorder = true;
},
endRecord() {
this.$refs['rec'].stopRecord();
},
recorderStop(e) {
uni.showLoading({
title: '发送中'
});
this.$http.uploadFile({
url: '/file/uploadAudio',
filePath: e.recordFilePath,
name: 'file',
fileType: 'audio',
success: res => {
var data = JSON.parse(res.data);
if (data.code == 200) {
var msg = {
time: e.recordTime,
url: data.data.fullPath,
text: data.data.sourceText
};
this.sendMsg(JSON.stringify(msg), 'VOICE');
}
}
});
this.$refs['rec'].clear(); //清理录音
// 隐藏语音组件
this.showRecorder = false;
// this.showtool=false
},
changeShowVice() {
this.showVice = !this.showVice;
},
upLoadoneComplete(e) {
this.sendMsg(JSON.stringify(e), e.type);
},
upLoadallComplete(e) {
// this.sendMsg(JSON.stringify(e),'IMAGE')
},
changeEmojiTool() {
this.showEmojitool = !this.showEmojitool;
this.showtool = false;
},
changeTool() {
this.showtool = !this.showtool;
this.showEmojitool = false;
},
sendCardclick(e) {
this.$refs.popup.close();
this.sendMsg(JSON.stringify(e.item.data), 'CARD');
},
open() {
uni.getSystemInfo({
success: res => {
this.windowHeight = res.windowHeight;
}
});
this.$refs.popup.open('top');
},
closepopup(e) {
this.$refs[e].close();
},
openpopup(e) {
this.$refs[e].open('top');
},
tryagin(e, i) {
//重新发送
this.chatWindowData.splice(i, 1);
this.chatWindowData.splice(i, 1);
this.$store.dispatch('updateChatById', {
userId: this.talkTo.userId,
data: this.chatWindowData
});
this.$nextTick(() => {
this.sendMsg(e.content, e.msgType);
});
},
sendVoiceCall() {
//发起语音
uni.showLoading({
title: '发起语音通话'
});
var formdata = {
userId: this.talkTo.userId,
msgType: 'TRTC_VOICE_START',
content: 'TRTC_VOICE_START'
};
this.$http.request({
url: '/chat/sendMsg',
method: 'POST',
data: JSON.stringify(formdata),
success: res => {
if (res.data.code == '200') {
if (res.data.data.status !== '0') {
uni.showToast({
title: res.data.data.statusLabel,
icon: 'none'
});
return;
}
var userInfo = res.data.data.userInfo;
var data = {
userId: userInfo.userId,
trtcId: userInfo.trtcId,
nickName: userInfo.nickName,
portrait: userInfo.portrait,
startTime: new Date().getTime(),
type: 'audio'
};
uni.setStorage({
key: 'call',
data: JSON.stringify(data),
success: function() {
TUICalling.call({
userID: userInfo.trtcId,
type: 1
});
}
});
}
}
});
},
sendVideoCall(hasVideo = 1) {
//发起视频
uni.showLoading({
title: '发起通话'
});
var formdata = null;
if (hasVideo == 1) {
formdata = {
userId: this.talkTo.userId,
msgType: 'TRTC_VIDEO_START',
content: 'TRTC_VIDEO_START'
}
} else if (hasVideo == 0) {
formdata = {
userId: this.talkTo.userId,
msgType: 'TRTC_VOICE_START',
content: 'TRTC_VOICE_START'
}
}
// this.sendMsg(formdata,formdata.msgType)
const userId = localStorage.getItem("userId")
const roomId = userId
const userInfo = uni.getStorageSync("userInfo")
const roomInfo = {
roomId: userId, //后面改成发起人的手机号或者id
roomName: `${userInfo.nickName}发起的视频聊天`,
creatorId: userId,
creatorName: userInfo.nickName,
publishId: userId,
publishName: userInfo.nickName,
isOver: 0,
webrtcUrl: config.getSRSUrl() + `/${roomId}/${userId}`,
type: "webrtc",
offline: 0,
invitedUserList: [this.talkTo.userId],
hasVideo:hasVideo,
isForce:0
}
this.$store
.dispatch('createRoom', roomInfo)
.then(res => {
customHttp.customHttp.post("/api/im/app/wsMsg", {
msgType: "10000",
msgId: JSON.stringify(roomInfo),
cmd: "",
msgTxt: ""
}, {
dataType: 'json',
custom: {
target: "znzq"
},
}).then((res1) => {
location.href = config.getVideoRoomUrl(roomInfo.roomId, roomInfo.creatorId, 1, 1,hasVideo)
})
})
if (1 > 0) {
return false;
}
this.$http.request({
url: '/chat/sendMsg',
method: 'POST',
data: JSON.stringify(formdata),
success: res => {
if (res.data.code == '200') {
if (res.data.data.status !== '0') {
uni.showToast({
title: res.data.data.statusLabel,
icon: 'none'
});
return;
}
var userInfo = res.data.data.userInfo;
var data = {
userId: userInfo.userId,
trtcId: userInfo.trtcId,
nickName: userInfo.nickName,
portrait: userInfo.portrait,
startTime: new Date().getTime(),
type: 'video'
};
uni.setStorage({
key: 'call',
data: JSON.stringify(data),
success: function() {
TUICalling.call({
userID: userInfo.trtcId,
type: 2
});
}
});
}
}
});
},
toolClick(e) {
switch (e.title) {
case '位置':
uni.chooseLocation({
success: res => {
this.sendMsg(JSON.stringify(res), 'LOCATION');
}
});
break;
case '相册':
this.$refs['upload'].chooseTap();
break;
case '语音':
this.startRecord();
break;
case '名片':
this.open();
break;
case '音视频':
uni.showActionSheet({
itemList: ['视频通话', '语音通话'],
success: res => {
switch (res.tapIndex) {
case 0:
this.sendVideoCall(1);
break;
case 1:
this.sendVideoCall(0);
break;
default:
break;
}
}
});
break;
case '收藏':
this.openpopup('popupfavorites');
uni.getSystemInfo({
success: res => {
// #ifdef APP-PLUS
this.windowHeight = res.windowHeight - res.statusBarHeight - res.safeArea.top -
res.safeAreaInsets.top;
// #endif
// #ifndef APP-PLUS
this.windowHeight = res.windowHeight;
// #endif
}
});
break;
case '拍摄':
// #ifdef APP-PLUS
var _this = this;
uni.showActionSheet({
itemList: ['拍摄图片', '拍摄视频'],
success: res => {
switch (res.tapIndex) {
case 0:
getImage();
break;
case 1:
getVideo();
break;
default:
break;
}
},
fail: function(res) {
console.log(res.errMsg);
}
});
function getImage() {
//拍照事件
var cmr = plus.camera.getCamera();
cmr.captureImage(
function(p) {
plus.io.resolveLocalFileSystemURL(
p,
function(entry) {
//读取图片信息
compressImage(entry.toLocalURL(), entry.name); //压缩图片
},
function(e) {
console.log('读取拍照文件错误:' + e.message);
}
);
},
function(e) {
console.log(e);
}, {
filename: 'file:///storage/emulated/0/Documents/weiliao/'
}
);
}
function getVideo() {
//拍摄视频
var cmr = plus.camera.getCamera();
cmr.startVideoCapture(
function(p) {
plus.io.resolveLocalFileSystemURL(
p,
function(entry) {
//读取文件信息
compressVideo(entry.fullPath, entry.name); //压缩视频
},
function(e) {
console.log('读取视频文件错误:' + e.message);
}
);
},
function(e) {
console.log(e);
}, {
filename: 'file:///storage/emulated/0/Documents/weiliao/'
}
);
}
function compressImage(url, filename) {
//压缩图片
var name = 'file:///storage/emulated/0/Documents/weiliao/' + filename;
plus.zip.compressImage({
src: url, //src: (String 类型 )压缩转换原始图片的路径
dst: name, //压缩转换目标图片的路径
quality: 60, //quality: (Number 类型 )压缩图片的质量.取值范围为1-100
overwrite: true //overwrite: (Boolean 类型 )覆盖生成新文件
},
function(e) {
//压缩后
// openFile(e.target)
uni.showLoading({
title: '发送中'
});
sendPhoto(e.target); //发送
},
function(error) {
console.log('压缩图片失败,请稍候再试');
}
);
}
function compressVideo(url, filename) {
//压缩视频
// var name = 'file:///storage/emulated/0/Documents/weiliao/compress/' + filename;
plus.zip.compressVideo({
src: url, //src: (String 类型 )压缩转换原始路径
// filename: name, //压缩后的路径
quality: 'medium' //压缩级别low medium high
},
function(e) {
//压缩后
// openFile(e.tempFilePath)
uni.showLoading({
title: '发送中'
});
sendVideo(e.tempFilePath); //发送
},
function(error) {
console.log('压缩视频失败,请稍候再试');
}
);
}
function openFile(filePath) {
//打开文件
let system = uni.getSystemInfoSync().platform;
if (system == 'ios') {
filePath = encodeURI(filePath);
}
uni.openDocument({
filePath,
success: res => {
console.log('打开文件成功');
}
});
}
function sendPhoto(filePath) {
//TODO
//发送图片
customHttp.upload(config.getImApiUrl() + '/file/upload', {
params: {},
/* 会加在url上 */
// #ifdef APP-PLUS || H5
files: [], // 需要上传的文件列表。使用 files 时filePath 和 name 不生效。App、H5 2.6.15+
// #endif
// #ifdef MP-ALIPAY
fileType: 'image/video/audio', // 仅支付宝小程序,且必填。
// #endif
filePath: filePath, // 要上传文件资源的路径。
// 注如果局部custom与全局custom有同名属性则后面的属性会覆盖前面的属性相当于Object.assign(全局,局部)
name: 'file', // 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
// #ifdef H5 || APP-PLUS
timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)
// #endif
header: {},
/* 会与全局header合并如有同名属性局部覆盖全局 */
formData: {}, // HTTP 请求中其他额外的 form data
// 返回当前请求的task, options。请勿在此处修改options。非必填
getTask: (task, options) => {
// task.onProgressUpdate((res) => {
// console.log('上传进度' + res.progress);
// console.log('已经上传的数据长度' + res.totalBytesSent);
// console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);
//
// // 测试条件,取消上传任务。
// if (res.progress > 50) {
// uploadTask.abort();
// }
// });
},
//validateStatus: (statusCode) => { // statusCode 必存在。此处示例为全局默认配置。演示,非必填选项
// return statusCode >= 200 && statusCode < 300
//}
}).then(res => {
// 返回的res.data 已经进行JSON.parse
}).catch(err => {
})
_this.$http.uploadFile({
url: config.getImApiUrl() + '/file/upload',
filePath: filePath,
name: 'file',
fileType: 'image',
success: res => {
var data = JSON.parse(res.data);
if (data.code == 200) {
var msg = {
name: data.data.fileName,
url: data.data.fullPath
};
_this.sendMsg(JSON.stringify(msg), 'IMAGE');
}
}
});
}
function sendVideo(filePath) {
//发送视频
_this.$http.uploadFile({
url: config.getImApiUrl() + '/file/upload',
filePath: filePath,
name: 'file',
fileType: 'video',
success: res => {
var data = JSON.parse(res.data);
if (data.code == 200) {
var msg = {
name: data.data.fileName,
videoUrl: data.data.fullPath,
url: data.data.screenShot
};
_this.sendMsg(JSON.stringify(msg), 'VIDEO');
}
}
});
}
// #endif
break;
default:
break;
}
},
sendMsg(e, msgType) {
if (!e) {
return;
}
this.$fc.pushOutMsg({
msgContent: e,
msgType: msgType,
windowType: this.talkTo.windowType,
userId: this.talkTo.userId
});
this.msg = '';
// #ifdef H5
this.msgFocus = false;
this.$nextTick(() => {
this.msgFocus = true;
});
console.log("==============sdk:")
console.log(this.talkTo.userId)
// this.imsdk.lim.im.sendP2PMessage(this.imsdk.lim.im.createP2PTextMessage(this.talkTo.userId, e))
// #endif
},
startRecognize() {
//语音文本输入
// #ifdef H5
uni.showToast({
title: 'H5暂不支持',
icon: 'none'
});
return;
// #endif
let _this = this;
let options = {};
options.engine = 'baidu';
options.punctuation = false; // 是否需要标点符号
options.timeout = 10 * 1000;
plus.speech.startRecognize(
options,
function(s) {
_this.msg = _this.msg + s;
},
function(e) {
uni.showToast({
title: '语音识别失败:' + e.message,
icon: 'none'
});
}
);
},
scrolltoBottom() {
if (this.autodown) {
this.$nextTick(() => {
this.timer = setTimeout(() => {
uni.pageScrollTo({
scrollTop: 9999999,
duration: 10
});
}, 200);
});
}
}
},
onNavigationBarButtonTap(e) {
if (!this.showtitleNViewBtns) {
return;
}
switch (e.index) {
case 0:
if (this.talkTo.windowType == 'GROUP') {
uni.redirectTo({
url: '../groupInfo/detail?param=' + this.talkTo.userId
});
}
if (this.talkTo.windowType == 'SINGLE') {
uni.redirectTo({
url: '../personInfo/detail?param=' + this.talkTo.userId
});
}
break;
default:
break;
}
}
};
</script>
<style lang="scss" scoped>
.autodownView {
height: 1px;
width: 100%;
opacity: 0;
}
.uni-list {
background: none;
}
.zfb-tk-main {
padding: 0 12px;
padding-bottom: 112rpx;
}
.zfb-tk-send-tool {
background: #f7f7f7;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
transition: all 0.1s;
}
.zfb-tk-send-tools {
height: 558rpx;
width: 100%;
background-color: #f7f7f7;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
}
.zfb-tk-send-tools-item {
padding: 35rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.zfb-tk-send-tools-icon {
background-color: #fff;
width: 110rpx;
height: 110rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border-radius: 12rpx;
}
.zfb-tk-send-tools-icon .wxfont {
color: #181818;
font-size: 64rpx;
}
.zfb-tk-send-tools-text {
font-size: 24rpx;
color: #666;
margin-top: 16rpx;
}
.zfb-tk-send-tool-c {
position: relative;
z-index: 3;
padding: 16rpx 12rpx;
box-sizing: border-box;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
border: 1px #ddd solid;
border-left: none;
border-right: none;
}
.zfb-tk-send-tool-c .zfb-tk-send-tool-btn {
transition: color 0.5s;
}
.zfb-tk-send-tool-input-box {
overflow: auto;
width: 100%;
margin: 0 12rpx;
min-height: 75rpx;
background-color: #fff;
border-radius: 24rpx;
padding-top: 18rpx;
max-height: 225rpx;
box-sizing: border-box;
}
.zfb-tk-send-tool .zfb-tk-send-tool-input {
padding: 0 24rpx;
box-sizing: border-box !important;
width: 100%;
background: #fff;
}
.zfb-tk-send-tool-vioce {
box-sizing: border-box;
margin: 0 12rpx;
width: 100%;
height: 75rpx;
border-radius: 24rpx;
background: #fff;
display: flex;
flex-direction: row;
align-items: center;
}
.zfb-tk-send-tool-vioce-item {
text-align: center;
font-size: 24rpx;
line-height: 75rpx;
flex: 1;
}
.zfb-tk-send-tool-vioce-item:nth-child(1) {
border-right: 1px #eee solid;
}
.zfb-tk-send-tool-text {
white-space: nowrap;
padding: 10rpx 24rpx;
border-radius: 12rpx;
border: 1px #ddd solid;
background: #f7f7f7;
color: #ddd;
}
.zfb-tk-send-tool-more {
font-size: 64rpx;
color: #333;
}
.zfb-tk-send-tool-icon {
font-size: 64rpx;
color: #333;
}
.zfb-tk-recorder {
width: 250rpx;
height: 250rpx;
left: 50%;
transform: translateX(-50%);
bottom: 680rpx;
box-sizing: border-box;
text-align: center;
position: fixed;
border-radius: 50%;
background-color: #f8f8f8;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);
padding: 20rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.popsendCard {
display: flex;
background-color: #fff;
overflow: auto;
}
.popsendCard-close {
width: 100%;
text-align: center;
height: 70rpx;
line-height: 70rpx;
font-size: 42rpx;
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
z-index: 9999;
}
.wxemojitool {
height: 558rpx;
}
.wxemojitool-content {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.wxemojitool-item {
font-size: 44rpx;
width: 93rpx;
height: 93rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
</style>