123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- <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">
- <image class="TUI-icon" @tap="switchAudio" :src="isAudio ? '/static/assets/keyboard.svg' : '/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/assets/face-emoji.svg"></image>
- <view v-if="!sendMessageBtn" @tap="handleExtensions"><image class="TUI-icon" src="/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">
- <!-- 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/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/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/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/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/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/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/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/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 {
-
- 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: () => {}
- },
- toUser: {
- type: String,
- default: () => {}
- }
- },
- watch: {
- conversation: {
- handler: function(newVal) {
- // todo 值会被改变
- // this.setData({
- // conversation: newVal
- // });
- },
- immediate: true,
- deep: true
- }
- },
- beforeMount() {
- var that=this;
- // 加载声音录制管理器
- 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 {
- var orderId=uni.getStorageSync('orderId');
- // res.tempFilePath 存储录音文件的临时路径
- const message = uni.$TUIKit.createAudioMessage({
- to: this.getToAccount(),
- conversationType: this.conversation.type,
- payload: {
- file: msg
- },
- cloudCustomData: 'orderId='+orderId
- });
- this.$sendTIMMessage(message);
- }
- }
- that.setData({
- startPoint: 0,
- popupToggle: false,
- isRecording: false,
- canSend: true,
- title: ' ',
- text: '按住说话'
- });
- });
- },
- methods: {
- switchAudio() {
- this.isAudio= !this.isAudio;
- this.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.displayFlag=targetFlag;
-
- },
- handleExtensions() {
- let targetFlag = 'extension';
- if (this.displayFlag === 'extension') {
- targetFlag = '';
- }
- this.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) {
- var orderId=uni.getStorageSync('orderId');
- const message = uni.$TUIKit.createImageMessage({
- to: this.getToAccount(),
- conversationType: this.conversation.type,
- payload: {
- file: res
- },
- cloudCustomData: 'orderId='+orderId,
- 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) {
- var orderId=uni.getStorageSync('orderId');
- const message = uni.$TUIKit.createVideoMessage({
- to: this.getToAccount(),
- conversationType: this.conversation.type,
- payload: {
- file: res
- },
- cloudCustomData: 'orderId='+orderId,
- 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() {
- return this.toUser;
- },
- 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
- // #ifdef MP-WEIXIN
- uni.showToast({
- title: '微信小程序暂不支持',
- icon: 'none'
- });
- // uni.$wxTUICalling.call({userID, type: value})
- // #endif
- },
- sendTextMessage(msg, flag) {
- var orderId=uni.getStorageSync('orderId');
- console.log(this.conversation.type)
- const to = this.getToAccount();
- const text = flag ? msg : this.inputText;
- const message = uni.$TUIKit.createTextMessage({
- to,
- conversationType: this.conversation.type,
- payload: {
- text:text
- },
- cloudCustomData: 'orderId='+orderId
- });
- 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) {
- var orderId=uni.getStorageSync('orderId');
- const message = uni.$TUIKit.createCustomMessage({
- to: this.getToAccount(),
- conversationType: this.conversation.type,
- payload: e.detail.payload,
- cloudCustomData: 'orderId='+orderId
- });
- 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).then((res) => {
- this.firstSendMessage = false
- }).catch((error) => {
-
- })
- 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>
|