This commit is contained in:
cansnow
2025-12-02 03:05:52 +08:00
parent b4c9ae1b67
commit 29be534f22
24 changed files with 1118 additions and 372 deletions
@@ -1,6 +1,28 @@
<template>
<view class="chat_action_bar">
<u-row class="action_row">
<view class="fun-box u-border-top show-fun-box" v-if="isEmoji">
<swiper class="emoji-swiper" :indicator-dots="true" :duration="50" :circular="true">
<swiper-item v-for="(page,index1) in Math.ceil(emojiList.length/pagesize)" :key="index1">
<view @tap="emojiClick(emojiList[pagesize*(page-1)+n])" v-for="(n,index2) in pagesize" :key="index2">
{{emojiList[pagesize*(page-1)+n]}}
</view>
</swiper-item>
</swiper>
<view style="padding:0rpx 20rpx;position: absolute;bottom: 1rpx;right: 10rpx;
width: 250rpx;height: 150rpx;z-index: 1000;opacity: 0.9;" class="u-flex u-row-right u-col-center">
<view class="u-flex u-row-center u-col-center"
style="border: 1px solid #f1f1f1;border-radius: 10rpx; background-color: #82848a;width: 100rpx;padding: 15rpx 20rpx;margin-right: 8rpx;">
<view @click="delSendStr()" @longpress="clearSendStr()">
<u-icon name="backspace" size="46" color="#ffffff"></u-icon>
</view>
</view>
<!-- <view>
<u-button @click="$noClicks(sendText)" type="success" :custom-style="{padding:'20rpx'}">发送
</u-button>
</view> -->
</view>
</view>
<u-row class="action_row" v-else>
<u-col v-for="item in actionList" :key="item.idx" @click="actionClick(item)" span="3">
<view class="action_item">
<image :src="item.icon" alt="" srcset="" />
@@ -13,11 +35,25 @@
<script>
import {ChatingFooterActionTypes,} from "@/constant";
import emojis from "@/common/emojis.js"
export default {
components: {},
props:{
isEmoji:{
type:Boolean,
default:false
}
},
watch:{
isEmoji(v){
console.log(v);
this.emojiMode = v;
}
},
data() {
return {
pagesize:24,
emojiList:emojis,
actionList: [
{
idx: 0,
@@ -29,19 +65,19 @@
idx: 1,
type: ChatingFooterActionTypes.Camera,
title: "拍摄",
icon: require("static/images/chating_action_image.png"),
icon: require("static/images/chating_action_camera.png"),
},
{
idx: 2,
type: ChatingFooterActionTypes.Video,
title: "视频通话",
icon: require("static/images/chating_action_image.png"),
icon: require("static/images/chating_action_call.png"),
},
{
idx: 3,
type: ChatingFooterActionTypes.Location,
title: "位置",
icon: require("static/images/chating_action_image.png"),
icon: require("static/images/chating_action_location.png"),
},
// {
// idx: 0,
@@ -59,6 +95,11 @@
};
},
methods: {
delSendStr(){},
clearSendStr(){},
async emojiClick(emoji){
this.$emit("prepareMediaMessage", 'emoji',emoji);
},
async actionClick(action) {
switch (action.type) {
case ChatingFooterActionTypes.Video:
@@ -84,7 +125,7 @@
<style lang="scss" scoped>
.chat_action_bar {
position: relative;
background: #f0f2f6;
background: #ececec;
padding: 24rpx 36rpx;
.action_row {
@@ -108,5 +149,29 @@
margin-top: 6rpx;
}
}
.emoji_row{
.emoji{
}
}
.emoji-swiper {
height: 400rpx;
swiper-item {
display: flex;
align-content: flex-start;
flex-wrap: wrap;
view {
width: 12%;
height: 16vw;
font-size: 48rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
</style>
@@ -2,25 +2,56 @@
<view>
<view>
<view class="chat_footer">
<!-- 语音信息 -->
<image v-if="1==2" v-show="!isAudio" @click.prevent="isAudio=!isAudio"
src="@/static/images/chating_footer_audio.png" alt="" srcset="" />
<image v-if="1==2" v-show="isAudio" @click.prevent="isAudio=!isAudio"
src="@/static/images/chating_footer_audio_recording.png" alt="" srcset="" />
<view class="input_content">
<CustomEditor class="custom_editor" ref="customEditor" @ready="editorReady" @focus="editorFocus"
<!-- #ifdef APP-PLUS -->
<view v-if="isAudio" class="voice_title" @touchstart.stop.prevent="startVoice"
@touchmove.stop.prevent="moveVoice" @touchend.stop="endVoice"
@touchcancel.stop="cancelVoice" :style="{ background: recording ? '#c7c6c6' : '#FFFFFF' }">
<text>{{ voiceTitle }}</text>
</view>
<!-- #endif -->
<CustomEditor v-if="!isAudio" class="custom_editor" ref="customEditor" @ready="editorReady" @focus="editorFocus"
@blur="editorBlur" @input="editorInput" />
</view>
<view class="footer_action_area">
<view class="footer_action_area" v-show="!isAudio">
<image class="emoji_action" @click.prevent="updateActionBar(true)"
src="@/static/images/chating_footer_emoji.png" alt="" srcset="" />
<image v-show="!hasContent" @click.prevent="updateActionBar"
src="@/static/images/chating_footer_add.png" alt="" srcset="" />
<image v-show="hasContent" @touchend.prevent="sendTextMessage" src="@/static/images/send_btn.png"
alt="" srcset="" />
<button class="send_btn" type="primary" v-show="hasContent" @touchend.prevent="sendTextMessage">发送</button>
</view>
</view>
<chating-action-bar @sendMessage="sendMessage" @prepareMediaMessage="prepareMediaMessage"
<chating-action-bar :isEmoji="isEmoji" @sendMessage="sendMessage" @prepareMediaMessage="prepareMediaMessage"
v-show="actionBarVisible" />
<u-action-sheet :safeAreaInsetBottom="true" round="12" :actions="actionSheetMenu" @select="selectClick"
:closeOnClickOverlay="true" :closeOnClickAction="true" :show="showActionSheet"
@close="showActionSheet = false">
</u-action-sheet>
</view>
<!-- 录音动画 -->
<!-- #ifdef APP-PLUS -->
<view class="voice_an" v-if="recording">
<view class="voice_an_icon">
<view id="one" class="wave"></view>
<view id="two" class="wave"></view>
<view id="three" class="wave"></view>
<view id="four" class="wave"></view>
<view id="five" class="wave"></view>
<view id="six" class="wave"></view>
<view id="seven" class="wave"></view>
</view>
<view class="text">
<text>{{voiceIconText}}</text>
</view>
</view>
<!-- #endif -->
</view>
</template>
@@ -60,6 +91,12 @@
},
data() {
return {
recording:false,
sendMsgTimmer: null, //发送时间定时器
sendDuring: 0, //发送时间计数器 1分钟以内的信息不显示时间
sendTimeBetween: 60, //发送信息显示的间隔,60秒以内信息不显示发送时间
isEmoji:false,
isAudio:false,
customEditorCtx: null,
inputHtml: "",
actionBarVisible: false,
@@ -143,15 +180,25 @@
});
});
},
recordAudioMsg(){
if (uni.getSystemInfoSync().platform == "android") {
permission.requestAndroid("android.permission.RECORD_AUDIO"); //Android请求录音权限
} else {
permission.requestIOS("record"); //ios请求录音权限
}
},
// action
onClickActionBarOutside() {
if (this.actionBarVisible) {
this.actionBarVisible = false;
}
},
updateActionBar() {
updateActionBar(isEmoji) {
this.actionBarVisible = !this.actionBarVisible;
console.log(this.isEmoji);
this.isEmoji = !!isEmoji;
console.log(this.isEmoji);
},
editorReady(e) {
this.customEditorCtx = e.context;
@@ -167,7 +214,7 @@
editorInput(e) {
this.inputHtml = e.detail.html;
},
prepareMediaMessage(type) {
prepareMediaMessage(type,extra) {
console.log(type)
if (type === ChatingFooterActionTypes.Video) {
this.actionSheetMenu = [...rtcChoose];
@@ -195,6 +242,18 @@
//longitude:1,
})
}
if (type === "emoji") {
//TODO 在光标处插入文字extra
this.customEditorCtx.insertText({
text: extra,
success: () => {
console.log("插入文字成功");
},
fail: (err) => {
console.log("插入文字失败", err);
}
});
}
},
// from comp
@@ -279,6 +338,133 @@
disposeKeyboardListener() {
uni.offKeyboardHeightChange(this.keyboardChangeHander);
},
/*----------------------------------------------------H5不支持)录音相关 start-------------------------------------- */
//准备开始录音
startVoice(e) {
if (!this.Audio.paused) {
//如果音频正在播放 先暂停。
this.stopAudio(this.AudioExam)
}
this.recording = true;
this.isStopVoice = false;
this.voiceCanSend = true;
this.voiceIconText = "正在录音..."
this.PointY = e.touches[0].clientY;
this.Recorder.start({
format: 'mp3'
});
},
//录音已经开始
beginVoice() {
let that = this;
if (that.isStopVoice) {
that.Recorder.stop();
return;
}
that.voiceTitle = '松开 结束'
that.voiceInterval = setInterval(() => {
console.log("that.voiceTime", that.voiceTime);
if (that.voiceTime > 49) {
that.voiceIconText = "录音结束倒计时[" + (60 - that.voiceTime) + "]s";
};
if (that.voiceTime == 60) {
clearInterval(that.voiceInterval);
that.endVoice();
}
that.voiceTime++;
}, 1000)
},
//move 正在录音中
moveVoice(e) {
const PointY = e.touches[0].clientY;
const slideY = this.PointY - PointY;
if (slideY > uni.upx2px(120)) {
this.voiceCanSend = false;
this.voiceIconText = '松开手指 取消发送 '
} else if (slideY > uni.upx2px(60)) {
this.voiceCanSend = true;
this.voiceIconText = '手指上滑 取消发送 '
} else {
this.voiceIconText = '正在录音... '
}
},
//结束录音
endVoice() {
this.isStopVoice = true; //加锁 确保已经结束录音并不会录制
this.Recorder.stop();
this.voiceTitle = '按住 说话'
},
//录音被打断
cancelVoice(e) {
console.log("路由被打断", e);
this.voiceTime = 0;
this.voiceTitle = '按住 说话';
this.voiceCanSend = false;
this.Recorder.stop();
},
//处理录音文件
handleRecorder({tempFilePath,duration }) {
if (this.voiceTime < 1) {
this.voiceIconText = "说话时间过短";
setTimeout(() => {
this.recording = false;
}, 500)
return;
}
let contentDuration = this.voiceTime;
this.voiceTime = 0;
this.recording = false;
clearInterval(this.voiceInterval);
console.log("录音文件", tempFilePath);
console.log("是否发送语音信息", this.voiceCanSend);
let voiceFile = {
tempFilePath: tempFilePath,
contentDuration: Math.ceil(contentDuration),
anmitionPlay: false,
};
if (this.voiceCanSend) {
console.log("=====上传语音文件,并发送语音信息====");
let audioType = this.messageApi.CONTENT_TYPE.AUDIO_CONTENT_TYPE;
this.uploadFile(voiceFile, audioType);
return;
} else {
console.log("=====已经取消发送语音信息====")
return;
}
},
//控制播放还是暂停音频文件
handleAudio(item) {
this.AudioExam = item;
this.Audio.paused ? this.playAudio(item) : this.stopAudio(item);
},
//播放音频
playAudio(item) {
let target = item.content.fileSaveTarget;
let src = item.content.fullPath;
if (target == "local") {
src = this.$u.api.multipartAddress.getFileByPath + src;
}
this.Audio.src = src;
this.Audio.hasBeenSentId = item.id;
this.Audio.play();
let currentAudioMsg = this.messageList.find(it => it.id == item.id);
currentAudioMsg.content.anmitionPlay = true;
},
//停止音频
stopAudio(item) {
let currentAudioMsg = this.messageList.find(it => it.id == item.id);
currentAudioMsg.content.anmitionPlay = false;
this.Audio.src = '';
this.Audio.stop();
},
//关闭动画
closeAnmition() {
const hasBeenSentId = this.Audio.hasBeenSentId;
let item = this.messageList.find(it => it.id == hasBeenSentId);
item.content.anmitionPlay = false;
},
/*-------------------------------------录音相关方法块 end---------------------------------------------------*/
},
};
</script>
@@ -303,9 +489,9 @@
.chat_footer {
display: flex;
align-items: center;
align-items: flex-end;
// background-color: #e9f4ff;
background: #f0f2f6;
background: #f6f6f6;
// height: 50px;
max-height: 120px;
padding: 24rpx 20rpx;
@@ -361,7 +547,7 @@
.send_btn {
height: 30px;
line-height: 30px;
background-color: #4a9cfc;
background-color: $uni-color-success;
padding: 0 8px;
border-radius: 4px;
color: #fff;