聊天页面处理没有聊天内容展示

This commit is contained in:
2022-03-07 14:29:37 +08:00
26 changed files with 1251 additions and 532 deletions

View File

@@ -0,0 +1,188 @@
<template xlang="wxml" minapp="mpvue">
<view>
</view>
</template>
<script>
export default {
name: 'tki-file-manager',
props: {},
data() {
return {}
},
methods: {
_openFile() {
// #ifdef APP-PLUS
if (plus.os.name.toLowerCase() != "android") {
uni.showModal({
title: '提示',
content: '仅支持Android平台',
success: function(res) {}
});
return false
}
let that = this
// java 代码来自 http://www.cnblogs.com/panhouye/archive/2017/04/23/6751710.html
let main = plus.android.runtimeMainActivity();
let Intent = plus.android.importClass("android.content.Intent");
//
let fileIntent = new Intent(Intent.ACTION_GET_CONTENT)
//fileIntent.setType(“image/*”);//选择图片
//fileIntent.setType(“audio/*”); //选择音频
//fileIntent.setType(“video/*”); //选择视频 mp4 3gp 是android支持的视频格式
//fileIntent.setType(“video/*;image/*”);//同时选择视频和图片
fileIntent.setType("*/*"); //无类型限制
fileIntent.addCategory(Intent.CATEGORY_OPENABLE);
main.startActivityForResult(fileIntent, 1);
// 获取回调
main.onActivityResult = function(requestCode, resultCode, data) {
let Activity = plus.android.importClass("android.app.Activity");
let ContentUris = plus.android.importClass("android.content.ContentUris");
let Cursor = plus.android.importClass("android.database.Cursor");
let Uri = plus.android.importClass("android.net.Uri");
let Build = plus.android.importClass("android.os.Build");
let Environment = plus.android.importClass("android.os.Environment");
let DocumentsContract = plus.android.importClass("android.provider.DocumentsContract");
let MediaStore = plus.android.importClass("android.provider.MediaStore");
// 给系统导入 contentResolver
let contentResolver = main.getContentResolver()
plus.android.importClass(contentResolver);
// 返回路径
let path = '';
if (resultCode == Activity.RESULT_OK) {
let uri = data.getData()
if ("file" == uri.getScheme().toLowerCase()) { //使用第三方应用打开
path = uri.getPath();
return;
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { //4.4以后
path = getPath(this, uri);
} else { //4.4以下下系统调用方法
path = getRealPathFromURI(uri)
}
// 回调
that.$emit('result', path)
}
// 4.4 以上 从Uri 获取文件绝对路径
function getPath(context, uri) {
let isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
let scheme = uri.getScheme().toLowerCase()
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
let docId = DocumentsContract.getDocumentId(uri);
let split = docId.split(":");
let type = split[0];
// 如果是手机内部存储
if ("primary" == type.toLowerCase()) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
return '/storage/' + type + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
let docId = DocumentsContract.getDocumentId(uri);
let split = docId.split(":");
return split[1]
// console.log(id)
// let contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), id);
// return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
let docId = DocumentsContract.getDocumentId(uri);
let split = docId.split(":");
let type = split[0];
let contentUri = null;
if ("image" == type.toLowerCase()) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video" == type.toLowerCase()) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio" == type.toLowerCase()) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
let selection = "_id=?";
let selectionArgs = [split[1]];
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content" == scheme) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file" == scheme) {
return uri.getPath();
}
}
// 4.4 以下 获取 绝对路径
function getRealPathFromURI(uri) {
let res = null
let proj = [MediaStore.Images.Media.DATA]
let cursor = contentResolver.query(uri, proj, null, null, null);
if (null != cursor && cursor.moveToFirst()) {
;
let column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
res = cursor.getString(column_index);
cursor.close();
}
return res;
}
// 通过uri 查找出绝对路径
function getDataColumn(context, uri, selection, selectionArgs) {
let cursor = null;
let column = "_data";
let projection = [column];
// let contentResolver = context.getContentResolver()
// plus.android.importClass(contentResolver);
cursor = contentResolver.query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
let column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
}
function isExternalStorageDocument(uri) {
return "com.android.externalstorage.documents" == uri.getAuthority() ? true : false
}
function isDownloadsDocument(uri) {
return "com.android.providers.downloads.documents" == uri.getAuthority() ? true : false
}
function isMediaDocument(uri) {
return "com.android.providers.media.documents" == uri.getAuthority() ? true : false
}
}
// #endif
// #ifndef APP-PLUS
uni.showModal({
title: '提示',
content: '仅支持Android平台',
success: function(res) {
}
});
// #endif
},
},
onLoad() {
// plus.io.resolveLocalFileSystemURL( '/storage/emulated/0', function(fs) {
// var directoryReader = fs.createReader();
// directoryReader.readEntries(function(entries) {
// var i;
// for (i = 0; i < entries.length; i++) {
// console.log(entries[i].name);
// }
// }, function(e) {
// console.log("Read entries failed: " + e.message);
// });
// }, function(e) {
// console.log("Request file system failed: " + e.message);
// });
}
}
</script>

View File

