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.

572 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view>
<view class="submit">
<view class="submit-chat">
<view class="bt-img" @tap="records">
<image :src="toc"></image>
</view>
<!-- 文本框 -->
<textarea :maxlength="-1" :auto-height="true" :adjust-position="true" confirm-type="send" :cursor-spacing="10"
:selection-start="selectionStart" :selection-end="selectionEnd" class="chat-send btnt" :class="{displaynone:isrecord}"
@confirm="sendMsg" @input="inputs" @focus="focus" v-model="msg"></textarea>
<view class="record btn" :class="{displaynone:!isrecord}" @touchstart="touchstart" @touchend="touchend"
@touchmove="touchmove">
按住说话
</view>
<view class="bt-img" @tap="emoji">
<image src="../../static/icon/emote.png"></image>
</view>
<view v-if="ifmore" class="bt-img" @tap="more">
<image src="../../static/icon/more.png"></image>
</view>
<u-button v-if="!ifmore" @tap="sendMsg" style="background-color: #89965f; width: 88rpx;color: #fff;border-radius: 10rpx;">发送</u-button>
</view>
<!-- 表情框 -->
<view class="emoji" :class="{displaynone:!isemoji}">
<view class="emoji-send">
<!-- <view class="emoji-send-det" @tap="emojiBack">
<image src="../../static/icon/emote.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/icon/image.png"></image>
<view class="more-list-title">图片</view>
</view>
<view class="more-list" @tap="sendImg('camera')">
<image src="../../static/icon/photo.png"></image>
<view class="more-list-title">拍照</view>
</view>
<!-- <view class="more-list" @tap="choseLocation">
<image src="../../static/icon/location.png"></image>
<view class="more-list-title">定位</view>
</view> -->
<view class="more-list" @click="chooseVideo()">
<image src="../../static/icon/video.png"></image>
<view class="more-list-title">拍摄视频</view>
</view>
<!-- <view class="more-list">
<image src="../../static/icon/file.png"></image>
<view class="more-list-title">文件</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>
<u-toast ref="uToast" />
</view>
</template>
<script>
// 引入表情组件
import emoji from '../emoji/emoji.vue'
// 录音
const recorderManager = uni.getRecorderManager();
export default {
components: {
emoji,
},
data() {
return {
isrecord: false,
isemoji: false,
ismore: false,
ifmore: true,
voicebg: false,
pageY: 0,
msg: "",
// 直接引用地址可能出不来需要用require
toc: require('../../static/icon/voice.png'),
timer: '', //计时器
vlength: 0,
selectionStart: 0,
selectionEnd: 0
};
},
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 = require("../../static/icon/voice.png");
} else {
this.isrecord = true;
this.toc = require("../../static/icon/keyboard.png");
}
},
// 表情
emoji() {
console.log('emoji')
this.isemoji = !this.isemoji;
//切换的时候关闭其功能
this.ismore = false
this.isrecord = false;
this.toc = require("../../static/icon/voice.png");
//切换高度
setTimeout(() => {
this.getElementHeight();
}, 10)
},
//接收表情
emotion(e) {
console.log(e),
this.msg = this.msg + e
},
//文字发送
sendMsg(e) {
console.log(e.detail.value,this.msg)
// var chatm = e.detail.value;
// var pos = chatm.indexOf('\n');
this.updateCursor();
// 检索字符串没有数据,返回-1
// if (pos != -1 && chatm.length > 1) {
// this.$emit('inputs', this.msg);
// setTimeout(() => {
// this.msg = '';
// }, 0)
// }
if (this.msg.length > 1) {
// 0为表情和文字
this.send(this.msg, 'txt');
this.ifmore=true;
}
},
inputs(e) {
var chatm = e.detail.value;
if (chatm.length > 1) {
this.ifmore=false;
}
else{
this.ifmore=true;
}
},
updateCursor() {
// 当 text 改变时,将光标移动到最后
this.selectionStart = this.msg.length;
this.selectionEnd = this.msg.length;
},
// 输入框聚焦
focus() {
console.log('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, 'txt')
}
},
// 表格退格
emojiBack() {
if (this.msg.length > 0) {
this.msg = this.msg.substring(0, this.msg.length - 1);
}
},
//更多功能
more() {
console.log('more')
this.ismore = !this.ismore;
//切换的时候关闭其他界面
this.isemoji = false
this.isrecord = false;
this.toc = require("../../static/icon/voice.png");
setTimeout(() => {
this.getElementHeight();
}, 10)
},
// 视频录像
chooseVideo(){
var that =this;
uni.chooseVideo({
sourceType: ['camera', 'album'],
maxDuration: 60, // 最大视频录制时长(秒)
success: function (res) {
console.log('选择视频成功,返回的参数:', res);
// 可以使用 res.tempFilePath 获取视频的本地路径
const filePath = res.tempFilePath;
console.log(filePath);
if(that.checkImageSize(filePath)){
that.send(filePath, 'video');
}
else{
that.$refs.uToast.show({
title: "视频大小不能超过20M...",
type: "error",
duration: 2000,
});
}
},
fail: function (err) {
console.error('选择视频失败:', err);
}
});
},
//图片发送
sendImg(e) {
let count = 9;
if (e == 'album') {
count = 9;
} else {
count = 1;
}
uni.chooseImage({
count: count, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: [e], //从相册选择
// success: function (res) { //用function的方式会找不到send方法
success: (res) => {
console.log(JSON.stringify(res.tempFilePaths));
const filePaths = res.tempFilePaths;
for (let i = 0; i < filePaths.length; i++) {
if(this.checkImageSize(filePath)){
this.send(filePaths[i], 'image')
}
else{
this.$refs.uToast.show({
title: "图片大小不能超过20M...",
type: "error",
duration: 2000,
});
}
}
}
});
},
checkImageSize(filePath) {
var ifsize= 0;
uni.getFileInfo({
filePath: filePath,
success: function (res) {
console.log('文件大小(字节):', res.size);
if (res.size > 20*1024 * 1024) { // 例如这里检查文件大小是否超过20MB
console.log('文件过大');
// 可以根据需要处理文件过大的情况,比如提示用户
ifsize=0;
} else {
console.log('文件大小合适');
// 处理正常的文件大小情况
ifsize=1;
}
return ifsize;
},
fail: function (err) {
console.error('获取文件信息失败:', err);
return ifsize;
}
});
},
//音频处理
//开始录音
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++;
//结束计时
if (i > 60) {
clearInterval(this.timer);
this.touchend();
}
}, 1000)
recorderManager.start();
},
//删除录音
touchmove(e) {
// console.log("滑动到的y轴高度",e.changedTouches[0].pageY);
if (this.pageY - e.changedTouches[0].pageY > 100) {
// 关闭录音界面
this.voicebg = false;
}
},
// 结束录音
touchend() {
console.log("结束录音")
clearInterval(this.timer);
recorderManager.stop();
// recorderManager.onStop(function(res) {
recorderManager.onStop((res) => {
if(this.vlength<1){
this.$refs.uToast.show({
title: "...",
type: "warning",
duration: 2000,
});
}
else{
let data = {
voice: res.tempFilePath,
time: this.vlength
}
if (this.voicebg) {
this.send(data, 'audio');
}
}
// //
this.vlength = 0;
this.voicebg = false;
console.log('recorder stop' + JSON.stringify(res));
// self.voicePath = res.tempFilePath;
});
},
//
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);
// console.log('位置名称:' + res.name);
// console.log('详细地址:' + res.address);
// console.log('纬度:' + res.latitude);
// console.log('经度:' + res.longitude);
}
});
},
//发送
send(msg, type) {
console.log(msg, type)
let date = {
message: msg,
type: type
}
this.$emit('inputs', date);
setTimeout(() => {
this.msg = '';
}, 0)
}
}
};
</script>
<style lang="scss" scoped>
.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: 999;
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 20rpx;
image {
width: 56rpx;
height: 56rpx;
margin: 0 10rpx;
flex: auto;
}
.btnt {
flex: auto;
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
max-height: 240rpx;
margin: 0 10rpx;
overflow-y: 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: 150rpx;
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%;
min-height: 220rpx;
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: 90rpx;
height: 90rpx;
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: #89965f;
border-radius: 42rpx;
color:#ffffff;
}
.voice-del {
position: absolute;
bottom: -480rpx;
width: 100%;
text-align: center;
color: #fff;
font-size: 28rpx;
}
}
</style>