529 lines
16 KiB
Vue
529 lines
16 KiB
Vue
<template>
|
||
<view>
|
||
<view class="TUI-message-input-container">
|
||
<!-- 快捷菜单栏 -->
|
||
<!-- <view class="TUI-commom-function">
|
||
<view v-for="(item, index) in commonFunction" :key="index" class="TUI-commom-function-item" :data-function="item" @tap="handleCommonFunctions">{{ item.name }}</view>
|
||
</view> -->
|
||
<view class="TUI-message-input">
|
||
<!-- #ifndef H5 -->
|
||
<image class="TUI-icon" @tap="switchAudio" :src="isAudio ? 'https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/keyboard.svg' : 'https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/audio.svg'"></image>
|
||
<!-- #endif -->
|
||
<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="向Ta问候下吧~" @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="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/face-emoji.svg"></image>
|
||
<view v-if="!sendMessageBtn" @tap="handleExtensions">
|
||
<image class="TUI-icon" src="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/more.svg"></image>
|
||
</view>
|
||
<view v-else class="TUI-sendMessage-btn" @tap="sendTextMessage">发送</view>
|
||
</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">
|
||
<view class="TUI-Extension-slot" @tap="handleSendPicture">
|
||
<image class="TUI-Extension-icon" src="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/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="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/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="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/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="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/send-video.svg"></image>
|
||
<view class="TUI-Extension-slot-name">发送视频</view>
|
||
</view>
|
||
|
||
<view class="TUI-Extension-slot" :data-value="1" @tap="handleCalling" v-if="conversation.type=='C2C'">
|
||
<image class="TUI-Extension-icon" src="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/audio-calling.svg"></image>
|
||
<view class="TUI-Extension-slot-name">语音通话</view>
|
||
</view>
|
||
<view class="TUI-Extension-slot" :data-value="2" @tap="handleCalling" v-if="conversation.type=='C2C'">
|
||
<image class="TUI-Extension-icon" src="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/video-calling.svg"></image>
|
||
<view class="TUI-Extension-slot-name">视频通话</view>
|
||
</view>
|
||
|
||
<view class="TUI-Extension-slot" @tap="handleServiceEvaluation" v-if='false'>
|
||
<image class="TUI-Extension-icon" src="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/static/assets/service-assess.svg"></image>
|
||
<view class="TUI-Extension-slot-name">服务评价</view>
|
||
</view>
|
||
<view class="TUI-Extension-slot" @tap="handleSendOrder" v-if='false'>
|
||
<image class="TUI-Extension-icon" src="https://jw-uniapp.oss-cn-beijing.aliyuncs.com/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 {
|
||
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: () => {}
|
||
}
|
||
},
|
||
|
||
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;
|
||
}
|
||
});
|
||
console.log(res);
|
||
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(e) {
|
||
if (this.conversation.type === 'GROUP') {
|
||
uni.navigateTo({
|
||
url: '/pages/im/group/invitation-friends/conversation?groupID=' + this.conversation.conversationID + '&callMediaType=' + e.currentTarget.dataset.value
|
||
});
|
||
return;
|
||
}
|
||
|
||
const type = e.currentTarget.dataset.value;
|
||
const { userID } = this.conversation.userProfile;
|
||
this.$emit('handleCall', {
|
||
detail: {
|
||
type,
|
||
userID
|
||
}
|
||
});
|
||
this.displayFlag = '';
|
||
},
|
||
|
||
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) {
|
||
this.$emit('sendMessage', {
|
||
detail: {
|
||
message
|
||
}
|
||
});
|
||
uni.$TUIKit.sendMessage(message)
|
||
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>
|