@@ -31,7 +31,7 @@ Vue.use(router)
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.prototype.$store = store Vue.prototype.$store = store
usqlite.connect({ uni.$sql = usqlite.connect({
name: 'zh-health', // 数据库名称 name: 'zh-health', // 数据库名称
path: '_doc/health.db', // 路径 path: '_doc/health.db', // 路径
}, (err, res) => { }, (err, res) => {
@@ -40,7 +40,7 @@ usqlite.connect({
fail: () => { fail: () => {
contactModel.create((err, res) => { contactModel.create((err, res) => {
console.error('SQLITE 创建表格', err, res) console.error('SQLITE 创建表格', err, res)
uni.setStorageSync('FIRST_RUN', 'X') uni.setStorageSync('FIRST_RUN', true)
}) })
} }
}) })

View File

@@ -2,7 +2,7 @@
"name" : "ZH-HEALTH", "name" : "ZH-HEALTH",
"appid" : "__UNI__C29473D", "appid" : "__UNI__C29473D",
"description" : "ZH-HEALTH您手上的健康管理专家", "description" : "ZH-HEALTH您手上的健康管理专家",
"versionName" : "1.0.20", "versionName" : "1.0.22",
"versionCode" : 100, "versionCode" : 100,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
@@ -47,6 +47,7 @@
"<uses-permission android:name=\"android.permission.INTERNET\"/>", "<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>", "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>", "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",

View File

@@ -7,33 +7,36 @@
<view class="preview" v-if="msg.objectName=='RC:TxtMsg'"> <view class="preview" v-if="msg.objectName=='RC:TxtMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>{{ msg.content || '' }} <text v-if="conversationType == 3">{{ user.name }}</text>{{ msg.content || '' }}
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:HQVCMsg'"> <view class="preview" v-else-if="msg.objectName=='RC:HQVCMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[语音] <text v-if="conversationType == 3">{{ user.name }}</text>[语音]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:ImgMsg'"> <view class="preview" v-else-if="msg.objectName=='RC:ImgMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[图片] <text v-if="conversationType == 3">{{ user.name }}</text>[图片]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:GIFMsg'"> <view class="preview" v-else-if="msg.objectName=='RC:GIFMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[表情] <text v-if="conversationType == 3">{{ user.name }}</text>[表情]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:FileMsg'"> <view class="preview" v-else-if="msg.objectName=='RC:FileMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[文件] <text v-if="conversationType == 3">{{ user.name }}</text>[文件]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:LBSMsg'"> <view class="preview" v-else-if="msg.objectName=='RC:LBSMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[位置] <text v-if="conversationType == 3">{{ user.name }}</text>[位置]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:InfoNtf' && JSON.parse(msg.message).mediaType==0"> <view class="preview" v-else-if="msg.objectName=='RC:AudioMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[语音通话] <text v-if="conversationType == 3">{{ user.name }}</text>[语音通话]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:InfoNtf' && JSON.parse(msg.message).mediaType==1"> <view class="preview" v-else-if="msg.objectName=='RC:VideoMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>[视频通话] <text v-if="conversationType == 3">{{ user.name }}</text>[视频通话]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:GrpNtf'"> <view class="preview" v-else-if="msg.objectName=='RC:GrpNtf'">
[{{ msg.message }}] [{{ msg.message }}]
</view> </view>
<view class="preview" v-if="msg.objectName=='RC:RcNtf'"> <view class="preview" v-else-if="msg.objectName=='RC:RcNtf'">
<text v-if="conversationType == 3">{{ user.name }}</text> 撤回了一条消息 <text v-if="conversationType == 3">{{ user.name }}</text> 撤回了一条消息
</view> </view>
<view class="preview" v-else>
{{ msg.objectName }}
</view>
</block> </block>
</view> </view>
</template> </template>

View File

@@ -2,7 +2,9 @@
<view class="emoji--lay" v-show="show"> <view class="emoji--lay" v-show="show">
<scroll-view class="scroll" :scroll-y="true"> <scroll-view class="scroll" :scroll-y="true">
<view class="emoji-flex"> <view class="emoji-flex">
<view class="item" v-for="(item, index) in emojiArr" :key="index" @click="$emit('onEmoji', item)">{{item.emoji}}</view> <view class="item" v-for="(item, index) in emojiArr" :key="index" @click="$emit('onEmoji', item)">
{{item.emoji}}
</view>
</view> </view>
</scroll-view> </scroll-view>
<view class="tool"> <view class="tool">
@@ -14,8 +16,8 @@
<script> <script>
import emoji from '@/static/im/emoji' import emoji from '@/static/im/emoji'
export default{ export default {
props:{ props: {
show: { show: {
type: Boolean, type: Boolean,
default: () => { default: () => {
@@ -23,7 +25,7 @@
} }
} }
}, },
data(){ data() {
return { return {
emojiArr: emoji emojiArr: emoji
} }
@@ -32,16 +34,19 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.emoji--lay{ .emoji--lay {
height: 600rpx; height: 600rpx;
position: relative; position: relative;
.scroll{
.scroll {
height: 600rpx; height: 600rpx;
.emoji-flex{
.emoji-flex {
padding: 15rpx 15rpx 120rpx; padding: 15rpx 15rpx 120rpx;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
.item{
.item {
margin: 10rpx 15rpx; margin: 10rpx 15rpx;
font-size: 52rpx; font-size: 52rpx;
width: calc(12.5% - 30rpx); width: calc(12.5% - 30rpx);
@@ -49,7 +54,8 @@
} }
} }
} }
.tool{
.tool {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
@@ -58,7 +64,8 @@
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
padding: 20rpx 30rpx 30rpx; padding: 20rpx 30rpx 30rpx;
.item{
.item {
line-height: 70rpx; line-height: 70rpx;
border-radius: 35rpx; border-radius: 35rpx;
width: 140rpx; width: 140rpx;
@@ -68,7 +75,8 @@
background: white; background: white;
border: solid 1rpx #f5f5f5; border: solid 1rpx #f5f5f5;
box-sizing: border-box; box-sizing: border-box;
&.sent{
&.sent {
border-color: #34CE98; border-color: #34CE98;
background: #34CE98; background: #34CE98;
color: white; color: white;

View File

@@ -25,6 +25,8 @@
<text class="text">文件</text> <text class="text">文件</text>
</view> </view>
<tki-file-manager ref="filemanager" @result="sendFileMessage"></tki-file-manager>
<u-action-sheet :actions="callActions" cancelText="取消" @close="callShow = false" @select="singleCall" <u-action-sheet :actions="callActions" cancelText="取消" @close="callShow = false" @select="singleCall"
:show="callShow"> :show="callShow">
</u-action-sheet> </u-action-sheet>
@@ -34,11 +36,15 @@
<script> <script>
import im from '@/utils/im/index.js' import im from '@/utils/im/index.js'
import imBase from '../../mixins/imBase.js' import imBase from '../../mixins/imBase.js'
import tkiFileManager from "@/components/tki-file-manager/tki-file-manager.vue"
export default { export default {
mixins: [ mixins: [
imBase imBase
], ],
components: {
tkiFileManager
},
data() { data() {
return { return {
callActions: [{ callActions: [{
@@ -68,6 +74,23 @@
} }
}, },
methods: { methods: {
sendFileMessage(path) {
if (path) {
im.sentFile(this.conversationType, this.targetId, path).then(res => {
this.success()
}).catch(err => {
uni.showToast({
icon: 'none',
title: '发送文件失败' + err
})
})
} else {
uni.showToast({
icon: 'none',
title: '选择文件失败'
})
}
},
singleCall(e) { singleCall(e) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type + url: '/pages/im/private/call?targetId=' + this.targetId + '&mediaType=' + e.type +
@@ -81,10 +104,15 @@
count: 9, count: 9,
sourceType: ['album'], sourceType: ['album'],
success: res => { success: res => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0], let funs = []
this.sender, (res) => { res.tempFilePaths.map((item, index) => {
this.success() funs[index] = im.sentImage(this.conversationType, this
}) .targetId, item)
})
Promise.all(funs).then(res => {
this.success()
})
} }
}) })
break; break;
@@ -92,8 +120,8 @@
uni.chooseImage({ uni.chooseImage({
sourceType: ['camera'], sourceType: ['camera'],
success: res => { success: res => {
im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0], im.sentImage(this.conversationType, this.targetId, res.tempFilePaths[0])
this.sender, (res) => { .then((res) => {
this.success() this.success()
}) })
} }
@@ -104,8 +132,13 @@
break; break;
case 'location': case 'location':
uni.chooseLocation({ uni.chooseLocation({
success: (c) => { success: (location) => {
console.log(c); const thumbnail = ''
// 通过 location 的经纬度合成一张图片再把图片的base64发送出去
im.sentLocation(this.conversationType, this.targetId, location, thumbnail)
.then(() => {
this.success()
})
} }
}) })
break; break;
@@ -116,10 +149,7 @@
}) })
break; break;
case 'file': case 'file':
uni.showToast({ this.$refs.filemanager._openFile()
icon: 'none',
title: '功能正在开发中'
})
break; break;
} }
}, },

View File

@@ -1,17 +1,7 @@
<template> <template>
<view class="sent--text"> <view class="sent--text">
<input <input class="input" type="text" :auto-blur="true" :focus="focusState" v-model="inputTxt" confirm-type="send"
class="input" cursor-spacing="10" @focus="focus" @blur="blur" @confirm="sent" />
type="text"
:auto-blur="true"
:focus="focusState"
v-model="inputTxt"
confirm-type="send"
cursor-spacing="10"
@focus="focus"
@blur="blur"
@confirm="sent"
/>
</view> </view>
</template> </template>
@@ -56,7 +46,7 @@
inputTxt: '' inputTxt: ''
} }
}, },
created(){ created() {
uni.$on('emojiValue', res => { uni.$on('emojiValue', res => {
this.inputTxt = res.value this.inputTxt = res.value
}) })
@@ -65,7 +55,7 @@
methods: { methods: {
sent() { sent() {
if (!this.disabled) { if (!this.disabled) {
im.sentText(this.conversationType, this.targetId, this.inputTxt, this.sender, () => { im.sentText(this.conversationType, this.targetId, this.inputTxt).then(() => {
RongIMLib.clearTextMessageDraft(this.conversationType, this.targetId) RongIMLib.clearTextMessageDraft(this.conversationType, this.targetId)
this.$emit('success') this.$emit('success')
this.inputTxt = '' this.inputTxt = ''
@@ -91,6 +81,7 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
.input { .input {
background: #F3F6FB; background: #F3F6FB;
height: 70rpx; height: 70rpx;

View File

@@ -1,6 +1,7 @@
<template> <template>
<view class="send--voice"> <view class="send--voice">
<view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord" @touchmove="touchmove"> <view class="voice" hover-class="chat-hover" @touchstart="startRecord" @touchend="stopRecord"
@touchmove="touchmove">
<text class="button">按住 说话</text> <text class="button">按住 说话</text>
</view> </view>
<!-- 录音层 --> <!-- 录音层 -->
@@ -99,19 +100,19 @@
stopRecord(e) { stopRecord(e) {
if (!this.showRecordTip) return if (!this.showRecordTip) return
// 延迟500毫秒结束录音 // 延迟500毫秒结束录音
setTimeout(()=> { setTimeout(() => {
this.recorderManager.stop() this.recorderManager.stop()
clearInterval(this.interval) clearInterval(this.interval)
// 监听录音结束 // 监听录音结束
this.recorderManager.onStop(res => { this.recorderManager.onStop(res => {
if(this.isMoveCancel) { if (this.isMoveCancel) {
this.isMoveCancel = false this.isMoveCancel = false
return return
} }
if((this.maxRecordTime - this.recordTime) <= 0){ if ((this.maxRecordTime - this.recordTime) <= 0) {
uni.showToast({ uni.showToast({
title: '说话时间太短', title: '说话时间太短',
icon : 'none', icon: 'none',
}) })
this.showRecordTip = false this.showRecordTip = false
return return
@@ -120,19 +121,19 @@
this.showRecordTip = false this.showRecordTip = false
this.senVoice() this.senVoice()
}) })
},500) }, 500)
}, },
// 发送语音消息 // 发送语音消息
senVoice(){ senVoice() {
if(this.mp3AudioSrc === null) { if (this.mp3AudioSrc === null) {
uni.showToast({ uni.showToast({
title: '发送失败, 暂无音频信息', title: '发送失败, 暂无音频信息',
icon : 'none' icon: 'none'
}) })
return return
} }
im.sentVoice(this.conversationType, this.targetId, this.mp3AudioSrc, (this.maxRecordTime - im.sentVoice(this.conversationType, this.targetId, this.mp3AudioSrc, (this.maxRecordTime -
this.recordTime), this.sender, () => { this.recordTime)).then(() => {
this.recordTime = this.maxRecordTime this.recordTime = this.maxRecordTime
this.mp3AudioSrc = null this.mp3AudioSrc = null
setTimeout(() => { setTimeout(() => {
@@ -142,9 +143,9 @@
}) })
}, },
// 移动按钮 // 移动按钮
touchmove(e){ touchmove(e) {
if(this.startOffsetTop - e.changedTouches[0].pageY > 100){ if (this.startOffsetTop - e.changedTouches[0].pageY > 100) {
if(this.showRecordTip){ if (this.showRecordTip) {
this.isMoveCancel = true this.isMoveCancel = true
this.showRecordTip = false this.showRecordTip = false
this.recorderManager.stop() this.recorderManager.stop()
@@ -160,7 +161,7 @@
let betaAudio = uni.createInnerAudioContext() let betaAudio = uni.createInnerAudioContext()
betaAudio.src = this.mp3AudioSrc; betaAudio.src = this.mp3AudioSrc;
// 在播放中 // 在播放中
if(this.isBetaPlay){ if (this.isBetaPlay) {
betaAudio.stop() betaAudio.stop()
betaAudio.onStop(() => { betaAudio.onStop(() => {
this.isBetaPlay = false; this.isBetaPlay = false;
@@ -180,7 +181,7 @@
}) })
}, },
// 播放提示音乐 // 播放提示音乐
toastAudiMp3(){ toastAudiMp3() {
let toastAudio = uni.createInnerAudioContext() let toastAudio = uni.createInnerAudioContext()
toastAudio.src = require('@/static/im/toast/sentVoice.mp3') toastAudio.src = require('@/static/im/toast/sentVoice.mp3')
toastAudio.autoplay = true toastAudio.autoplay = true
@@ -227,12 +228,14 @@
margin-right: 15rpx; margin-right: 15rpx;
padding: 0 20rpx; padding: 0 20rpx;
font-weight: bold; font-weight: bold;
.button { .button {
font-size: 30rpx; font-size: 30rpx;
color: #333; color: #333;
} }
} }
.lay{
.lay {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
@@ -241,11 +244,13 @@
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
box-sizing: border-box; box-sizing: border-box;
.lay-header{
.lay-header {
height: calc(100vh - 140px); height: calc(100vh - 140px);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
.modal { .modal {
display: flex; display: flex;
background: rgba(0, 0, 0, .6); background: rgba(0, 0, 0, .6);
@@ -257,6 +262,7 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.icon { .icon {
width: 88rpx; width: 88rpx;
height: 88rpx; height: 88rpx;
@@ -268,12 +274,14 @@
} }
} }
} }
.lay-toast{
.lay-toast {
text-align: center; text-align: center;
color: rgba($color: #fff, $alpha: .8); color: rgba($color: #fff, $alpha: .8);
font-size: 28rpx; font-size: 28rpx;
} }
.lay-footer{
.lay-footer {
background-color: white; background-color: white;
height: 100px; height: 100px;
border-radius: 50% 50% 0 0; border-radius: 50% 50% 0 0;
@@ -286,11 +294,13 @@
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
.lay-footer-icon{
.lay-footer-icon {
width: 58rpx; width: 58rpx;
height: 58rpx; height: 58rpx;
} }
.lay-footer-text{
.lay-footer-text {
line-height: 40rpx; line-height: 40rpx;
color: gray; color: gray;
font-size: 28rpx; font-size: 28rpx;

View File

@@ -2,8 +2,7 @@
<view class="msg--call"> <view class="msg--call">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view> <view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="im--text" :class="isRemote ? 'left': 'right'"> <view class="im--text" :class="isRemote ? 'left': 'right'">
<uni-icons type="videocam" size="44rpx" v-if="msg.mediaType == 1" /> <uni-icons type="phone" size="44rpx" />
<uni-icons type="phone" size="40rpx" v-else />
{{ label }} {{ label }}
</view> </view>
</view> </view>
@@ -18,7 +17,6 @@
mixins: [ mixins: [
imBase imBase
], ],
name: 'showText',
props: { props: {
message: { message: {
type: Object, type: Object,
@@ -31,23 +29,18 @@
default: false default: false
} }
}, },
mounted() {
},
computed: { computed: {
msg() {
return JSON.parse(this.message.content.message)
},
label() { label() {
return this.msg.connected ? '通话时长:' + duration : '未接通' return this.message.content.customFields.status == 1 ? '通话时长:' + duration : '未接通'
}, },
isRemote() { isRemote() {
return this.message.messageDirection == 2 return this.message.messageDirection == 2
}, },
duration() { duration() {
if (this.message.duration > 3600) { if (this.message.content.customFields.duration > 3600) {
return moment.utc(this.message.duration * 1000).format('HH:mm:ss') return moment.utc(this.message.content.customFields.duration * 1000).format('HH:mm:ss')
} else { } else {
return moment.utc(this.message.duration * 1000).format('mm:ss') return moment.utc(this.message.content.customFields.duration * 1000).format('mm:ss')
} }
} }
} }

View File

@@ -0,0 +1,95 @@
<template>
<view class="msg--file">
<message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="file" :class="isRemote ? 'left': 'right'">
<view class="img">
{{ content.fileType }}
{{ content.name }}
</view>
</view>
</view>
</view>
</template>
<!-- "content": {
"fileType": "jpg",
"remote": "https://rongcloud-spic.ronghub.com/Xl1PRVpHVldeRQAGVgEHAAcBBgYGBgcDAwMGMjA3MA%3D%3D.jpg?e=1661583313&token=livk5rb3__JZjCtEiMxXpQ8QscLxbNLehwhHySnX:t58hs4uvM1RFsBeKLTcDbVW-k5w=",
"size": 347062,
"objectName": "RC:FileMsg",
"name": "Screenshot_2022-02-25-14-44-55-886_io.zhhealth.app.jpg",
"local": "file:///storage/emulated/0/DCIM/Screenshots/Screenshot_2022-02-25-14-44-55-886_io.zhhealth.app.jpg",
"userInfo": {
"userId": "10051",
"name": "Jason.电信",
"extra": "",
"portraitUrl": "http://storage.zh.shangkelian.cn/uploads/2022/02/16/29b13f5301694721ad7acd8b8b67bbd9.jpg"
}
}, -->
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
import imBase from '../../mixins/imBase.js'
export default {
mixins: [
imBase
],
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
}
},
components: {
messageState
},
computed: {
isRemote() {
return this.message.messageDirection == 2
},
content() {
return this.message.content
}
}
}
</script>
<style lang="scss" scoped>
.msg--file {
display: flex;
align-items: flex-end;
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.file {
.img {
width: 180rpx;
}
&.left {
.img {
border-radius: 0 10rpx 10rpx 10rpx;
}
}
&.right {
.img {
border-radius: 10rpx 0 10rpx 10rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<view class="msg--location">
<message-state :message="message" :isGroup="isGroup" :isRemote="isRemote" />
<view class="">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="location" :class="isRemote ? 'left': 'right'" @click="showLocation">
<view class="location--name">
{{ content.customFields.name }}
</view>
<view class="location--address">
{{ content.customFields.address }}
</view>
<image class="map" :src="require('@/static/imgs/map.jpeg')" mode="aspectFill" />
</view>
</view>
</view>
</template>
<script>
import * as RongIMLib from '@/uni_modules/RongCloud-IMWrapper/js_sdk/index'
import messageState from './messageState'
import imBase from '../../mixins/imBase.js'
export default {
mixins: [
imBase
],
name: 'showImage',
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
}
},
components: {
messageState
},
computed: {
isRemote() {
return this.message.messageDirection == 2
},
content() {
return this.message.content
}
},
methods: {
showLocation() {
uni.openLocation({
latitude: Number(this.content.customFields.latitude),
longitude: Number(this.content.customFields.longitude),
fail: (err) => {
uni.showToast({
icon: 'none',
title: '打开地图失败'
})
}
})
}
}
}
</script>
<style scoped lang="scss">
.msg--location {
display: flex;
align-items: flex-end;
.name {
font-size: 24rpx;
color: $text-gray-m;
}
.location {
position: relative;
width: 400rpx;
background: #FFFFFF;
padding: 10rpx;
.location--name {
font-size: 32rpx;
overflow: hidden;
word-break: break-all;
}
.location--address {
padding-bottom: 10rpx;
font-size: 24rpx;
color: $text-gray-m;
}
.map {
width: 400rpx;
height: 200rpx;
}
&.left {
border-radius: 0 10rpx 10rpx 10rpx;
}
&.right {
border-radius: 10rpx 0 10rpx 10rpx;
}
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<view class="">
<show-location v-if="message.content.objectName == 'RC:LBSMsg'" :message="message" :isGroup="isGroup" />
<show-video v-else-if="message.content.objectName == 'RC:VideoMsg'" :message="message" :isGroup="isGroup" />
<show-audio v-else-if="message.content.objectName == 'RC:AudioMsg'" :message="message" :isGroup="isGroup" />
</view>
</template>
<script>
import showLocation from './showLocation'
import showAudio from './showAudio'
import showVideo from './showVideo'
export default {
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
}
},
components: {
showLocation,
showAudio,
showVideo
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,84 @@
<template>
<view class="msg--call">
<view class="name" v-if="isGroup && isRemote">{{ contact(message.senderUserId).name }}</view>
<view class="im--text" :class="isRemote ? 'left': 'right'">
<uni-icons type="videocam" size="44rpx" />
{{ label }}
</view>
</view>
</template>
<script>
import utils from '@/utils/index.js'
import moment from 'moment'
import imBase from '../../mixins/imBase.js'
export default {
mixins: [
imBase
],
props: {
message: {
type: Object,
default: () => {
return {}
}
},
isGroup: {
type: Boolean,
default: false
}
},
computed: {
label() {
return this.message.content.customFields.status == 1 ? '通话时长:' + duration : '未接通'
},
isRemote() {
return this.message.messageDirection == 2
},
duration() {
if (this.message.content.customFields.duration > 3600) {
return moment.utc(this.message.content.customFields.duration * 1000).format('HH:mm:ss')
} else {
return moment.utc(this.message.content.customFields.duration * 1000).format('mm:ss')
}
}
}
}
</script>
<style scoped lang="scss">
.msg--call {
.name {
font-size: 26rpx;
color: $text-gray-m;
display: inline-block;
}
.im--text {
max-width: 508rpx;
padding: 20rpx;
line-height: 46rpx;
font-size: 32rpx;
color: $text-color;
display: flex;
flex-direction: row;
align-items: center;
&.left {
border-radius: 0 20rpx 20rpx 20rpx;
background: white;
}
&.right {
border-radius: 20rpx 0 20rpx 20rpx;
background: $main-color;
color: white;
.uni-icons {
color: white !important;
}
}
}
}
</style>

View File

@@ -8,6 +8,9 @@
<view class="notify" v-else-if="message.objectName === 'RC:RcNtf'"> <view class="notify" v-else-if="message.objectName === 'RC:RcNtf'">
{{ contact(message.senderUserId).name }} 撤回了一条消息 {{ contact(message.senderUserId).name }} 撤回了一条消息
</view> </view>
<view class="notify" v-else-if="message.objectName === 'RC:InfoNtf'">
{{ message.sentTime|timeCustomCN }}
</view>
<view v-else :class="['cell-item', message.messageDirection == 1 ? 'right' : 'left']"> <view v-else :class="['cell-item', message.messageDirection == 1 ? 'right' : 'left']">
<u-avatar class="avatar" @click="toUser(message)" :size="avatarSize" shape="square" <u-avatar class="avatar" @click="toUser(message)" :size="avatarSize" shape="square"
:src="contact(message.senderUserId).portraitUrl" /> :src="contact(message.senderUserId).portraitUrl" />
@@ -15,7 +18,9 @@
<show-text v-if="message.objectName === 'RC:TxtMsg'" :message="message" :isGroup="isGroup" /> <show-text v-if="message.objectName === 'RC:TxtMsg'" :message="message" :isGroup="isGroup" />
<show-voice v-else-if="message.objectName === 'RC:HQVCMsg'" :message="message" :isGroup="isGroup" /> <show-voice v-else-if="message.objectName === 'RC:HQVCMsg'" :message="message" :isGroup="isGroup" />
<show-image v-else-if="message.objectName === 'RC:ImgMsg'" :message="message" :isGroup="isGroup" /> <show-image v-else-if="message.objectName === 'RC:ImgMsg'" :message="message" :isGroup="isGroup" />
<show-call v-else-if="message.objectName === 'RC:InfoNtf'" :message="message" :isGroup="isGroup" /> <show-file v-else-if="message.objectName === 'RC:FileMsg'" :message="message" :isGroup="isGroup" />
<show-normal v-else-if="message.objectName === 'RC:IWNormalMsg'" :message="message" :isGroup="isGroup" />
<view v-else class=""> <view v-else class="">
[未处理的消息类型 {{ message.objectName }}] [未处理的消息类型 {{ message.objectName }}]
</view> </view>
@@ -33,7 +38,8 @@
import showVoice from './show/showVoice' import showVoice from './show/showVoice'
import showImage from './show/showImage' import showImage from './show/showImage'
import showText from './show/showText' import showText from './show/showText'
import showCall from './show/showCall' import showFile from './show/showFile'
import showNormal from './show/showNormal'
import utils from '@/utils/index.js' import utils from '@/utils/index.js'
import imBase from '../mixins/imBase.js' import imBase from '../mixins/imBase.js'
@@ -42,10 +48,11 @@
imBase imBase
], ],
components: { components: {
showCall,
showVoice, showVoice,
showImage, showImage,
showText showText,
showFile,
showNormal
}, },
props: { props: {
message: { message: {

View File

@@ -1,6 +1,7 @@
<template> <template>
<view class="chat"> <view class="chat">
<sent-message-bar :conversationType="conversationType" :targetId="targetId" @onSuccess="getNewMessage()" /> <sent-message-bar id="msgbar" :conversationType="conversationType" :targetId="targetId"
@onSuccess="getNewMessage()" />
<view class="shade" @click="hidePop" v-show="showPop"> <view class="shade" @click="hidePop" v-show="showPop">
<view class="pop" :style="popStyle" :class="{'show':showPop}"> <view class="pop" :style="popStyle" :class="{'show':showPop}">
@@ -11,7 +12,8 @@
</view> </view>
<view class="body"> <view class="body">
<view class="scroll"> <view class="place" :style="{ height: placeHeight + 'px' }"></view>
<view class="scroll" id="scroll">
<view class="cell" v-for="(message, index) in messages" :key="index"> <view class="cell" v-for="(message, index) in messages" :key="index">
<show-message-cell :message="message" isGroup @messageAction="messageAction" /> <show-message-cell :message="message" isGroup @messageAction="messageAction" />
</view> </view>
@@ -51,7 +53,9 @@
messages: [], messages: [],
groupInfo: { groupInfo: {
name: '' name: ''
} },
placeHeight: uni.getSystemInfoSync().windowHeight,
bottomHeihgt: 56
} }
}, },
computed: { computed: {
@@ -69,6 +73,20 @@
this.initGroupInfo() this.initGroupInfo()
}, },
onLoad(e) { onLoad(e) {
const query = uni.createSelectorQuery().in(this);
this.$nextTick(function() {
query.select('#msgbar').boundingClientRect(bottom => {
this.bottomHeihgt = bottom.height
}).exec();
})
// 监听键盘高度变化
uni.onKeyboardHeightChange(keyboard => {
query.select('#scroll').boundingClientRect(scroll => {
const placeHeight = this.windowHeight - scroll.height - keyboard.height - this
.bottomHeihgt
this.placeHeight = placeHeight > 0 ? placeHeight : 0
}).exec();
})
this.targetId = e.targetId this.targetId = e.targetId
// 获取历史消息列表 // 获取历史消息列表
this.getMessageList() this.getMessageList()
@@ -138,14 +156,25 @@
this.$refs.messageBar.onHidePopus() this.$refs.messageBar.onHidePopus()
}, },
getNewMessage() { getNewMessage() {
if (new Date().getTime() - this.latestMessage.sentTime > 18000000) {
// 在本地插入一条时间的消息
const messageContent = {
objectName: 'RC:InfoNtf',
message: 'DateInfo'
}
RongIMLib.insertOutgoingMessage(this.conversationType, this.targetId, 50, messageContent, 0)
}
im.getMessageList( im.getMessageList(
this.conversationType, this.conversationType,
this.targetId, this.targetId,
this.latestMessage.sentTime, this.latestMessage.sentTime || 0,
10, 10,
false, false,
(messages) => { (messages) => {
this.messages.unshift(...messages) console.log(messages);
//
this.messages.unshift(...messages.reverse())
this.scrollBottom() this.scrollBottom()
}) })
}, },
@@ -158,12 +187,9 @@
20, 20,
true, true,
(messages) => { (messages) => {
console.log('获取消息列表', messages);
const msgs = messages.filter(item => item.receivedStatus == 0) const msgs = messages.filter(item => item.receivedStatus == 0)
console.log('未读消息', msgs);
if (msgs.length) { if (msgs.length) {
RongIMLib.sendReadReceiptResponse(3, this.targetId, msgs, (res) => { RongIMLib.sendReadReceiptResponse(3, this.targetId, msgs, (res) => {
console.error('发送群聊已读回执成功', res);
msgs.map(item => { msgs.map(item => {
RongIMLib.setMessageReceivedStatus(item.messageId, 1) RongIMLib.setMessageReceivedStatus(item.messageId, 1)
}) })

View File

@@ -20,8 +20,15 @@
</view> </view>
<!-- content --> <!-- content -->
<view v-if="$store.state.token !== ''"> <view v-if="$store.state.token !== ''">
<connection-status :connection="connection" /> <block v-if="conversations.length>0">
<conversation-list @refresh="getConversationList()" :conversations="conversations" /> <connection-status :connection="connection" />
<conversation-list @refresh="getConversationList()" :conversations="conversations" />
</block>
<view class="no-lists" v-else>
<u-image class="cover" radius="4" width="500rpx" height="500rpx"
:src="require('@/static/imgs/no-new-news.png')" :lazy-load="true" />
<span> 空空如也~</span>
</view>
</view> </view>
<!-- 未登录 --> <!-- 未登录 -->
<view v-else class="vertical null-list"> <view v-else class="vertical null-list">
@@ -55,6 +62,11 @@
connectionStatus connectionStatus
}, },
onLoad() { onLoad() {
RongIMLib.getCurrentUserId(({
userId
}) => {
console.log('getCurrentUserId', userId);
})
// 监听新的好友申请 // 监听新的好友申请
uni.$on('onNewContactConversation', () => { uni.$on('onNewContactConversation', () => {
console.log('更新好友申请数量'); console.log('更新好友申请数量');
@@ -107,7 +119,7 @@
conversations conversations
}) => { }) => {
if (code === 0) { if (code === 0) {
console.log(conversations,',,,,,') console.log('获取会话列表', conversations);
this.conversations = conversations this.conversations = conversations
} }
}) })
@@ -215,4 +227,21 @@
.u-border-bottom { .u-border-bottom {
border-bottom: solid 1rpx #f9f9f9 !important; border-bottom: solid 1rpx #f9f9f9 !important;
} }
.no-lists {
min-height: 80vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: $title-size-m;
color: $text-gray-m;
.cover{
opacity: 0.8!important;
}
span {
padding-top: $padding;
}
}
</style> </style>

View File

@@ -12,6 +12,9 @@ export default {
}, },
sender() { sender() {
return this.$store.getters.sender return this.$store.getters.sender
},
windowHeight() {
return uni.getSystemInfoSync().windowHeight
} }
}, },
methods: { methods: {

View File

@@ -133,23 +133,7 @@
methods: { methods: {
afterHangup() { afterHangup() {
clearInterval(this.interval) clearInterval(this.interval)
const targetId = this.targetId // duration: this.duration
const sentStatus = 30
const messageContent = {
objectName: 'RC:InfoNtf',
userInfo: this.$store.getters.sender,
message: JSON.stringify({
mediaType: this.mediaType,
connected: this.connected,
duration: this.duration
})
}
const sentTime = 0
if (this.isCall) {
IMLib.insertOutgoingMessage(1, targetId, sentStatus, messageContent, sentTime)
} else {
IMLib.insertIncomingMessage(1, targetId, targetId, sentStatus, messageContent, sentTime)
}
uni.$emit('onReceiveMessage_' + this.targetId, { uni.$emit('onReceiveMessage_' + this.targetId, {
targetId: this.targetId targetId: this.targetId
}) })

View File

@@ -1,6 +1,7 @@
<template> <template>
<view class="chat"> <view class="chat">
<sent-message-bar :conversationType="conversationType" :targetId="targetId" @onSuccess="getNewMessage()" /> <sent-message-bar id="msgbar" :conversationType="conversationType" :targetId="targetId"
@onSuccess="getNewMessage()" />
<view class="shade" @click="hidePop" v-show="showPop"> <view class="shade" @click="hidePop" v-show="showPop">
<view class="pop" :style="popStyle" :class="{'show':showPop}"> <view class="pop" :style="popStyle" :class="{'show':showPop}">
<view v-for="(item, index) in popButton" :key="index" @click="pickerMenu(item)"> <view v-for="(item, index) in popButton" :key="index" @click="pickerMenu(item)">
@@ -10,7 +11,8 @@
</view> </view>
<!-- chat --> <!-- chat -->
<view class="body"> <view class="body">
<view class="scroll"> <view class="place" :style="{ height: placeHeight + 'px' }"></view>
<view class="scroll" id="scroll">
<view class="cell" v-for="(message, index) in messages" :key="index"> <view class="cell" v-for="(message, index) in messages" :key="index">
<show-message-cell :message="message" @messageAction="messageAction" /> <show-message-cell :message="message" @messageAction="messageAction" />
</view> </view>
@@ -46,7 +48,9 @@
name: '', name: '',
userId: '', userId: '',
portraitUrl: '' portraitUrl: ''
} },
placeHeight: uni.getSystemInfoSync().windowHeight,
bottomHeihgt: 56
} }
}, },
computed: { computed: {
@@ -66,6 +70,20 @@
}) })
}, },
onLoad(e) { onLoad(e) {
const query = uni.createSelectorQuery().in(this);
this.$nextTick(function() {
query.select('#msgbar').boundingClientRect(bottom => {
this.bottomHeihgt = bottom.height
}).exec();
})
// 监听键盘高度变化
uni.onKeyboardHeightChange(keyboard => {
query.select('#scroll').boundingClientRect(scroll => {
const placeHeight = this.windowHeight - scroll.height - keyboard.height - this
.bottomHeihgt
this.placeHeight = placeHeight > 0 ? placeHeight : 0
}).exec();
})
this.targetId = e.targetId this.targetId = e.targetId
this.userInfo = this.$store.getters.contactInfo(this.targetId) this.userInfo = this.$store.getters.contactInfo(this.targetId)
// 获取消息列表 // 获取消息列表
@@ -106,6 +124,9 @@
}) })
}, },
onUnload() { onUnload() {
uni.offKeyboardHeightChange(res => {
console.log('卸载监听键盘高度变化', res);
})
uni.$off('onUserDelete_' + this.targetId) uni.$off('onUserDelete_' + this.targetId)
uni.$off('onReceiveMessage_' + this.targetId) uni.$off('onReceiveMessage_' + this.targetId)
uni.$off('onRecallMessage_' + this.targetId) uni.$off('onRecallMessage_' + this.targetId)
@@ -114,19 +135,30 @@
}, },
onNavigationBarButtonTap() { onNavigationBarButtonTap() {
uni.navigateTo({ uni.navigateTo({
url:'/pages/im/friends/info?targetId='+this.targetId url: '/pages/im/friends/info?targetId=' + this.targetId
}) })
}, },
methods: { methods: {
getNewMessage() { getNewMessage() {
if (new Date().getTime() - this.latestMessage.sentTime > 18000000) {
// 在本地插入一条时间的消息
const messageContent = {
objectName: 'RC:InfoNtf',
message: 'DateInfo'
}
RongIMLib.insertOutgoingMessage(this.conversationType, this.targetId, 50, messageContent, 0)
}
im.getMessageList( im.getMessageList(
this.conversationType, this.conversationType,
this.targetId, this.targetId,
this.latestMessage.sentTime || 0, this.latestMessage.sentTime || 0,
1, 10,
false, false,
(messages) => { (messages) => {
this.messages.unshift(...messages) console.log(messages);
//
this.messages.unshift(...messages.reverse())
this.scrollBottom() this.scrollBottom()
}) })
}, },
@@ -160,6 +192,8 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.place {}
/* 窗口 */ /* 窗口 */
.chat { .chat {
background: $window-color; background: $window-color;

BIN
static/imgs/map.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
static/imgs/no-new-news.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@@ -41,6 +41,7 @@ export default {
updateContactInfo(state, contactInfo) { updateContactInfo(state, contactInfo) {
Vue.set(state.contacts, contactInfo.targetId, contactInfo) Vue.set(state.contacts, contactInfo.targetId, contactInfo)
}, },
// 设置我的资料
setSenderInfo(state, contactInfo) { setSenderInfo(state, contactInfo) {
state.myInfo = { state.myInfo = {
userId: contactInfo.targetId, userId: contactInfo.targetId,
@@ -69,8 +70,11 @@ export default {
}) })
}, },
setSenderInfo({ setSenderInfo({
commit commit,
dispatch
}, contactInfo) { }, contactInfo) {
contactInfo.type = 0 // type 更改为0标记是我自己
dispatch('updateContact', contactInfo)
commit('setSenderInfo', contactInfo) commit('setSenderInfo', contactInfo)
}, },
// 载入好友信息 // 载入好友信息

View File

@@ -73,6 +73,7 @@ const connect = (token, userInfo, callback) => {
key: FK, key: FK,
success: () => { success: () => {
contactModel.find((err, results) => { contactModel.find((err, results) => {
console.log('初始化联系人信息', results);
results.map(item => { results.map(item => {
store.dispatch('launchContact', item) store.dispatch('launchContact', item)
}) })

View File

@@ -55,7 +55,8 @@ const notifyMsgTypes = [
IMLib.ObjectName.Location, IMLib.ObjectName.Location,
IMLib.ObjectName.Voice, IMLib.ObjectName.Voice,
IMLib.ObjectName.HQVoice, IMLib.ObjectName.HQVoice,
IMLib.ObjectName.Sight IMLib.ObjectName.Sight,
'RC:IWNormalMsg'
] ]
const imLibListeners = () => { const imLibListeners = () => {

View File

@@ -18,7 +18,8 @@ const getMessageList = (conversationType, targetId, timeStamp, count, isForward,
'RC:CombineMsg', 'RC:CombineMsg',
'RC:GrpNtf', 'RC:GrpNtf',
'RC:InfoNtf', 'RC:InfoNtf',
'RC:RcNtf' 'RC:RcNtf',
'RC:IWNormalMsg'
] ]
RongIMLib.getHistoryMessagesByTimestamp( RongIMLib.getHistoryMessagesByTimestamp(
@@ -80,35 +81,23 @@ const getGroupPendinglist = (targetId, callback) => {
* @param {string} content 消息内容 * @param {string} content 消息内容
* @param {function} callback 回调函数 * @param {function} callback 回调函数
*/ */
const sentText = (conversationType, targetId, content, user, callback) => { const sentText = (conversationType, targetId, content) => {
const msg = { return new Promise((resolve, reject) => {
conversationType: conversationType, const message = {
targetId: String(targetId), conversationType: conversationType,
content: { targetId: String(targetId),
objectName: 'RC:TxtMsg', content: {
content: content, objectName: 'RC:TxtMsg',
userInfo: user content: content,
} userInfo: store.getters.sender
}
RongIMLib.sendMessage(msg, ({
code,
messageId
}) => {
if (code === 0) {
if (conversationType == 3) {
RongIMLib.sendReadReceiptRequest(messageId, (res) => {
console.log('发送回执请求', res);
})
} }
callback(messageId)
} else {
console.log('发送失败', msg);
uni.showToast({
icon: 'none',
title: '发送失败' + code
})
} }
sendCommonMessage(message, (messageId) => {
resolve(messageId)
}, (errCode) => {
reject(errCode)
})
}) })
} }
@@ -118,111 +107,199 @@ const sentText = (conversationType, targetId, content, user, callback) => {
* @param {string} targetId 会话id * @param {string} targetId 会话id
* @param {string} voiceUrl 录音的本地路径 * @param {string} voiceUrl 录音的本地路径
* @param {integer} time 录音时长 * @param {integer} time 录音时长
* @param {function} callback 录音时长 * @param {function} user 本人信息
*/ */
const sentVoice = (conversationType, targetId, voiceUrl, time, user, callback) => { const sentVoice = (conversationType, targetId, voiceUrl, time) => {
const msg = { return new Promise((resolve, reject) => {
conversationType: conversationType, const msg = {
targetId: String(targetId), conversationType: conversationType,
content: { targetId: String(targetId),
objectName: 'RC:HQVCMsg', content: {
local: 'file:///' + plus.io.convertLocalFileSystemURL(voiceUrl), objectName: 'RC:HQVCMsg',
duration: time == 0 ? 1 : time, local: 'file://' + plus.io.convertLocalFileSystemURL(voiceUrl),
userInfo: user duration: time == 0 ? 1 : time,
} userInfo: store.getters.sender
} }
RongIMLib.sendMediaMessage(msg, {
success: (messageId) => {
callback(messageId);
},
progress: (progress, messageId) => {
console.log(messageId);
},
cancel: (messageId) => {
// 发送取消回调
},
error: (errorCode, messageId) => {
console.log(errorCode, messageId);
} }
RongIMLib.sendMediaMessage(msg, {
success: (messageId) => {
if (conversationType == 3) {
RongIMLib.sendReadReceiptRequest(messageId)
}
resolve(messageId)
},
progress: (progress, messageId) => {},
cancel: (messageId) => {},
error: (errorCode, messageId) => {
reject(errorCode)
}
})
}) })
} }
const sentImage = (conversationType, targetId, imageUrl, user, callback) => { // 发送的图片可能会涉及到一次多张用Promise来确保前端一次性清算
const msg = { const sentImage = (conversationType, targetId, imageUrl) => {
conversationType: conversationType, return new Promise((resolve, reject) => {
targetId: String(targetId), uni.getImageInfo({
content: { src: imageUrl,
objectName: 'RC:ImgMsg', success: (imgInfo) => {
local: 'file:///' + plus.io.convertLocalFileSystemURL(imageUrl), const msg = {
userInfo: user conversationType: conversationType,
} targetId: String(targetId),
} content: {
RongIMLib.sendMediaMessage(msg, { objectName: 'RC:ImgMsg',
success: (messageId) => { local: imgInfo.path,
callback(messageId); userInfo: store.getters.sender
}, }
progress: (progress, messageId) => { }
console.log(messageId); RongIMLib.sendMediaMessage(msg, {
}, success: (messageId) => {
cancel: (messageId) => { if (conversationType == 3) {
// 发送取消回调 RongIMLib.sendReadReceiptRequest(messageId)
}, }
error: (errorCode, messageId) => { resolve(messageId)
console.log(errorCode, messageId); },
} progress: (progress, messageId) => {},
cancel: (messageId) => {},
error: (errorCode, messageId) => {
reject(errorCode)
}
})
}
})
}) })
} }
const sentGif = (conversationType, targetId, gifUrl, time, user, callback) => { const sentFile = (conversationType, targetId, fileUrl) => {
const msg = { return new Promise((resolve, reject) => {
conversationType: conversationType, const msg = {
targetId: String(targetId), conversationType: conversationType,
content: { targetId: String(targetId),
objectName: 'RC:GIFMsg', content: {
local: 'file:///' + plus.io.convertLocalFileSystemURL(gifUrl), objectName: 'RC:FileMsg',
duration: time, local: plus.io.convertLocalFileSystemURL(fileUrl),
userInfo: user userInfo: store.getters.sender
} }
}
RongIMLib.sendMediaMessage(msg, {
success: (messageId) => {
callback(messageId);
},
progress: (progress, messageId) => {
console.log(messageId);
},
cancel: (messageId) => {
// 发送取消回调
},
error: (errorCode, messageId) => {
console.log(errorCode, messageId);
} }
RongIMLib.sendMediaMessage(msg, {
success: (messageId) => {
if (conversationType == 3) {
RongIMLib.sendReadReceiptRequest(messageId)
}
resolve(messageId)
},
progress: (progress, messageId) => {},
cancel: (messageId) => {},
error: (errorCode, messageId) => {
reject(errorCode)
}
})
}) })
} }
const sendFile = (conversationType, targetId, fileUrl, time, user, callback) => { // 发送地理位置
const msg = { const sentLocation = (conversationType, targetId, location, thumbnail) => {
conversationType: conversationType, return new Promise((resolve, reject) => {
targetId: String(targetId), const message = {
content: { conversationType: conversationType,
objectName: 'RC:FileMsg', targetId: String(targetId),
local: 'file:///' + plus.io.convertLocalFileSystemURL(fileUrl), content: {
duration: time, customType: 2,
userInfo: user objectName: 'RC:LBSMsg',
customFields: {
name: location.name,
address: location.address,
latitude: Number(location.latitude),
longitude: Number(location.longitude),
thumbnail: thumbnail
},
userInfo: store.getters.sender,
}
} }
}
RongIMLib.sendMediaMessage(msg, { sendCommonMessage(message, (messageId) => {
success: (messageId) => { resolve(messageId)
callback(messageId); }, (errCode) => {
}, reject(errCode)
progress: (progress, messageId) => { })
console.log(messageId); })
}, }
cancel: (messageId) => {
// 发送取消回调 /**
}, * 发送视频通话结果
error: (errorCode, messageId) => { */
console.log(errorCode, messageId); const sentVideo = (conversationType, targetId, status, time) => {
return new Promise((resolve, reject) => {
const message = {
conversationType: conversationType,
targetId: String(targetId),
content: {
customType: 2,
objectName: 'RC:VideoMsg',
customFields: {
status: status,
duration: time
},
userInfo: store.getters.sender,
}
}
sendCommonMessage(message, (messageId) => {
resolve(messageId)
}, (errCode) => {
reject(errCode)
})
})
}
/**
* 发送语音通话结果
*/
const sentAudio = (conversationType, targetId, status, time) => {
return new Promise((resolve, reject) => {
const message = {
conversationType: conversationType,
targetId: String(targetId),
content: {
customType: 2,
objectName: 'RC:AudioMsg',
customFields: {
status: status,
duration: time
},
userInfo: store.getters.sender,
}
}
sendCommonMessage(message, (messageId) => {
resolve(messageId)
}, (errCode) => {
reject(errCode)
})
})
}
/**
* 发送普通消息
*/
const sendCommonMessage = (message, success, fail) => {
RongIMLib.sendMessage(message, ({
code,
messageId
}) => {
if (code === 0) {
if (message.conversationType == 3) {
RongIMLib.sendReadReceiptRequest(messageId)
}
success(messageId)
} else {
uni.showToast({
icon: 'none',
title: '发送失败' + code
})
fail(code)
} }
}) })
} }
@@ -234,6 +311,8 @@ export default {
sentText, sentText,
sentVoice, sentVoice,
sentImage, sentImage,
sentGif, sentFile,
sendFile sentLocation,
sentVideo,
sentAudio
} }