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.
1405 lines
42 KiB
1405 lines
42 KiB
<template name="im-input">
|
|
<view id="more-oprate">
|
|
<view class="im-container bg-gray" :style="[{paddingBottom:paddingB+'px',minHeight:InputBottom==0?'auto':InputBottom+50+ 'px'}]"><!-- bottom:footerHeight+'px', -->
|
|
<view class="im-footer bg-gray" v-if="contactid!==-2">
|
|
<view class="im-menus f-28" v-show="!isFocus || contact.is_group!=1" style="margin-bottom: 8rpx;" :class="[recShow ? 'cuIcon-keyboard' : 'cuIcon-sound']" hover-class="tap" @tap="showRec"></view>
|
|
<view class="im-menus f-24" v-show="isFocus && contact.is_group==1" style="margin-bottom: 13rpx;" @tap="modelName='userModel'">@</view>
|
|
<view class="im-msgarea" style="flex: 0.97;width: 400rpx;">
|
|
<!-- im-flex1 -->
|
|
<editor id="editor" style="width: 100%;line-break: anywhere;" class="solid-bottom bg-white im-input c-333" :adjust-position="false" maxlength="300" cursor-spacing="10"
|
|
@focus="InputFocus" @blur="InputBlur" @input="changeMsgText" @ready="onEditorReady" :read-only="readOnly" v-show="recShow==false"> </editor>
|
|
<view class="toolBox" v-show="recShow==true">
|
|
<view class="recorder" :class="{active:isUseRecorder}" @touchstart.prevent="startRecorder"
|
|
@touchend.prevent="endRecorder" @touchmove.prevent="moveRecorder" @touchcancel="cancelRecorder">
|
|
{{isUseRecorder ? '松开结束' : '按住说话'}}
|
|
</view>
|
|
</view>
|
|
<view class='im-flex im-space-between message-quote radius-6 im-align-items-center' v-if="quote">
|
|
<view class='text-overflow'>{{quote.content}}</view>
|
|
<view class="cuIcon-close" @tap="closeQuote"></view>
|
|
</view>
|
|
|
|
</view>
|
|
<mumu-recorder ref='recorderRef' @success='handlerSuccess' @error='handlerError' v-if="isH5"></mumu-recorder>
|
|
<view class="im-flex im-justify-content-start im-align-items-center" style="margin-bottom: 8rpx;" >
|
|
<view class="im-menus cuIcon-emoji f-28 ml-5" hover-class="tap" @tap="showAppBox(1)"></view>
|
|
<view class="im-menus cuIcon-roundadd f-28 mr-10" hover-class="tap" v-if="!inputMsg" @tap="showAppBox(2)"></view>
|
|
<view v-if="inputMsg" style="width: 140rpx;">
|
|
<button class="cu-btn bg-green shadow mr-10" @touchend.prevent="sendTextMsg">发送</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view v-else class="im-footer bg-gray">
|
|
<view class="im-flex1 im-msgarea mr-10 ml-10">
|
|
<editor id="editor" class="solid-bottom bg-white im-input c-333" :adjust-position="false" maxlength="300" cursor-spacing="10"
|
|
@focus="InputFocus" @blur="InputBlur" @input="changeMsgText" @ready="onEditorReady" :read-only="readOnly" v-show="recShow==false"> </editor>
|
|
</view>
|
|
<view class="im-flex im-justify-content-start im-align-items-center mr-10" style="margin-bottom: 15rpx;" >
|
|
<button class="cu-btn bg-green shadow" @click="sendTextMsg1" :disabled="isAnswering">发送</button>
|
|
</view>
|
|
</view>
|
|
<!-- 表情窗口 -->
|
|
<view class="im-flex im-columns im-emoji-box" :style="[{height:boxHeight+'px'}]" v-if="appBox==1">
|
|
<scroll-view scroll-x class="bg-gray nav im-emoji-header" scroll-with-animation :scroll-left="scrollLeft">
|
|
<view class="cu-item" :class="index==TabCur?'text-green':''" v-for="(item,index) in emojiList" :key="index" @tap="tabSelect" :data-id="index" :data-name="item.name">
|
|
<view :class="[item.icon]" class="f-20"></view>
|
|
</view>
|
|
</scroll-view>
|
|
<scroll-view scroll-y class="bg-white im-emoji-body">
|
|
<view class="im-flex im-wrap im-justify-content-start im-align-items-center pd-10" :class="emojiName=='favors'?' cu-list grid col-5':''">
|
|
<view v-if="emojiName=='favors'" class="im-emoji-item">
|
|
<view class="upload-emoji" @tap="uploadEmoji"><text class="cuIcon-add c-999" style="vertical-align: sub;"></text></view>
|
|
</view>
|
|
<view v-for="(item,index) in currentEmojiList" class="im-emoji-item" :key="index">
|
|
<!-- <block v-for="(iteme,indexe) in imglist" :key="indexe" v-if="network_log == 'none'">
|
|
<view v-if="iteme.name==item.name">
|
|
<image :src="iteme.path" style="width:100rpx;height:100rpx" mode="aspectFit" :fade-show="false" lazy-load @tap="chooseDiyEmoji(item)" v-if="emojiName=='favors'"></image>
|
|
<image :src="iteme.path" style="width:44rpx;;height:44rpx" mode="aspectFit" lazy-load @tap="chooseEmoji(item)" v-else></image>
|
|
</view>
|
|
</block>
|
|
<block v-else> -->
|
|
<image :src="item.src" style="width:100rpx;height:100rpx" mode="aspectFit" :fade-show="false" lazy-load @tap="chooseDiyEmoji(item)" v-if="emojiName=='favors'"></image>
|
|
<image :src="item.src" style="width:44rpx;;height:44rpx" mode="aspectFit" lazy-load @tap="chooseEmoji(item)" v-else></image>
|
|
<!-- </block> -->
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<!-- 工具栏窗口 -->
|
|
<view class="im-flex im-app-box im-flex im-justify-content-start im-wrap im-align-content-start pd-20" :style="[{height:boxHeight+'px'}]" v-if="appBox==2">
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" @tap="chooseImg">
|
|
<view class="bg-white cuIcon-album f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">照片</view>
|
|
</view>
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" @tap="chooseVideo">
|
|
<view class="bg-white cuIcon-video f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">视频</view>
|
|
</view>
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" @tap="chooseFile">
|
|
<view class="bg-white cuIcon-file f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">文件</view>
|
|
</view>
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" v-if='!contact.is_group && (isH5 || isApp) && parseInt(globalConfig.chatInfo.webrtc)' @tap="calling(0)">
|
|
<view class="bg-white cuIcon-dianhua f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">语音通话</view>
|
|
</view>
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" v-if='!contact.is_group && (isH5 || isApp) && parseInt(globalConfig.chatInfo.webrtc)' @tap="calling(1)">
|
|
<view class="bg-white cuIcon-record f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">视频通话</view>
|
|
</view>
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" @tap="chooseLocation">
|
|
<view class="bg-white cuIcon-location f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">位置</view>
|
|
</view>
|
|
<view class="im-flex im-columns im-align-items-center mt-10 im-app-item" @tap="modelName='contactModel'">
|
|
<view class="bg-white cuIcon-addressbook f-24 radius-10 im-app-item-icon"></view>
|
|
<view class="mt-5">名片</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="voice-model c-white radius-10 im-flex im-columns im-align-items-center pd-10" v-show="isUseRecorder">
|
|
<view class="cuIcon-voicefill mt-15 mb-5 f-28" :class="[isCancel ? 'c-red' : 'voice-icon']"></view>
|
|
<view :class="[isCancel ? 'c-red' : '']">
|
|
{{isCancel ? '松开取消' : '正在录音'}}
|
|
</view>
|
|
</view>
|
|
|
|
<view class="cu-modal bottom-modal" :class="modelName=='userModel'?'show':''" @tap="closeModel()">
|
|
<view class="cu-dialog" v-if="modelName=='userModel'">
|
|
<view class="cu-bar bg-white">
|
|
<view class="action text-gray" @tap="closeModel()">取消</view>
|
|
<view class="f-16">选择提醒的人</view>
|
|
<view class="action text-green" @tap="at()">完成</view>
|
|
</view>
|
|
<view class="manage-content" style="height:500px" @tap.stop=''>
|
|
<scroll-view style="height:500px" scroll-y="true">
|
|
<user-select v-if="contact.is_group==1" :type="4" :contact_id="contact.id" ref="userSelect" @setData="setAtList"></user-select>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="cu-modal bottom-modal" :class="modelName=='contactModel'?'show':''" @tap="closeModel()">
|
|
<view class="cu-dialog" v-if="modelName=='contactModel'">
|
|
<view class="cu-bar bg-white">
|
|
<view class="action text-gray" @tap="closeModel()">取消</view>
|
|
<view class="f-16">选择分享的联系人</view>
|
|
<view class="action text-green" @tap="sendContactCard()">完成</view>
|
|
</view>
|
|
<view class="manage-content" style="height:500px" @tap.stop=''>
|
|
<scroll-view style="height:500px" scroll-y="true">
|
|
<user-select :type="1" :multiple="false" :contact_id="contact.id" ref="contactSelect"></user-select>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
</template>
|
|
<script>
|
|
import MumuRecorder from '@/uni_modules/mumu-recorder/components/mumu-recorder/mumu-recorder.vue'
|
|
import userSelect from '@/components/message/user-select.vue';
|
|
import Edit from '@/utils/edit.js'
|
|
import emoji from '@/utils/emoji.js'
|
|
import { useMsgStore } from '@/store/message';
|
|
import { useloginStore } from '@/store/login';
|
|
import pinia from '@/store/index'
|
|
// #ifdef APP-PLUS
|
|
import {getSavedImages3} from '@/utils/LocalFileSystemURL.js'
|
|
// #endif
|
|
const msgStore = useMsgStore(pinia);
|
|
const userStore = useloginStore(pinia);
|
|
export default {
|
|
name : "im-input",
|
|
components: { MumuRecorder,userSelect },
|
|
props : {
|
|
boxStatus:{type:Number, default:0},
|
|
contactid:{type:Number, default:0},
|
|
contact:{type:Object, default:{}},
|
|
isAnswering:{type:Boolean, default:false}
|
|
},
|
|
data() {
|
|
return {
|
|
editorCtx:null,
|
|
InputBottom : 0,
|
|
paddingB : 0,
|
|
footerHeight : 50,
|
|
boxHeight : 300,
|
|
uploading : false,
|
|
recShow : false,
|
|
inputMsg : "",
|
|
recorderManager : null,
|
|
recing : false,
|
|
recLength : 1,
|
|
recTimer : null,
|
|
tmpVoice : '',
|
|
isUseRecorder: false,
|
|
playItemIndex: -1,
|
|
currentAudio: '',
|
|
mainHeight:0,
|
|
isCancel:false,
|
|
isH5:false,
|
|
isApp:false,
|
|
appBox:0,
|
|
TabCur: 0,
|
|
emojiName:'',
|
|
scrollLeft: 0,
|
|
emojiList:[],
|
|
currentEmojiList:[],
|
|
isFocus:false,
|
|
globalConfig:userStore.globalConfig,
|
|
userInfo:userStore.userInfo,
|
|
readOnly:false,
|
|
edit: null,
|
|
modelName:false,
|
|
isAt:false,
|
|
quote:'',
|
|
boardHeight:0,
|
|
inputMsg1:"",
|
|
network_log:'',
|
|
imglist:[],
|
|
FileImg:uni.getStorageSync('FileImg')
|
|
}
|
|
},
|
|
watch:{
|
|
boxStatus(val){
|
|
this.appBox=0;
|
|
this.InputBottom=0;
|
|
},
|
|
appBox(val){
|
|
// 如果没有打开应用盒子,输入框的高度设置为0;
|
|
if(val==0 && !this.isFocus){
|
|
this.InputBottom=0;
|
|
}
|
|
},
|
|
InputBottom(val){
|
|
this.$emit('setPad',val);
|
|
},
|
|
inputMsg1(val){
|
|
const text1 = val.replace(/<(\/?)(?!img\b)[^>]+>/g, '');
|
|
const hasImg = /<img\b[^>]*>/i.test(text1);
|
|
if(hasImg){
|
|
const imgSrcList = [];
|
|
const imgRegex = /<img\b[^>]*src=["']?([^"'>]+)["']?[^>]*>/gi;
|
|
let imgMatch;
|
|
while ((imgMatch = imgRegex.exec(text1)) !== null) {
|
|
imgSrcList.push(imgMatch[1]);
|
|
}
|
|
|
|
imgSrcList.forEach(src => {
|
|
this.editorCtx.insertImage({
|
|
src: src,
|
|
// alt: item.title,
|
|
width: 18,
|
|
height: 18,
|
|
nowrap:true,
|
|
extClass:'emoji-image',
|
|
success: ()=>{
|
|
},
|
|
});
|
|
})
|
|
}else{
|
|
this.editorCtx.insertText({
|
|
text: text1
|
|
})
|
|
}
|
|
|
|
// console.log(text1,'123');
|
|
}
|
|
},
|
|
created : function(){
|
|
// #ifndef H5
|
|
// 监听键盘高度
|
|
// uni.onKeyboardHeightChange(res => {
|
|
// if(this.appBox==0 || res.height>0){
|
|
// this.boardHeight=res.height;
|
|
// }
|
|
// })
|
|
// #endif
|
|
uni.$on('updateEmoji',(res) => {
|
|
this.getEmojiList()
|
|
})
|
|
this.currentEmojiList=emoji[0]['children'];
|
|
this.getEmojiList();
|
|
// #ifdef APP-PLUS
|
|
// this.downloadFileImg()
|
|
// #endif
|
|
uni.getSystemInfo({
|
|
success: res => {
|
|
let windowHeight = res.windowHeight;
|
|
this.mainHeight=windowHeight;
|
|
}
|
|
});
|
|
// #ifdef H5
|
|
this.isH5=true;
|
|
// this.paddingB=15;
|
|
// this.footerHeight=65;
|
|
// #endif
|
|
// #ifdef APP-PLUS
|
|
this.isApp=true;
|
|
// #endif
|
|
// #ifndef H5
|
|
this.isH5=false;
|
|
this.recorderManager = uni.getRecorderManager();
|
|
this.recorderManager.onStop((res) => {
|
|
this.tmpVoice = res.tempFilePath;
|
|
this.recing = false;
|
|
if(this.recLengt<1){
|
|
// 检测录音是否大于1秒
|
|
return this.checkRecorder(this.recLength);
|
|
}else{
|
|
// 发送语音消息
|
|
this.sendVoiceMsg();
|
|
}
|
|
});
|
|
this.recorderManager.onError(() => {
|
|
uni.showToast({ title: '录音失败', icon: 'none' });
|
|
this.recing = false;
|
|
});
|
|
// #endif
|
|
// #ifdef MP
|
|
try {
|
|
var res = uni.getSystemInfoSync();
|
|
res.model = res.model.replace(' ', '');
|
|
res.model = res.model.toLowerCase();
|
|
var res1 = res.model.indexOf('iphonex');
|
|
if(res1 > 5){res1 = -1;}
|
|
var res2 = res.model.indexOf('iphone1');
|
|
if(res2 > 5){res2 = -1;}
|
|
if(res1 != -1 || res2 != -1){
|
|
let paddingB = uni.upx2px(50);
|
|
this.paddingB =paddingB;
|
|
this.footerHeight=55+paddingB;
|
|
}
|
|
} catch (e){return null;}
|
|
// #endif
|
|
// this.network_log = uni.getStorageSync('network_log')
|
|
// if(this.network_log == 'none'){
|
|
// this.getImagePath()
|
|
// }
|
|
},
|
|
methods:{
|
|
updateKeyboardHeightChange(res){
|
|
if(this.appBox==0 || res.height>0){
|
|
this.boardHeight=res.height;
|
|
}
|
|
},
|
|
msgItem(){
|
|
return {
|
|
id:this.$util.getUuid(),
|
|
sendTime:new Date().getTime(),
|
|
status: "going",
|
|
type: "text",
|
|
content: "",
|
|
is_read: 0,
|
|
is_group: 0,
|
|
file_id: 0,
|
|
file_cate: 0,
|
|
fileName: "",
|
|
fileSize: 0,
|
|
extends: null,
|
|
isImageInserted: false
|
|
}
|
|
},
|
|
// 设置@提醒的人
|
|
at(){
|
|
this.isAt=true;
|
|
let data=this.$refs.userSelect.selectUser;
|
|
this.closeModel();
|
|
this.edit.addLink({
|
|
prefix: '@',
|
|
data:data
|
|
})
|
|
setTimeout(()=>{
|
|
this.getFocus();
|
|
},100)
|
|
},
|
|
// 设置@提醒的人
|
|
sendContactCard(){
|
|
let data=this.$refs.contactSelect.selectUser;
|
|
if(data.length!=1){
|
|
return uni.showToast({
|
|
icon:'none',
|
|
title:'必须选择一位联系人'
|
|
})
|
|
}
|
|
this.closeModel();
|
|
let contact=data[0];
|
|
let message={
|
|
type:'contact',
|
|
status:'going',
|
|
content:'[个人名片] '+contact.displayName,
|
|
extends:{
|
|
avatar:contact.avatar,
|
|
displayName:contact.displayName,
|
|
id:contact.id
|
|
}
|
|
};
|
|
this.$emit('send',Object.assign(this.msgItem(), message),false);
|
|
},
|
|
// 关闭弹窗
|
|
closeModel(){
|
|
if(this.modelName=="userModel"){
|
|
this.$refs.userSelect.selectUser=[];
|
|
this.$refs.userSelect.changeUser=[];
|
|
}
|
|
this.modelName='';
|
|
},
|
|
setAtList(item){
|
|
const val = {user_id:item.user_id,realname:item.realname?item.realname:item.realname1}
|
|
this.isAt=true;
|
|
this.closeModel();
|
|
this.edit.addLink({
|
|
prefix: '@',
|
|
data: item.avatar?val:item
|
|
})
|
|
},
|
|
// 编辑器获得焦点
|
|
getFocus(){
|
|
this.editorCtx.format('fontFamily', 'inherit');
|
|
this.isFocus=true;
|
|
},
|
|
chooseDiyEmoji(item){
|
|
let message={
|
|
type:'emoji',
|
|
content:item.src,
|
|
file_id:item.file_id,
|
|
status:'going'
|
|
}
|
|
this.$emit('send',Object.assign(this.msgItem(), message),false);
|
|
},
|
|
// 选择表情
|
|
chooseEmoji(item){
|
|
// #ifdef H5
|
|
this.editorCtx.insertImage({
|
|
src: item.src,
|
|
alt: item.title,
|
|
width: 18,
|
|
height: 18,
|
|
nowrap:true,
|
|
extClass:'emoji-image',
|
|
success: ()=>{
|
|
},
|
|
complete: ()=> {
|
|
this.editorCtx.blur();
|
|
this.showAppBox(1)
|
|
},
|
|
});
|
|
// #endif
|
|
// #ifndef H5
|
|
this.readOnly= true
|
|
setTimeout(()=>{
|
|
this.editorCtx.insertImage({
|
|
src: item.src,
|
|
alt: item.title,
|
|
width: 18,
|
|
height: 18,
|
|
nowrap:true,
|
|
extClass:'emoji-image',
|
|
success: function() {
|
|
},
|
|
complete: ()=> {
|
|
this.readOnly= false
|
|
},
|
|
});
|
|
},10);
|
|
// #endif
|
|
},
|
|
tabSelect(e) {
|
|
this.TabCur = e.currentTarget.dataset.id;
|
|
this.emojiName = e.currentTarget.dataset.name;
|
|
this.scrollLeft = (e.currentTarget.dataset.id - 1) * 60;
|
|
this.currentEmojiList=this.emojiList[this.TabCur]['children'];
|
|
},
|
|
showAppBox(val){
|
|
if(this.appBox==val){
|
|
this.appBox=0;
|
|
this.InputBottom=0;
|
|
}else{
|
|
this.appBox=val;
|
|
this.InputBottom=this.boxHeight;
|
|
this.recShow = false;
|
|
}
|
|
},
|
|
// 展示录音界面
|
|
showRec : function(){
|
|
this.InputBottom=0;
|
|
this.appBox=0;
|
|
this.recShow == true ? this.recShow = false : this.recShow = true
|
|
},
|
|
// 发送录音
|
|
sendVoiceMsg: function(){
|
|
if (this.tmpVoice == '') {
|
|
uni.showToast({ title: "录制已取消", icon: "none" });
|
|
return;
|
|
}
|
|
let res={
|
|
localUrl:this.tmpVoice,
|
|
duration:this.recLength
|
|
}
|
|
this.handlerSuccess(res);
|
|
this.tmpVoice = '';
|
|
this.recLength = 0;
|
|
},
|
|
// 发送文本消息
|
|
sendTextMsg: function () {
|
|
if(this.appBox!=1){
|
|
this.isFocus=true;
|
|
}
|
|
this.editorCtx.getContents({
|
|
success:(e)=>{
|
|
let msg=e.html;
|
|
let msg1=e.text.replace(/\n/g, ' ').trim();
|
|
const contentText = /^\s*$/.test(msg.replace(/<[^>]+>/g, ""));
|
|
const hasImg = /<img\b/i.test(msg);
|
|
// console.log('消息发送',msg);
|
|
|
|
let result = [];
|
|
// #ifdef H5
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(msg, 'text/html');
|
|
const images = doc.querySelectorAll('img');
|
|
images.forEach(img => {
|
|
if (!img.classList.contains('emoji-image')) {
|
|
result.push(img.src);
|
|
}
|
|
});
|
|
// #endif
|
|
// #ifdef APP
|
|
// 匹配所有 img 标签
|
|
const imgRegex1 = /<img[^>]+>/g;
|
|
// 匹配 class 属性中的 emoji-image
|
|
const emojiClassRegex = /class=["'][^"']*emoji-image[^"']*["']/i;
|
|
|
|
const images1 = msg.match(imgRegex1) || [];
|
|
|
|
images1.forEach(imgTag => {
|
|
if (!emojiClassRegex.test(imgTag)) {
|
|
// 提取 src 属性
|
|
const srcMatch = imgTag.match(/src=["']([^"']+)["']/);
|
|
if (srcMatch && srcMatch[1]) {
|
|
result.push(srcMatch[1]);
|
|
}
|
|
}
|
|
});
|
|
// #endif
|
|
|
|
|
|
// console.log('图片消息',result);
|
|
if (msg == '<p><br></p>'||(contentText && !hasImg)) {
|
|
uni.showToast({ title: "内容不能为空", icon: "none" });
|
|
this.inputMsg = '';
|
|
this.editorCtx.clear();
|
|
return false;
|
|
}
|
|
|
|
if(result.length>0){
|
|
let message={
|
|
type:'image',
|
|
status:'going'
|
|
};
|
|
result.forEach((res)=>{
|
|
message.imgid=1;
|
|
message.content=res;
|
|
// console.info(res);
|
|
this.$emit('send',Object.assign(this.msgItem(), message),res);
|
|
})
|
|
this.inputMsg = '';
|
|
this.editorCtx.clear();
|
|
}else{
|
|
// 获取@的所有人
|
|
this.edit.getLink().then((e)=>{
|
|
let message={
|
|
type:'text',
|
|
content:msg,
|
|
plain_text:msg1,
|
|
extends:this.quote
|
|
}
|
|
// 如果有qute就是引用消息
|
|
if(this.quote.msg_id){
|
|
message.pid=this.quote.msg_id;
|
|
message.extends=this.quote;
|
|
}
|
|
const userList = Array.from(new Set(e));
|
|
message.at=userList;
|
|
this.inputMsg = '';
|
|
this.closeQuote();
|
|
this.editorCtx.clear();
|
|
if(this.appBox!=1){
|
|
this.getFocus();
|
|
setTimeout(()=>{
|
|
this.isFocus=true;
|
|
},10)
|
|
}
|
|
|
|
this.$emit('send',Object.assign(this.msgItem(), message),'');
|
|
});
|
|
}
|
|
},
|
|
fail:(e)=>{
|
|
this.inputMsg = '';
|
|
this.editorCtx.clear();
|
|
this.editorCtx.format('fontFamily', 'inherit');
|
|
console.info('错误');
|
|
}
|
|
})
|
|
|
|
},
|
|
sendTextMsg1(){
|
|
this.editorCtx.getContents({
|
|
success:(e)=>{
|
|
let msg=e.html;
|
|
let msg1=e.text.replace(/\n/g, ' ').trim();
|
|
const contentText = /^\s*$/.test(msg.replace(/<[^>]+>/g, ""));
|
|
if (msg == '<p><br></p>'||contentText) {
|
|
uni.showToast({ title: "内容不能为空", icon: "none" });
|
|
this.inputMsg = '';
|
|
this.editorCtx.clear();
|
|
return false;
|
|
}
|
|
this.edit.getLink().then((e)=>{
|
|
let message={
|
|
type:'text',
|
|
content:msg,
|
|
plain_text:msg1,
|
|
extends:this.quote
|
|
}
|
|
// 如果有qute就是引用消息
|
|
if(this.quote.msg_id){
|
|
message.pid=this.quote.msg_id;
|
|
message.extends=this.quote;
|
|
}
|
|
const userList = Array.from(new Set(e));
|
|
message.at=userList;
|
|
this.inputMsg = '';
|
|
this.closeQuote();
|
|
this.editorCtx.clear();
|
|
if(this.appBox!=1){
|
|
this.getFocus();
|
|
setTimeout(()=>{
|
|
this.isFocus=true;
|
|
},10)
|
|
}
|
|
this.$emit('send',Object.assign(this.msgItem(), message),'');
|
|
|
|
this.opengpt(msg1)
|
|
});
|
|
}
|
|
})
|
|
},
|
|
opengpt(text){
|
|
const val = text;
|
|
this.$emit('sendChat',val);
|
|
},
|
|
uploadEmoji(){
|
|
uni.navigateTo({
|
|
url: '/pages/message/emoji'
|
|
})
|
|
return;
|
|
},
|
|
// 选择图片
|
|
chooseImg(){
|
|
let message={
|
|
type:'image',
|
|
status:'going'
|
|
};
|
|
uni.chooseImage({
|
|
count : 9,
|
|
sizeType: ['original', 'compressed'],
|
|
sourceType : ['album', 'camera'],
|
|
success : (res)=>{
|
|
const tempFiles = res.tempFiles;
|
|
tempFiles.forEach((item) => {
|
|
message.content=item.path;
|
|
message.fileName=item.name;
|
|
message.fileSize=item.size;
|
|
this.$emit('send',Object.assign(this.msgItem(), message),item.path);
|
|
})
|
|
}
|
|
});
|
|
},
|
|
// 选择视频
|
|
chooseVideo: function () {
|
|
let _this = this;
|
|
let message={
|
|
type:'video',
|
|
status:'going'
|
|
};
|
|
uni.showModal({
|
|
title:"提示",
|
|
content:"是否需要进行压缩视频",
|
|
confirmText:"是",
|
|
cancelText:"否",
|
|
success(e) {
|
|
uni.chooseVideo({
|
|
sourceType: ['camera', 'album'],
|
|
compressed:e.confirm,
|
|
success: (res) => {
|
|
// if(res.duration>60){
|
|
// return uni.showToast({
|
|
// title: '视频长度不能超过60秒'
|
|
// })
|
|
// }
|
|
const tempFilePaths = res.tempFilePath;
|
|
let fixMode=(res.width > res.height) ? 1 : 2;
|
|
let arr={
|
|
duration:Math.ceil(res.duration),
|
|
width:res.width,
|
|
height:res.height,
|
|
fixMode:fixMode,
|
|
poster:''
|
|
};
|
|
message.fileName=res.name;
|
|
message.fileSize=res.size;
|
|
message.extends=arr;
|
|
message.content=tempFilePaths;
|
|
message.confused = e.confirm;
|
|
_this.$emit('send',Object.assign(_this.msgItem(), message),tempFilePaths);
|
|
}
|
|
});
|
|
}
|
|
})
|
|
},
|
|
// 选择文件
|
|
// chooseFile:function(){
|
|
// let self=this;
|
|
// // #ifdef H5
|
|
// uni.chooseFile({
|
|
// count: 5, //默认100
|
|
// success: function (res) {
|
|
// self.appendFile(res);
|
|
// }
|
|
// });
|
|
// // #endif
|
|
// // #ifdef MP
|
|
// wx.chooseMessageFile({
|
|
// count: 5, //默认100
|
|
// success: function (res) {
|
|
// self.appendFile(res);
|
|
// }
|
|
// });
|
|
// // #endif
|
|
|
|
// // #ifdef APP-PLUS
|
|
// const lemonjkFileSelect = uni.requireNativePlugin('lemonjk-FileSelect');
|
|
// lemonjkFileSelect.showPicker({
|
|
// pathScope: "/Download", // 各属性配置见下方【showPicker可配置参数说明】
|
|
// mimeType: "*/*",
|
|
// utisType:"public.data",
|
|
// multi:'yes',
|
|
// }, result => {
|
|
// // 未授权文件读取权限,可以提示用户未打开读取文件权限(仅安卓)
|
|
// if(result.code==1001){
|
|
// uni.showModal({
|
|
// title:"需要文件访问权限",
|
|
// content:"您还未授权本应用读取文件。为保证您可以正常上传文件,请在权限设置页面打开文件访问权限(不同手机厂商表述可能略有差异)请根据自己手机品牌设置",
|
|
// confirmText:"去授权",
|
|
// cancelText:"算了",
|
|
// success(e) {
|
|
// if(e.confirm){
|
|
// // 跳转到应用设置页
|
|
// lemonjkFileSelect.gotoSetting();
|
|
// }
|
|
// }
|
|
// })
|
|
// }
|
|
// let type='file';
|
|
// let imageExts=['jpg','jpeg','png','bmp','gif'];
|
|
// let videoExts=['mp4','3gp','avi','m2v','mkv','mov'];
|
|
// result.files.forEach((item)=>{
|
|
// if(imageExts.includes(item.fileExtension)){
|
|
// type='image';
|
|
// }else if(videoExts.includes(item.fileExtension)){
|
|
// type='video';
|
|
// }else{
|
|
// type='file';
|
|
// }
|
|
// let filePath='file://'+item.filePath;
|
|
// const message={
|
|
// type:type,
|
|
// status:'going',
|
|
// fileName:item.FileName,
|
|
// fileSize:item.fileSize,
|
|
// content:filePath
|
|
// };
|
|
// this.$emit('send',Object.assign(this.msgItem(), message),filePath);
|
|
// })
|
|
// })
|
|
// // #endif
|
|
|
|
// },
|
|
|
|
chooseFile: function() {
|
|
let self = this;
|
|
|
|
// 允许的文件类型(按扩展名)
|
|
const allowedExtensions = ['pdf', 'doc', 'docx', 'txt', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar'];
|
|
|
|
// #ifdef H5
|
|
uni.chooseFile({
|
|
count: 5,
|
|
accept: '.' + allowedExtensions.join(',.'), // 限制选择类型
|
|
success: function(res) {
|
|
const filteredFiles = res.tempFiles.filter(file => {
|
|
const ext = file.name.split('.').pop().toLowerCase();
|
|
return allowedExtensions.includes(ext);
|
|
});
|
|
if (filteredFiles.length > 0) {
|
|
self.appendFile({ tempFiles: filteredFiles });
|
|
} else {
|
|
uni.showToast({ title: '只能上传PDF/Word/Excel等文档', icon: 'none' });
|
|
}
|
|
}
|
|
});
|
|
// #endif
|
|
|
|
// #ifdef MP
|
|
wx.chooseMessageFile({
|
|
count: 5,
|
|
type: 'file', // 小程序专用参数:只选文档
|
|
success: function(res) {
|
|
const filteredFiles = res.tempFiles.filter(file => {
|
|
const ext = file.name.split('.').pop().toLowerCase();
|
|
return allowedExtensions.includes(ext);
|
|
});
|
|
if (filteredFiles.length > 0) {
|
|
self.appendFile({ tempFiles: filteredFiles });
|
|
} else {
|
|
uni.showToast({ title: '只能上传PDF/Word/Excel等文档', icon: 'none' });
|
|
}
|
|
}
|
|
});
|
|
// #endif
|
|
|
|
// #ifdef APP-PLUS
|
|
const lemonjkFileSelect = uni.requireNativePlugin('lemonjk-FileSelect');
|
|
lemonjkFileSelect.showPicker({
|
|
pathScope: "/Download",
|
|
mimeType: "application/*", // 限制MIME类型
|
|
utisType: "public.data",
|
|
multi: 'yes'
|
|
}, result => {
|
|
if (result.code == 1001) {
|
|
uni.showModal({
|
|
title: "需要文件访问权限",
|
|
content: "请授权文件访问权限",
|
|
confirmText: "去授权",
|
|
success(e) {
|
|
if (e.confirm) lemonjkFileSelect.gotoSetting();
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
// 过滤文件类型
|
|
const validFiles = result.files.filter(item => {
|
|
const ext = item.fileExtension.toLowerCase();
|
|
return allowedExtensions.includes(ext);
|
|
});
|
|
|
|
if (validFiles.length === 0) {
|
|
uni.showToast({ title: '只能上传PDF/Word/Excel等文档', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
validFiles.forEach(item => {
|
|
const message = {
|
|
type: 'file', // 强制设为文件类型
|
|
status: 'going',
|
|
fileName: item.FileName,
|
|
fileSize: item.fileSize,
|
|
content: 'file://' + item.filePath
|
|
};
|
|
this.$emit('send', Object.assign(this.msgItem(), message), message.content);
|
|
});
|
|
});
|
|
// #endif
|
|
},
|
|
|
|
// 写入文件
|
|
appendFile(res){
|
|
const tempFiles=res.tempFiles;
|
|
tempFiles.forEach((item) => {
|
|
let path=item.path;
|
|
// #ifdef APP-PLUS
|
|
path='file://'+ item.path;
|
|
// #endif
|
|
let message={
|
|
type:'file',
|
|
status:'going',
|
|
fileName:item.name,
|
|
fileSize:item.size,
|
|
content:path
|
|
};
|
|
// #ifdef H5
|
|
let type=item.type;
|
|
if(type.indexOf("image/")!=-1){
|
|
message.type="image";
|
|
}
|
|
if(type.indexOf("video/")!=-1){
|
|
message.type="video";
|
|
}
|
|
// #endif
|
|
this.$emit('send',Object.assign(this.msgItem(), message),path);
|
|
})
|
|
|
|
},
|
|
// 选择定位
|
|
chooseLocation(){
|
|
uni.chooseLocation({
|
|
success: (res) => {
|
|
// console.log('123456:' + res);
|
|
// console.log('位置名称:' + res.name);
|
|
// console.log('详细地址:' + res.address);
|
|
// console.log('纬度:' + res.latitude);
|
|
// console.log('经度:' + res.longitude);
|
|
let message={
|
|
type:'location',
|
|
status:'going',
|
|
content:'[位置] '+res.name,
|
|
extends:res
|
|
};
|
|
this.$emit('send',Object.assign(this.msgItem(), message),false);
|
|
}
|
|
})
|
|
// uni.navigateTo({
|
|
// url:'/pages/mapselect/mapselect'
|
|
// })
|
|
},
|
|
calling(is_video){
|
|
// #ifdef MP
|
|
return uni.showToast({
|
|
title:'小程序暂不支持',
|
|
icon:'none'
|
|
})
|
|
// #endif
|
|
if(!parseInt(this.globalConfig.chatInfo.webrtc)){
|
|
return uni.showToast({
|
|
title:'未开启音视频通话',
|
|
icon:'none'
|
|
})
|
|
}
|
|
if(!parseInt(this.globalConfig.chatInfo.simpleChat)){
|
|
return uni.showToast({
|
|
title:'系统已关闭私聊',
|
|
icon:'none'
|
|
})
|
|
}
|
|
if(msgStore.webrtcLock){
|
|
return uni.showToast({
|
|
title:'其他终端正在通话中',
|
|
icon:'none'
|
|
})
|
|
}
|
|
let msg_id=this.$util.getUuid();
|
|
uni.navigateTo({
|
|
url: '/pages/message/call?msg_id='+msg_id+'&type='+is_video+'&status=1&id='+this.contact.id+'&name='+this.contact.displayName+'&avatar='+encodeURI(this.contact.avatar)
|
|
})
|
|
|
|
},
|
|
changeMsgText(e){
|
|
// 只有设置过@后才回去检查@时间
|
|
if(this.isAt){
|
|
this.edit.eventLink(e.detail);
|
|
if(this.edit.isSetContents){
|
|
setTimeout(()=>{
|
|
this.getFocus()
|
|
},200);
|
|
}
|
|
}
|
|
|
|
const html = String(e.detail.html || '');
|
|
|
|
// const urlMatch = html.match(/<p>(\s|<br\s*\/?>)*(<img[^>]*>(\s|<br\s*\/?>)*)*(https?:\/\/[^\s]+?)\s*<\/p>/i);
|
|
const urlMatch = html.match(/<p>(?:<span[^>]*>.*?<\/span>)*(\s|<br\s*\/?>)*(<img[^>]*>(\s|<br\s*\/?>)*)*(https?:\/\/[^\s]+?)\s*<\/p>/i);
|
|
const url = urlMatch ? urlMatch[4] : '';
|
|
// 检查是否是图片 URL
|
|
const isImageUrl = /\.(png|jpe?g|gif|webp|svg|bmp)(\?.*)?$/i.test(url);
|
|
// console.log(e);
|
|
if (urlMatch&&isImageUrl) {
|
|
this.img1(urlMatch[4]);
|
|
return
|
|
}
|
|
|
|
const txt=html.replace(/\n/g, '');
|
|
if((txt==''||txt=='<p><br></p>') && e.detail.html=='<p><br></p>'){
|
|
this.inputMsg='';
|
|
}else{
|
|
this.inputMsg=e.detail.html;
|
|
}
|
|
},
|
|
img1(val){
|
|
if (val) {
|
|
const _this = this
|
|
this.editorCtx.insertImage({
|
|
src: val,
|
|
width: 50,
|
|
height: 'auto',
|
|
nowrap: true
|
|
});
|
|
|
|
setTimeout(() => {
|
|
this.editorCtx.getContents({
|
|
success: (res) => {
|
|
const html = res.html;
|
|
// 转义URL中的特殊字符以确保正则匹配
|
|
const escapedUrl = val.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
// 匹配<p>标签内的URL
|
|
let regex;
|
|
let newHtml;
|
|
// #ifdef APP
|
|
regex = new RegExp(
|
|
`(<p[^>]*>\\s*)` + // 分组1: <p>开始
|
|
`((?:<img[^>]*>\\s*)*)` + // 分组2: 前置图片
|
|
`${escapedUrl}` + // 要删除的URL
|
|
`((?:\\s*<img[^>]*>)*)` + // 分组3: 后置图片
|
|
`(\\s*</p>)`, // 分组4: </p>结束
|
|
'gi');
|
|
newHtml = html.replace(regex, '$1$2$3$4');
|
|
// #endif
|
|
// #ifdef H5
|
|
regex = new RegExp(`(<img[^>]*>(\\s|<br\\s*\/?>)*)${escapedUrl}(?=[^<]*</p>)`, 'gi');
|
|
newHtml = html.replace(regex, '$1');
|
|
// #endif
|
|
|
|
// console.log('1',escapedUrl);
|
|
// console.log('2',regex);
|
|
// console.log('3',newHtml);
|
|
// 更新编辑器内容
|
|
this.editorCtx.setContents({
|
|
html: newHtml,
|
|
success: () => {
|
|
// console.log(_this.editorCtx);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}, 0); // 使用setTimeout确保插入完成后再删除
|
|
}
|
|
},
|
|
onEditorReady() {
|
|
// #ifdef MP-BAIDU
|
|
this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editor');
|
|
// #endif
|
|
|
|
// #ifdef APP-PLUS || MP-WEIXIN || H5
|
|
const query = uni.createSelectorQuery().in(this);
|
|
query.select('#editor').context((res) => {
|
|
this.edit = new Edit({context: res.context,maxCount: 300});
|
|
this.editorCtx = res.context
|
|
}).exec()
|
|
// #endif
|
|
},
|
|
InputFocus(e) {
|
|
this.isFocus=true;
|
|
if(this.appBox>0){
|
|
// 关闭表情盒子和更多盒子
|
|
this.appBox=0;
|
|
}
|
|
this.InputBottom = 0;
|
|
},
|
|
getInputTop(){
|
|
console.log('123456');
|
|
const query=this.$util.getQuery(this);
|
|
setTimeout(()=>{
|
|
query.select('#editor').boundingClientRect();
|
|
query.exec(data =>{
|
|
if(this.boardHeight>0){
|
|
//如果editord的top,还没屏幕减去键盘高度大,说明editor还在下面,给InputBottom增加一个键盘高度
|
|
if((this.mainHeight-this.boardHeight)>data[0].top){
|
|
this.InputBottom = 0;
|
|
}else{
|
|
this.InputBottom =this.boardHeight;
|
|
}
|
|
}
|
|
})
|
|
},10)
|
|
},
|
|
InputBlur(e) {
|
|
if(!this.appBox && !this.isFocus){
|
|
this.InputBottom = 0;
|
|
}
|
|
setTimeout(()=>{
|
|
this.isFocus=false;
|
|
},10)
|
|
|
|
},
|
|
// 开始录音
|
|
startRecorder() {
|
|
console.log('录音开始...')
|
|
// #ifdef H5
|
|
this.$refs.recorderRef.start()
|
|
// #endif
|
|
|
|
// #ifndef H5
|
|
this.recorderManager.start({duration:60000, format:'mp3' });
|
|
this.recLength = 0;
|
|
this.recTimer = setInterval(()=>{this.recLength++;}, 1000);
|
|
// #endif
|
|
|
|
this.isUseRecorder = true
|
|
},
|
|
// 结束录音
|
|
endRecorder() {
|
|
console.log('录音结束')
|
|
// #ifdef H5
|
|
this.$refs.recorderRef.stop()
|
|
// #endif
|
|
|
|
// #ifndef H5
|
|
this.recorderManager.stop();
|
|
clearInterval(this.recTimer);
|
|
// #endif
|
|
|
|
this.isUseRecorder = false
|
|
},
|
|
//中断录音
|
|
cancelRecorder(){
|
|
this.endRecorder();
|
|
this.isCancel=true;
|
|
},
|
|
// 移除录音按钮
|
|
moveRecorder(e){
|
|
let touch=e.touches[0];
|
|
if(touch.clientY<this.mainHeight-80){
|
|
this.isCancel=true;
|
|
}else{
|
|
this.isCancel=false;
|
|
}
|
|
},
|
|
handlerSuccess(res) {
|
|
this.checkRecorder(res.duration);
|
|
if(this.isCancel){
|
|
this.isCancel=false;
|
|
return console.log('录音已取消');
|
|
}
|
|
let message={
|
|
type:'voice',
|
|
content:res.localUrl,
|
|
fileName:this.$util.getUuid()+'.mp3',
|
|
extends:{
|
|
duration: res.duration
|
|
}
|
|
}
|
|
this.$emit('send',Object.assign(this.msgItem(), message));
|
|
},
|
|
// 检测录音是否合格
|
|
checkRecorder(duration){
|
|
if(duration<1 || isNaN(duration) || !duration){
|
|
this.recLength = 0;
|
|
this.tmpVoice = '';
|
|
this.recing = false;
|
|
this.isCancel=true;
|
|
return uni.showToast({
|
|
title: '录音时间太短',
|
|
icon: 'error'
|
|
})
|
|
}
|
|
},
|
|
handlerError(code) {
|
|
switch (code) {
|
|
case '201':
|
|
uni.showModal({
|
|
content: '麦克风权限被拒绝,请刷新页面后授权麦克风权限。'
|
|
})
|
|
break
|
|
default:
|
|
console.log('录音功能受限,请知晓!')
|
|
break
|
|
}
|
|
},
|
|
closeQuote(){
|
|
this.quote='';
|
|
},
|
|
// 引用消息
|
|
quoteMessage(quote){
|
|
this.quote=quote;
|
|
// 如果是群聊.需要@人员
|
|
if(this.contact.is_group==1 && quote.user_id!=this.userInfo.user_id){
|
|
this.setAtList({
|
|
user_id:quote.user_id,
|
|
realname:quote.realname,
|
|
})
|
|
}
|
|
},
|
|
getEmojiList(){
|
|
this.$api.emojiApi.emojiList({}).then((res)=>{
|
|
if(res.code==0){
|
|
emoji[1]['children']=res.data;
|
|
if(this.TabCur==1){
|
|
this.currentEmojiList=res.data;
|
|
}
|
|
}
|
|
this.emojiList=emoji;
|
|
})
|
|
|
|
},
|
|
// downloadFileImg(){
|
|
// if(this.FileImg==false){
|
|
// // console.log('123456');
|
|
// var self1 = this;
|
|
// this.currentEmojiList.forEach((res)=>{
|
|
// // console.log(res);
|
|
// uni.downloadFile({ url: res.src,success: (downloadResult) => {
|
|
// self1.saveToPermanentStorage(downloadResult.tempFilePath);
|
|
// }})
|
|
// });
|
|
// }
|
|
// },
|
|
// // App端持久化存储实现
|
|
// saveToPermanentStorage(tempPath) {
|
|
// return new Promise((resolve, reject) => {
|
|
// // 获取应用文档目录(持久化存储)
|
|
// plus.io.resolveLocalFileSystemURL(
|
|
// '_doc',
|
|
// (docDir) => {
|
|
// // 创建目标路径
|
|
// docDir.getDirectory(
|
|
// 'emoji',
|
|
// { create: true, exclusive: false },
|
|
// (entry) => {
|
|
// // 从临时路径获取文件名
|
|
// const fileName = this.getFileName(tempPath);
|
|
// uni.setStorageSync('FileImg',true);
|
|
// const fileName1 = this.getFileName(docDir.fullPath + 'emoji/' +fileName);
|
|
// // console.log(fileName);
|
|
// // console.log(fileName1);
|
|
// // 新增:检查文件是否存在
|
|
// entry.getFile(fileName1,{ create: false }, // 不创建新文件
|
|
// (fileEntry) => {
|
|
// // console.log('文件已存在,拒绝操作');
|
|
// // 文件已存在,拒绝操作
|
|
// reject(new Error('文件已存在: ' + fileName));
|
|
// },
|
|
// (error) => {
|
|
// // console.log(error);
|
|
// // 文件不存在(或发生其他错误),继续复制操作
|
|
// if (error.code === 14) { // 1表示文件不存在(不同平台错误码可能不同)
|
|
// this.copyFile(tempPath, entry, fileName, resolve, reject);
|
|
// } else {
|
|
// reject(error);
|
|
// }
|
|
// }
|
|
// );
|
|
// },
|
|
// (error) => {
|
|
// reject(error);
|
|
// }
|
|
// );
|
|
// },
|
|
// (error) => {
|
|
// reject(error);
|
|
// }
|
|
// );
|
|
// });
|
|
// },
|
|
|
|
// // 提取复制逻辑为独立方法
|
|
// copyFile(tempPath, targetDir, fileName, resolve, reject) {
|
|
// plus.io.resolveLocalFileSystemURL(
|
|
// tempPath,
|
|
// (tempEntry) => {
|
|
// tempEntry.copyTo(
|
|
// targetDir,
|
|
// fileName,
|
|
// (newEntry) => {
|
|
// resolve(newEntry.toLocalURL());
|
|
// },
|
|
// (error) => {
|
|
// reject(error);
|
|
// }
|
|
// );
|
|
// },
|
|
// (error) => {
|
|
// reject(error);
|
|
// }
|
|
// );
|
|
// },
|
|
// // 获取文件名工具方法
|
|
// getFileName(path) {
|
|
// const index = path.lastIndexOf('/');
|
|
// let fileName = path.substr(index + 1);
|
|
// fileName = fileName.replace(/\(\d+\)(?=\.[^./]+$)/, '');
|
|
// return fileName;
|
|
// },
|
|
// async getImagePath(){
|
|
// this.imglist = await getSavedImages3()
|
|
// this.imglist.map(item => {
|
|
// item.path = plus.io.convertLocalFileSystemURL(item.path)
|
|
// item.name = item.name.replace(/\.png$/i, '');
|
|
// });
|
|
// // console.info('读取地址',this.imglist);
|
|
// },
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.im-footer{
|
|
// position:fixed; left:0; bottom:0;
|
|
padding:0; width:100%; min-height:100rpx;display:flex; flex-wrap:nowrap; overflow:hidden; box-shadow:1px 1px 6px #999999; align-items:flex-end;z-index:101}
|
|
.im-footer .items{width:auto; line-height:88rpx; flex-shrink:0; font-size:28rpx; color:#2B2E3D;}
|
|
.im-menus{width:80rpx; height:80rpx; flex-shrink:0; line-height:80rpx; text-align:center;}
|
|
.im-input{padding:14rpx 14rpx; border-radius:10rpx;margin:0 8rpx !important;height:100%;min-height:44rpx;max-height: 300rpx;font-size: 28rpx;word-break: break-all;}
|
|
.im-msgarea{padding:12rpx 10rpx 12rpx 0;}
|
|
.im-record{width:100%; position:fixed; left:0; bottom:0; background:#FFFFFF; padding:30px 0; padding-bottom:100rpx; z-index:11; box-shadow:1px 1px 6px #999999;}
|
|
.im-record-close{width:100rpx; height:100rpx; position:absolute; top:0px; right:0px; z-index:100; text-align:center; line-height:100rpx; color:#888888; font-size:38rpx !important;}
|
|
.im-record-txt{text-align:center; font-size:26rpx; line-height:30px; padding-bottom:10px; color:#CCCCCC;}
|
|
.im-record-btn{width:60px; height:60px; margin:0 auto; border:5px solid #F1F2F3; border-radius:100%; background:#00B26A;}
|
|
.im-recording{background:#FF0000; animation:fade linear 2s infinite;}
|
|
@keyframes fade{from{opacity:0.1;} 50%{opacity:1;} to{opacity:0.1;}}
|
|
.im-record-txt text{color:#00B26A; padding:0 12px;}
|
|
.im-send-voice{margin-top:12px; font-size:28rpx; color:#00BA62; text-align:center;}
|
|
.im-send-voice text{margin:0 15px; color:#00BA62;}
|
|
.toolBox {
|
|
height:72rpx;
|
|
margin-bottom:3rpx;
|
|
.recorder{
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background-color: #fff;
|
|
padding: 14rpx;
|
|
border-radius: 10rpx;
|
|
font-size: 28rpx;
|
|
box-shadow: 2rpx 2rpx 6rpx rgba(0, 0, 0, 0.2);
|
|
position: relative;
|
|
margin: 0 6rpx !important;
|
|
height:100%;
|
|
&.active {
|
|
background-color: #67C23A;;
|
|
color:#fff;
|
|
}
|
|
}
|
|
}
|
|
.voice-model{
|
|
width:240rpx;
|
|
height:180rpx;
|
|
position: fixed;
|
|
top: 50%;
|
|
z-index: 2;
|
|
transform: translate(-50%, -50%);
|
|
left: 50%;
|
|
padding: 0 4rpx 0 6rpx;
|
|
background-color: #363636b3;
|
|
}
|
|
.im-emoji-box{
|
|
// position:fixed;
|
|
// bottom:0;
|
|
width:100%;
|
|
z-index:3;
|
|
background-color: #F1F2F3;
|
|
.im-emoji-header{
|
|
height:90rpx;
|
|
}
|
|
.im-emoji-body{
|
|
height:100%;padding-bottom: 100rpx;
|
|
.im-emoji-item{
|
|
padding:22rpx;
|
|
}
|
|
}
|
|
}
|
|
.im-app-box{
|
|
position:fixed;bottom:0;width:100%;background-color: #F1F2F3;z-index:3;
|
|
.im-app-item{
|
|
width:160rpx;height:160rpx;
|
|
.im-app-item-icon{
|
|
padding:20rpx 25rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.message-quote{
|
|
padding:8rpx;
|
|
font-size:24rpx;
|
|
margin:16rpx -10rpx 0 10rpx;
|
|
background-color: #e3e3e3;
|
|
.text-overflow{
|
|
overflow: hidden !important;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap !important;
|
|
width:380rpx;
|
|
}
|
|
}
|
|
.voice-icon{
|
|
animation: twinkle 0.5s infinite alternate;
|
|
}
|
|
@keyframes twinkle {
|
|
0%{
|
|
opacity:0.9;
|
|
}
|
|
100%{
|
|
opacity:0.3;
|
|
}
|
|
}
|
|
|
|
.upload-emoji{
|
|
width:90rpx;
|
|
height:90rpx;
|
|
border:dashed 1px #999;
|
|
font-size:50rpx;
|
|
text-align: center;
|
|
border-radius: 6rpx;
|
|
}
|
|
.im-container{
|
|
width: 100%;
|
|
min-height: 3.125rem;
|
|
box-shadow: 1px 1px 6px #999;
|
|
z-index: 1001;
|
|
border-top: solid 1px #e6e6e6;
|
|
}
|
|
</style>
|
|
<style>
|
|
.im-input /deep/ .ql-editor{
|
|
max-height:300rpx;
|
|
line-height: 1.5;
|
|
font-size: 30rpx !important;
|
|
word-break: break-all;
|
|
word-wrap: break-word;
|
|
padding-left: 3px;
|
|
}
|
|
|
|
|
|
.im-input /deep/ .ql-editor p img{
|
|
vertical-align: text-top;
|
|
}
|
|
</style>
|