This commit is contained in:
cansnow
2025-12-11 22:33:31 +08:00
parent 375917f06c
commit 5a086fa1fa
44 changed files with 1978 additions and 359 deletions
@@ -15,7 +15,7 @@
</view>
</view>
<u-row class="action_row" v-else>
<u-col v-for="item in actionList" :key="item.idx" @click="actionClick(item)" span="3">
<u-col v-for="(item,idx) in actionList" :key="idx" @click="actionClick(item)" span="3">
<view class="action_item">
<image class="img" :src="item.icon" alt="" srcset="" />
<text class="action_item_title">{{ item.title }}</text>
@@ -28,10 +28,11 @@
<script>
import {ChatingFooterActionTypes,} from "@/constant";
import emojis from "@/common/emojis.js"
import chating_action_image from "@/static/images/chating_action_image.png";
import chating_action_camera from "@/static/images/chating_action_camera.png";
import chating_action_call from "@/static/images/chating_action_call.png";
import chating_action_location from "@/static/images/chating_action_location.png";
import chating_action_image_img from "@/static/images/chat/action_bar/image.png";
import chating_action_camera_img from "@/static/images/chat/action_bar/camera.png";
import chating_action_call_img from "@/static/images/chat/action_bar/call.png";
import chating_action_location_img from "@/static/images/chat/action_bar/location.png";
import chating_action_file_img from "@/static/images/chat/action_bar/file.png";
export default {
props:{
@@ -50,37 +51,36 @@
emojiList:emojis,
actionList: [
{
idx: 0,
type: ChatingFooterActionTypes.Album,
title: "照片",
icon: chating_action_image,
icon: chating_action_image_img,
},
{
idx: 1,
type: ChatingFooterActionTypes.Camera,
title: "拍摄",
icon: chating_action_camera,
icon: chating_action_camera_img,
},
{
idx: 2,
type: ChatingFooterActionTypes.Video,
type: ChatingFooterActionTypes.Call,
title: "视频通话",
icon: chating_action_call,
icon: chating_action_call_img,
},
{
idx: 3,
type: ChatingFooterActionTypes.Location,
title: "位置",
icon: chating_action_location,
icon: chating_action_location_img,
},
// {
// idx: 0,
// type: "File",
// title: "文件",
// icon: chating_action_file_img,
// },
// {
// type: ChatingFooterActionTypes.Album,
// title: "红包",
// icon: chating_action_image,
// },
// {
// idx: 0,
// type: ChatingFooterActionTypes.Album,
// title: "转账",
// icon: chating_action_image,
@@ -98,21 +98,24 @@
this.$emit("onUserEvent",{type:"clearSendStr"});
},
async emojiClick(emoji){
this.$emit("prepareMediaMessage", 'emoji',emoji);
this.$emit("onUserEvent", {type:'insertEmoji', emoji:emoji});
},
async actionClick(action) {
switch (action.type) {
case ChatingFooterActionTypes.Video:
this.$emit("prepareMediaMessage", action.type);
break;
case ChatingFooterActionTypes.Album:
this.$emit("prepareMediaMessage", action.type);
this.$emit("onUserEvent",{type:"prepend_image_message",source:"album"});
break;
case ChatingFooterActionTypes.Camera:
this.$emit("prepareMediaMessage", action.type);
this.$emit("onUserEvent",{type:"prepend_image_message",source:"camera"});
break;
case ChatingFooterActionTypes.Call:
this.$emit("onUserEvent",{type:"prepend_call_message"});
break;
case "File":
this.$emit("onUserEvent",{type:"prepend_file_message"});
break;
case ChatingFooterActionTypes.Location:
this.$emit("prepareMediaMessage", action.type);
this.$emit("onUserEvent",{type:"prepend_location_message"});
break;
default:
break;
@@ -29,16 +29,14 @@
<button class="send_btn" type="primary" v-show="hasContent" @touchend.prevent="sendTextMessage">发送</button>
</view>
</view>
<chating-action-bar :isEmoji="isEmoji"
@sendMessage="sendMessage($event,storeCurrentConversation.userID,storeCurrentConversation.groupID)"
@prepareMediaMessage="prepareMediaMessage"
<chating-action-bar
:isEmoji="isEmoji"
@onUserEvent="onUserEvent"
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>
<!-- 录音动画 -->
<!-- #ifdef APP-PLUS -->
<view class="voice_an" v-if="recording">
@@ -61,7 +59,7 @@
<script>
import {mapGetters,mapActions} from "vuex";
import {getPurePath,html2Text} from "@/util/common";
import {getPurePath,html2Text,getVideoCover,getVideoInfo} from "@/util/common";
import {offlinePushInfo} from "@/util/imCommon";
import {ChatingFooterActionTypes,UpdateMessageTypes,} from "@/constant";
import IMSDK, {IMMethods,MessageStatus,MessageType,} from "openim-uniapp-polyfill";
@@ -75,12 +73,12 @@
const rtcChoose = [
{
name: "视频通话",
type: ChatingFooterActionTypes.Video,
type: 'video',
idx: 0,
},
{
name: "语言通话",
type: ChatingFooterActionTypes.Voice,
type: 'voice',
idx: 1,
},
];
@@ -109,6 +107,8 @@
actionSheetMenu: [],
showActionSheet: false,
isInsertingEmoji: false, // 标记是否正在插入表情
fileSelectedArray:[]
};
},
computed: {
@@ -163,12 +163,14 @@
offlinePushInfo,
})
.then(({data}) => {
console.log(data);
this.updateOneMessage({
message: data,
isSuccess: true,
});
})
.catch(({data,errCode,errMsg}) => {
console.log(errCode,errMsg);
uni.$u.toast(errMsg);
this.updateOneMessage({
message: data,
@@ -227,136 +229,54 @@
// SimpleEditor 返回的是纯文本,直接使用
this.inputHtml = e.detail.value || e.detail.text || e.detail.html || "";
},
prepareMediaMessage(type,extra) {
console.log(type,extra)
if (type === ChatingFooterActionTypes.Video) {
this.actionSheetMenu = [...rtcChoose];
this.showActionSheet = true;
}
if (type === ChatingFooterActionTypes.Album) {
this.chooseOrShotImage(["album"]).then((paths) =>
this.batchCreateImageMesage(paths)
);
}
if (type === ChatingFooterActionTypes.Camera) {
this.chooseOrShotImage(["camera"]).then((paths) =>
this.batchCreateImageMesage(paths)
);
}
if (type === ChatingFooterActionTypes.Location) {
uni.chooseLocation({
complete(res) {
console.log(res);
},
fail(res) {
console.log(res);
}
//latitude:1,
//longitude:1,
})
}
if (type === "emoji") {
//TODO 在光标处插入文字extra
//editorContext.insertImage(
// 标记正在插入表情(先设置标志,保护表情栏不被隐藏)
this.isInsertingEmoji = true;
// 确保表情栏显示(只在真正需要时才更新状态,避免不必要的响应式触发)
const wasVisible = this.actionBarVisible;
const wasEmoji = this.isEmoji;
if (!wasVisible || !wasEmoji) {
// 只有在需要时才更新状态,减少响应式触发
if (!wasVisible) {
this.actionBarVisible = true;
}
if (!wasEmoji) {
this.isEmoji = true;
}
}
// 直接插入文本,不等待 nextTick,减少延迟
this.$refs.customEditor.insertText(extra,() =>{
console.log("插入文字成功");
// 延迟重置标志,确保其他事件不会隐藏表情栏
setTimeout(() => {
this.isInsertingEmoji = false;
}, 300);
},(err) => {
console.log("插入文字失败", err);
this.isInsertingEmoji = false;
});
}
},
// from comp
batchCreateImageMesage(paths) {
/*
createAdvancedTextMessage
createTextAtMessage
createLocationMessage
createTextMessage
createCustomMessage
createQuoteMessage
createAdvancedQuoteMessage
createCardMessage
createImageMessage
createImageMessage
createImageMessageByURL
createSoundMessage
createSoundMessageFromFullPath
createSoundMessageByURL
createVideoMessage
createVideoMessageFromFullPath
createVideoMessageByURL
createFileMessage
createFileMessageFromFullPath
createFileMessageByURL
createMergerMessage
createFaceMessage
createForwardMessage
*/
paths.forEach(async (path) => {
const message = await IMSDK.asyncApi(
IMMethods.CreateImageMessageFromFullPath,
IMSDK.uuid(),
getPurePath(path)
);
this.sendMessage(message,this.storeCurrentConversation.userID,this.storeCurrentConversation.groupID);
sendMediaMesage(paths) {
const _this = this;
paths.forEach(async (item) => {
try {
let message = null;
if(item.search('.mp4')>0){
const realVideoPath = await getPurePath(item);
console.log('处理后的可用路径', realVideoPath);
const info = await getVideoInfo(realVideoPath);
const cover = await getVideoCover(item);
const videoParams = {
videoPath: realVideoPath,
videoType: "mp4",
duration: info.duration,
snapshotPath: getPurePath(cover),
};
console.log('videoParams', videoParams);
message = await IMSDK.asyncApi(
IMMethods.CreateVideoMessageFromFullPath,
IMSDK.uuid(),
videoParams
);
}else{
message = await IMSDK.asyncApi(
IMMethods.CreateImageMessageFromFullPath,
IMSDK.uuid(),
getPurePath(item)
);
}
console.log(message);
if(message){
_this.sendMessage(message,_this.storeCurrentConversation.userID,_this.storeCurrentConversation.groupID);
}
} catch (error) {
console.log(error);
}
});
},
selectClick({idx}) {
if (idx === 0) {
uni.$u.toast('根据相关政策,暂时禁用视频通话');
//发送视频通话
// this.chooseOrShotImage(["album"]).then((paths) =>
// this.batchCreateImageMesage(paths)
// );
} else {
uni.$u.toast('根据相关政策,暂时禁用音频通话');
//发送音频通话
// this.chooseOrShotImage(["camera"]).then((paths) =>
// this.batchCreateImageMesage(paths)
// );
}
},
chooseOrShotImage(sourceType) {
return new Promise((resolve, reject) => {
uni.chooseImage({
count: 9,
sizeType: ["compressed"],
sourceType,
success: function({tempFilePaths}) {
resolve(tempFilePaths);
},
fail: function(err) {
console.log(err);
reject(err);
},
});
});
},
// keyboard
keyboardChangeHander({height}) {
//console.log(height);
@@ -503,6 +423,7 @@
},
/*-------------------------------------录音相关方法块 end---------------------------------------------------*/
onUserEvent(e){
const _this = this;
switch(e.type){
case "clearSendStr":
this.$refs.customEditor.clear();
@@ -510,8 +431,107 @@
case "delSendStr":
this.$refs.customEditor.delete();
break;
case "insertEmoji":
//TODO 在光标处插入文字extra
//editorContext.insertImage(
// 标记正在插入表情(先设置标志,保护表情栏不被隐藏)
this.isInsertingEmoji = true;
// 确保表情栏显示(只在真正需要时才更新状态,避免不必要的响应式触发)
const wasVisible = this.actionBarVisible;
const wasEmoji = this.isEmoji;
if (!wasVisible || !wasEmoji) {
// 只有在需要时才更新状态,减少响应式触发
if (!wasVisible) {
this.actionBarVisible = true;
}
if (!wasEmoji) {
this.isEmoji = true;
}
}
// 直接插入文本,不等待 nextTick,减少延迟
this.$refs.customEditor.insertText(e.emoji,() =>{
console.log("插入文字成功");
// 延迟重置标志,确保其他事件不会隐藏表情栏
setTimeout(() => {
this.isInsertingEmoji = false;
}, 300);
},(err) => {
console.log("插入文字失败", err);
this.isInsertingEmoji = false;
});
break;
case "prepend_image_message":
if(e.source == "camera"){
var cmr = plus.camera.getCamera();
cmr.captureImage((src) =>{
_this.sendMediaMesage([plus.io.convertLocalFileSystemURL(src)]);
}, (err) =>{
console.log(err);
}, {
filename:"_doc/camera/"
});
return ;
}
if(e.source == "album"){
plus.gallery.pick(({files})=>{
_this.sendMediaMesage(files);
}, (error )=>{
reject(error);
}, {
animation:true,
confirmText:"确定",
//crop:null,
editable:true,
filename:"_doc/",
filter:"none",
maximum:9,
multiple:true,
permissionAlert:true,
//popover:{},
//selected:[""],
onmaxed(){
console.log("超出最大选择数");
},
});
}
break;
case "prepend_call_message":
this.actionSheetMenu = [...rtcChoose];
this.showActionSheet = true;
break;
case "prepend_file_message":
uni.chooseFile({
count:9,
multiple: true,
success: (res) => {
console.log('选择文件成功', res);
//const filePaths = res.tempFiles.map(file => file.path);
//_this.sendMediaMesage(filePaths);
},
fail: (err) => {
console.log('选择文件失败', err);
}
});
break;
case "prepend_location_message":
uni.chooseLocation({
complete(res) {
console.log(res);
},
fail(res) {
console.log(res);
}
//latitude:1,
//longitude:1,
});
break;
default:
console.log(e);
break;
}
console.log(e);
}
},
};