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.
 
 
 
 
 

589 lines
15 KiB

<template>
<view>
<view class="TUI-message-input-container">
<view class="TUI-commom-function">
<view v-for="(item, index) in 0" :key="index" class="TUI-commom-function-item" :data-function="item" @tap="handleCommonFunctions">
{{ item.name }}
</view>
</view>
<view class="TUI-message-input">
<!-- <image class="TUI-icon" @tap="switchAudio" :src="isAudio ? '/static/static/assets/keyboard.svg' : '/static/static/assets/audio.svg'"></image> -->
<view v-if="!isAudio" class="TUI-message-input-main">
<input
class="TUI-message-input-area"
:adjust-position="true"
cursor-spacing="20"
v-model="inputText"
@input="onInputValueChange"
maxlength="140"
type="text"
placeholder-class="input-placeholder"
placeholder="说点什么呢~"
@focus="inputBindFocus"
@blur="inputBindBlur"
/>
</view>
<view
v-else
class="TUI-message-input-main"
@longpress="handleLongPress"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
style="display: flex; justify-content: center; font-size: 32rpx; font-family: PingFangSC-Regular;"
>
<text>{{ text }}</text>
</view>
<view class="TUI-message-input-functions" hover-class="none">
<!-- <image class="TUI-icon" @tap="handleEmoji" src="/static/static/assets/face-emoji.svg"></image> -->
<!-- <view v-if="!sendMessageBtn" @tap="handleExtensions"><image class="TUI-icon" src="/static/static/assets/more.svg"></image></view> -->
<!-- <view v-else class="TUI-sendMessage-btn" @tap="sendTextMessage">发送</view> -->
<image class="TUI-icon" @tap="sendTextMessage" src="../../../static/message/send.png"></image>
</view>
</view>
<view v-if="displayFlag === 'emoji'" class="TUI-Emoji-area"><TUI-Emoji @enterEmoji="appendMessage"></TUI-Emoji></view>
<view v-if="displayFlag === 'extension'" class="TUI-Extensions">
<!-- TODO: 这里功能还没实现 -->
<!-- <camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 300px;"></camera>-->
<view class="TUI-Extension-slot" @tap="handleSendPicture">
<image class="TUI-Extension-icon" src="/static/static/assets/take-photo.svg"></image>
<view class="TUI-Extension-slot-name">拍摄照片</view>
</view>
<view class="TUI-Extension-slot" @tap="handleSendImage">
<image class="TUI-Extension-icon" src="/static/static/assets/send-img.svg"></image>
<view class="TUI-Extension-slot-name">发送图片</view>
</view>
<view class="TUI-Extension-slot" @tap="handleShootVideo">
<image class="TUI-Extension-icon" src="/static/static/assets/take-video.svg"></image>
<view class="TUI-Extension-slot-name">拍摄视频</view>
</view>
<view class="TUI-Extension-slot" @tap="handleSendVideo">
<image class="TUI-Extension-icon" src="/static/static/assets/send-video.svg"></image>
<view class="TUI-Extension-slot-name">发送视频</view>
</view>
<!-- <view class="TUI-Extension-slot" @tap="handleCalling(1)">
<image class="TUI-Extension-icon" src="/static/static/assets/audio-calling.svg"></image>
<view class="TUI-Extension-slot-name">语音通话</view>
</view>
<view class="TUI-Extension-slot" @tap="handleCalling(2)">
<image class="TUI-Extension-icon" src="/static/static/assets/video-calling.svg"></image>
<view class="TUI-Extension-slot-name">视频通话</view>
</view>
<view class="TUI-Extension-slot" @tap="handleServiceEvaluation">
<image class="TUI-Extension-icon" src="/static/static/assets/service-assess.svg"></image>
<view class="TUI-Extension-slot-name">服务评价</view>
</view> -->
<view class="TUI-Extension-slot" @tap="handleSendOrder">
<image class="TUI-Extension-icon" src="/static/static/assets/send-order.svg"></image>
<view class="TUI-Extension-slot-name">发送订单</view>
</view>
</view>
<TUI-Common-Words class="tui-cards" :display="displayCommonWords" @sendMessage="$handleSendTextMessage" @close="$handleCloseCards"></TUI-Common-Words>
<TUI-Order-List class="tui-cards" :display="displayOrderList" @sendCustomMessage="$handleSendCustomMessage" @close="$handleCloseCards"></TUI-Order-List>
<TUI-Service-Evaluation
class="tui-cards"
:display="displayServiceEvaluation"
@sendCustomMessage="$handleSendCustomMessage"
@close="$handleCloseCards"
></TUI-Service-Evaluation>
</view>
<view class="record-modal" v-if="popupToggle" @longpress="handleLongPress" @touchmove="handleTouchMove" @touchend="handleTouchEnd">
<view class="wrapper"><view class="modal-loading"></view></view>
<view class="modal-title">{{ title }}</view>
</view>
</view>
</template>
<script>
import TUIEmoji from '../message-elements/emoji/index';
import TUICommonWords from '../message-private/common-words/index';
import TUIOrderList from '../message-private/order-list/index';
import TUIServiceEvaluation from '../message-private/service-evaluation/index';
export default {
data() {
return {
// todo conversation
// conversation: {},
firstSendMessage: true,
inputText: '',
extensionArea: false,
sendMessageBtn: false,
displayFlag: '',
isAudio: false,
bottomVal: 0,
startPoint: 0,
popupToggle: false,
isRecording: false,
canSend: true,
text: '按住说话',
title: ' ',
notShow: false,
isShow: true,
recordTime: 0,
recordTimer: null,
commonFunction: [
{
name: '常用语',
key: '0'
},
{
name: '发送订单',
key: '1'
},
{
name: '服务评价',
key: '2'
}
],
displayServiceEvaluation: false,
displayCommonWords: false,
displayOrderList: false
};
},
components: {
TUIEmoji,
TUICommonWords,
TUIOrderList,
TUIServiceEvaluation
},
props: {
conversation: {
type: Object,
default: () => {}
}
},
watch: {
conversation: {
handler: function(newVal) {
// todo 值会被改变
// this.setData({
// conversation: newVal
// });
},
immediate: true,
deep: true
}
},
beforeMount() {
// 加载声音录制管理器
this.recorderManager = uni.getRecorderManager();
this.recorderManager.onStop(res => {
clearInterval(this.recordTimer);
// 兼容 uniapp 打包app,duration 和 fileSize 需要用户自己补充
// 文件大小 = (音频码率) x 时间长度(单位:秒) / 8
let msg = {
duration: res.duration ? res.duration : this.recordTime * 1000,
tempFilePath: res.tempFilePath,
fileSize: res.fileSize ? res.fileSize : ((48 * this.recordTime) / 8) * 1024
};
uni.hideLoading();
// 兼容 uniapp 语音消息没有duration
if (this.canSend) {
if (msg.duration < 1000) {
uni.showToast({
title: '录音时间太短',
icon: 'none'
});
} else {
// res.tempFilePath 存储录音文件的临时路径
const message = uni.$TUIKit.createAudioMessage({
to: this.getToAccount(),
conversationType: this.conversation.type,
payload: {
file: msg
}
});
this.$sendTIMMessage(message);
}
}
this.setData({
startPoint: 0,
popupToggle: false,
isRecording: false,
canSend: true,
title: ' ',
text: '按住说话'
});
});
},
methods: {
switchAudio() {
this.setData({
isAudio: !this.isAudio,
text: '按住说话'
});
},
handleLongPress(e) {
this.recorderManager.start({
duration: 60000,
// 录音的时长,单位 ms,最大值 600000(10 分钟)
sampleRate: 44100,
// 采样率
numberOfChannels: 1,
// 录音通道数
encodeBitRate: 192000,
// 编码码率
format: 'aac' // 音频格式,选择此格式创建的音频消息,可以在即时通信 IM 全平台(Android、iOS、微信小程序和Web)互通
});
this.setData({
startPoint: e.touches[0],
title: '正在录音',
// isRecording : true,
// canSend: true,
notShow: true,
isShow: false,
isRecording: true,
popupToggle: true,
recordTime: 0
});
this.recordTimer = setInterval(() => {
this.recordTime++;
}, 1000);
},
// 录音时的手势上划移动距离对应文案变化
handleTouchMove(e) {
if (this.isRecording) {
if (this.startPoint.clientY - e.touches[e.touches.length - 1].clientY > 100) {
this.setData({
text: '抬起停止',
title: '松开手指,取消发送',
canSend: false
});
} else if (this.startPoint.clientY - e.touches[e.touches.length - 1].clientY > 20) {
this.setData({
text: '抬起停止',
title: '上划可取消',
canSend: true
});
} else {
this.setData({
text: '抬起停止',
title: '正在录音',
canSend: true
});
}
}
},
// 手指离开页面滑动
handleTouchEnd() {
this.setData({
isRecording: false,
popupToggle: false
});
uni.hideLoading();
this.recorderManager.stop();
},
handleEmoji() {
let targetFlag = 'emoji';
if (this.displayFlag === 'emoji') {
targetFlag = '';
}
this.setData({
displayFlag: targetFlag
});
},
handleExtensions() {
let targetFlag = 'extension';
if (this.displayFlag === 'extension') {
targetFlag = '';
}
this.setData({
displayFlag: targetFlag
});
},
error(e) {
console.log(e.detail);
},
handleSendPicture() {
this.sendImageMessage('camera');
},
handleSendImage() {
this.sendImageMessage('album');
},
sendImageMessage(type) {
uni.chooseImage({
sourceType: [type],
count: 1,
success: res => {
if (res) {
const message = uni.$TUIKit.createImageMessage({
to: this.getToAccount(),
conversationType: this.conversation.type,
payload: {
file: res
},
onProgress: percent => {
message.percent = percent;
}
});
this.$sendTIMMessage(message);
}
}
});
},
handleShootVideo() {
this.sendVideoMessage('camera');
},
handleSendVideo() {
this.sendVideoMessage('album');
},
sendVideoMessage(type) {
uni.chooseVideo({
sourceType: [type],
// 来源相册或者拍摄
maxDuration: 60,
// 设置最长时间60s
camera: 'back',
// 后置摄像头
success: res => {
if (res) {
const message = uni.$TUIKit.createVideoMessage({
to: this.getToAccount(),
conversationType: this.conversation.type,
payload: {
file: res
},
onProgress: percent => {
message.percent = percent;
}
});
this.$sendTIMMessage(message);
}
}
});
},
handleCommonFunctions(e) {
switch (e.target.dataset.function.key) {
case '0':
this.setData({
displayCommonWords: true
});
break;
case '1':
this.setData({
displayOrderList: true
});
break;
case '2':
this.setData({
displayServiceEvaluation: true
});
break;
default:
break;
}
},
handleSendOrder() {
this.setData({
displayOrderList: true
});
},
appendMessage(e) {
this.setData({
inputText: this.inputText + e.detail.message,
sendMessageBtn: true
});
},
getToAccount() {
if (!this.conversation || !this.conversation.conversationID) {
return '';
}
switch (this.conversation.type) {
case 'C2C':
return this.conversation.conversationID.replace('C2C', '');
case 'GROUP':
return this.conversation.conversationID.replace('GROUP', '');
default:
return this.conversation.conversationID;
}
},
handleCalling(value) {
// todo 目前支持单聊
if (this.conversation.type === 'GROUP') {
uni.showToast({
title: '群聊暂不支持',
icon: 'none'
});
return;
}
const { userID } = this.conversation.userProfile;
// #ifdef APP-PLUS
if(typeof(uni.$TUICalling) === 'undefined') {
logger.error('请使用真机运行并且自定义基座调试,可能影响音视频功能~ 插件地址:https://ext.dcloud.net.cn/plugin?id=7097 , 调试地址:https://nativesupport.dcloud.net.cn/NativePlugin/use/use');
uni.showToast({
title: '请使用真机运行并且自定义基座调试,可能影响音视频功能~ ',
icon: 'none',
duration: 3000
});
} else {
uni.$TUICalling.call(
{
userID: userID,
type: value
},
res => {
console.log(JSON.stringify(res));
}
);
}
// #endif
},
sendTextMessage(msg, flag) {
const to = this.getToAccount();
const text = flag ? msg : this.inputText;
const message = uni.$TUIKit.createTextMessage({
to,
conversationType: this.conversation.type,
payload: {
text
}
});
this.setData({
inputText: '',
sendMessageBtn: false
});
this.$sendTIMMessage(message);
},
onInputValueChange(event) {
if (event.detail.value) {
this.setData({
sendMessageBtn: true
});
} else {
this.setData({
sendMessageBtn: false
});
}
},
$handleSendTextMessage(event) {
this.sendTextMessage(event.detail.message, true);
this.setData({
displayCommonWords: false
});
},
$handleSendCustomMessage(e) {
const message = uni.$TUIKit.createCustomMessage({
to: this.getToAccount(),
conversationType: this.conversation.type,
payload: e.detail.payload
});
this.$sendTIMMessage(message);
this.setData({
displayOrderList: false
});
},
$handleCloseCards(e) {
switch (e.detail.key) {
case '0':
this.setData({
displayCommonWords: false
});
break;
case '1':
this.setData({
displayOrderList: false
});
break;
case '2':
this.setData({
displayServiceEvaluation: false
});
break;
default:
break;
}
},
$sendTIMMessage(message) {
const SDKAppID = getApp().globalData.SDKAppID;
this.$emit('sendMessage', {
detail: {
message
}
});
uni.$TUIKit.sendMessage(message).then((res) => {
if(this.firstSendMessage) {
uni.$aegis.reportEvent({
name: 'sendMessage',
ext1: 'sendMessage-success',
ext2: 'uniTuikitExternal',
ext3: `${SDKAppID}`,
})
}
this.firstSendMessage = false
}).catch((error) => {
uni.$aegis.reportEvent({
name: 'sendMessage',
ext1: `sendMessage-failed#error: ${error}`,
ext2: 'uniTuikitExternal',
ext3: `${SDKAppID}`,
})
})
this.setData({
displayFlag: ''
});
},
handleClose() {
this.setData({
displayFlag: ''
});
},
handleServiceEvaluation() {
this.setData({
displayServiceEvaluation: true
});
},
inputBindFocus() {
console.log('占位:函数 inputBindFocus 未声明');
},
inputBindBlur() {
console.log('占位:函数 inputBindBlur 未声明');
}
}
};
</script>
<style>
@import './index.css';
</style>