flinfo/dc-App/pages/Chat/newChat/submit.vue
2025-03-28 16:03:03 +08:00

587 lines
14 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>
<view class="submit">
<view class="submit-chat">
<view class="bt-img" @tap="records" v-if="isShow">
<image :src="toc"></image>
</view>
<view class="bt-img" @tap="more">
<image src="/static/chat/takepictures.png"></image>
</view>
<!-- 文本框 -->
<textarea auto-height="true" class="chat-send btn" :class="{displaynone:isrecord}" @input="inputs"
@focus="focus" v-model="msg" placeholder="Please enter content"></textarea>
<view class="record btn" :class="{displaynone:!isrecord}" @touchstart="touchstart" @touchend="touchend"
@touchmove="touchmove">
<span style="font-size: 30rpx">
Please press and hold to speak
</span>
</view>
<!-- <view class="bt-img" @tap="emoji">
<image src="/static/logo.png"></image>
</view> -->
<view class="bt-size" v-if="msg!=''" @tap="send(msg,0)">
send
</view>
</view>
<!-- 表情 -->
<view class="emoji" :class="{displaynone:!isemoji}">
<view class="emoji-send">
<view class="emoji-send-det" @tap="emojiBack">
<image src="/static/chat/more.png"></image>
</view>
<view class="emoji-send-bt" @tap="emojiSend">发送</view>
</view>
<emoji @emotion="emotion" :height="260"></emoji>
</view>
<!-- 更多 -->
<view class="more" :class="{displaynone:!ismore}">
<view class="more-list" @tap="sendImg('album')">
<image src="/static/chat/pictures.png"></image>
<view class="more-list-title">Photos</view>
</view>
<view class="more-list" @tap="sendImg('camera')">
<image src="/static/chat/takepictures.png"></image>
<view class="more-list-title">Take Photo</view>
</view>
</view>
</view>
<view class="voice-bg" :class="{displaynone:!voicebg}">
<view class="voice-bg-len">
<view class="voice-bg-time" :style="{width:vlength/0.6+'%'}">
{{ vlength }}
</view>
<!-- <view class="voice-del">上滑取消录音</view> -->
</view>
</view>
</view>
</template>
<script>
// 引入组件
import emoji from './emoji.vue'
import {pathToBase64, base64ToPath} from 'image-tools';
import request from '../../../utils/request'
import {fileToBase64} from '@/uni_modules/lime-file-utils'
import upload from "@/utils/upload";
import config from "@/config";
// 录音
const recorderManager = uni.getRecorderManager();
export default {
data() {
return {
isrecord: false,
isemoji: false,
ismore: false,
voicebg: false,
pageY: 0,
msg: "",
// 直接引用地址可能出不来需要用require
toc: "/static/chat/language.png",
timer: '', //计时器
vlength: 0,
translatorImageUploadUrl: config.translatorImageUploadUrl,
isShow: false
};
},
components: {
emoji,
},
props: {
// 父组件传过来的值
title: {
type: String,
default: ''
},
},
mounted() {
if (this.title == 'Translator') {
this.isShow = true
}
},
methods: {
//获取高度方法
getElementHeight() {
const query = uni.createSelectorQuery().in(this);
query.select('.submit').boundingClientRect(data => {
this.$emit('heights', data.height);
}).exec();
},
//切换音频
records() {
//切换的时候关闭其他界面
this.ismore = false
this.isemoji = false
//切换高度
setTimeout(() => {
this.getElementHeight();
}, 10)
if (this.isrecord) {
this.isrecord = false;
this.toc = "/static/chat/language.png";
} else {
this.isrecord = true;
this.toc = "/static/chat/keyboard.png";
}
},
// 表情
emoji() {
this.isemoji = !this.isemoji;
//切换的时候关闭其功能
this.ismore = false
this.isrecord = false;
//切换高度
setTimeout(() => {
this.getElementHeight();
}, 10)
},
//接收表情
emotion(e) {
console.log(e),
this.msg = this.msg + e
},
//文字发送
inputs(e) {
console.log("inputs里面的内容", e)
var chatm = e.detail.value;
var pos = chatm.indexOf('\n');
// 检索字符串没有数据,返回-1
// if (pos != -1 && chatm.length > 1) {
// this.$emit('inputs', this.msg);
// setTimeout(() => {
// this.msg = '';
// }, 0)
// }
if (pos != -1 && chatm.length > 1) {
// 0为表情和文字
this.send(this.msg, 0)
}
},
// 输入框聚焦
focus() {
//关闭其他项
this.isemoji = false;
this.ismore = false;
setTimeout(() => {
this.getElementHeight()
}, 10)
},
// 表情内发送
emojiSend() {
// if (this.msg.length > 0) {
// this.$emit('inputs', this.msg);
// setTimeout(() => {
// this.msg = '';
// }, 0)
// }
if (this.msg.length > 0) {
//0为表情和文字
this.send(this.msg, 0)
}
},
// 表格退格
emojiBack() {
if (this.msg.length > 0) {
this.msg = this.msg.substring(0, this.msg.length - 1);
}
},
//更多功能
more() {
this.ismore = !this.ismore;
//切换的时候关闭其他界面
this.isemoji = false
setTimeout(() => {
this.getElementHeight();
}, 10)
},
//图片发送
sendImg(e) {
console.log('此时的标题', this.title)
let count = 1;
if (e == 'album') {
count = 1;
} else {
count = 1;
}
let that = this
uni.chooseImage({
count: count, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: [e], //从相册选择
// success: function (res) { //用function的方式会找不到send方法
success: (res) => {
const tempFilePaths = res.tempFilePaths;
console.log(res, 199);
if ('Trip Advisor' == that.title) {
uni.uploadFile({
url: 'http://47.243.63.30:8080/v1/files/upload',
filePath: tempFilePaths[0],
header: {
"Authorization": "Bearer app-4Wqu03XTw297LtEsTXhotOuP" //
},
name: 'file',
success: (res) => {
console.log(res.data,'上传图片返回结果')
//将res.data转为json
let json = JSON.parse(res.data)
console.log(json.id,'上传图片返回结果')
upload({
filePath: tempFilePaths[0],
url: 'base64Api/upload',
name: 'file',
}).then(res1 => {
request({
url: 'base64Api/inputBase64',
method: 'post',
data: {
base64: res1.base64
}
}).then(res2 => {
that.send(json.id, 1, res1.base64,null,res1.url)
})
})
// that.send(json.id, 1, res.data)
},
fail: (err) => {
console.log(err,'上传报错')
}
})
}else {
upload({
filePath: tempFilePaths[0],
url: 'base64Api/upload',
name: 'file',
}).then(res1 => {
request({
url: 'base64Api/inputBase64',
method: 'post',
data: {
base64: res1.base64
}
}).then(res2 => {
that.send(res2.data, 1, res1.base64)
})
})
}
// pathToBase64(tempFilePaths[0]).then(base64 => {
//
// request({
// url: 'base64Api/inputBase64',
// method: 'post',
// data: {
// base64: base64
// }
// }).then(res => {
// that.send(res.data, 1, base64)
// })
//
// })
// .catch(error => {
// console.error(error)
// })
}
});
},
//音频处理
//开始录音
touchstart(e) {
console.log("开始录音")
console.log("点击产生数据", e)
this.pageY = e.changedTouches[0].pageY;
this.voicebg = true;
let i = 1;
this.timer = setInterval(() => {
this.vlength = i;
i++;
console.log("计时器开始工作,第几秒", i)
//结束计时
if (i > 60) {
clearInterval(this.timer);
this.touchend();
}
}, 1000)
const options = {
format: 'mp3', // 音频格式
sampleRat: 16000,
numberOfChannels: 1,
};
recorderManager.start(options);
},
//删除录音
touchmove(e) {
// console.log("滑动到的y轴高度",e.changedTouches[0].pageY);
if (this.pageY - e.changedTouches[0].pageY > 100) {
// 关闭录音界面
this.voicebg = false;
}
},
// 结束录音
touchend() {
clearInterval(this.timer);
let that = this
recorderManager.onStop(function (res) {
console.log('recorder stop' + JSON.stringify(res));
let data = {
voice: res.tempFilePath,
time: this.vlength
}
// let mp3Base64 = fileToBase64(res.tempFilePath)
//上传文件
upload({
filePath: res.tempFilePath,
url: 'base64Api/upload',
name: 'file',
}).then(res => {
console.log('上传成功', res)
// //时长归位
request({
url: 'base64Api/inputBase64',
method: 'post',
data: {
base64: res.base64,
type: 2
}
}).then(ress => {
that.send(ress.data, 2, res.base64, that.vlength, res.url)
this.vlength = 0;
})
}).catch(error => {
console.error(error, '上传错误')
})
})
recorderManager.stop();
this.voicebg = false;
console.log("结束录音");
},
//获取位置
choseLocation() {
uni.chooseLocation({
// success: function(res) {
success: res => {
let data = {
name: res.name,
address: res.address,
latitude: res.latitude,
longitude: res.longitude
}
this.send(data, 3);
}
});
},
//发送
send(msg, type, base64, time,url) {
let date = {
message: msg,
type: type,
base64: base64,
time: time,
filePath: base64,
url:url
}
this.$emit('inputs', date);
setTimeout(() => {
this.msg = '';
}, 0)
},
}
};
</script>
<style lang="scss" scoped>
.bt-size {
width: 140rpx;
height: 50rpx;
background: #096300;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 14px;
margin-bottom: 8px;
border-radius: 50px;
}
.submit {
background: rgba(244, 244, 244, 0.96);
border-top: 1px solid rgba(39, 40, 50, 0.1);
width: 100%;
position: fixed;
bottom: 0;
z-index: 100;
// padding-bottom: var(--status-bar-height);
padding-bottom: env(safe-area-inset-bottom);
}
.displaynone {
display: none;
}
.submit-chat {
width: 100%;
display: flex;
align-items: flex-end;
box-sizing: border-box;
padding: 14rpx 14rpx;
image {
width: 56rpx;
height: 56rpx;
margin: 0 10rpx;
flex: auto;
}
.btn {
flex: auto;
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
max-height: 160rpx;
margin: 0 10rpx;
}
.chat-send {
line-height: 44rpx;
}
.record {
line-height: 44rpx;
text-align: center;
font-size: 20rpx;
color: rgba(39, 40, 50, 0.6);
}
}
.emoji {
width: 100%;
height: 460rpx;
background: rgba(236, 237, 238, 1);
box-shadow: 0px 11rpx 0px 0px rgba(0, 0, 0, 0.1);
.emoji-send {
width: 280rpx;
height: 104rpx;
padding-top: 24rpx;
background-color: rgba(236, 237, 238, 0.8);
position: fixed;
// bottom: 0;
bottom: env(safe-area-inset-bottom);
right: 0;
display: flex;
.emoji-send-bt {
flex: 1;
margin: 0 32rpx 0 20rpx;
height: 80rpx;
background: rgba(255, 228, 49, 1);
font-size: 32rpx;
text-align: center;
line-height: 80rpx;
border-radius: 12rpx;
}
.emoji-send-det {
flex: 1;
margin-left: 24rpx;
height: 80rpx;
background: #fff;
font-size: 32rpx;
text-align: center;
line-height: 80rpx;
border-radius: 12rpx;
image {
width: 42rpx;
height: 32rpx;
}
}
}
}
.more {
width: 100%;
height: 436rpx;
background: rgba(236, 237, 238, 1);
box-shadow: 0px 11rpx 0px 0px rgba(0, 0, 0, 0.1);
bottom: env(safe-area-inset-bottom);
padding: 8rpx 20rpx;
box-sizing: border-box;
.more-list {
width: 25%;
text-align: center;
float: left;
padding-top: 32rpx;
image {
width: 72rpx;
height: 72rpx;
padding: 24rpx;
background: rgba(255, 255, 255, 1);
border-radius: 24rpx;
}
.more-list-title {
font-size: 24rpx;
color: rgba(39, 40, 50, 0.5);
line-height: 34rpx;
}
}
}
.voice-bg {
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.3);
position: fixed;
top: 0;
bottom: 0;
z-index: 1001;
.voice-bg-len {
height: 84rpx;
width: 600rpx;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 42rpx;
text-align: center;
}
.voice-bg-time {
display: inline-block;
min-width: 120rpx;
line-height: 84rpx;
background-color: rgba(255, 228, 49, 1);
border-radius: 42rpx;
}
.voice-del {
position: absolute;
bottom: -480rpx;
width: 100%;
text-align: center;
color: #fff;
font-size: 28rpx;
}
}
</style>