Compare commits

28 Commits

Author SHA1 Message Date
e4d73085bc marge 2022-03-07 14:31:06 +08:00
ca40d790b1 聊天页面处理没有聊天内容展示 2022-03-07 14:29:37 +08:00
唐明明
aadef3c148 merge 2022-03-07 09:18:00 +08:00
81d4b9017d tongbi 2022-03-01 13:04:45 +08:00
335a3aa8d6 消息间隔30分钟,插入一条时间消息,记录消息大概的发送时间 2022-03-01 11:29:04 +08:00
9628c8ccec clean 2022-03-01 10:40:59 +08:00
dbda19870f 优化消息发送函数,设定音视频通话的记录发送规则 2022-03-01 10:40:00 +08:00
04d9d772c4 发送消息的回执请求完善 2022-02-28 16:52:37 +08:00
bce7822e51 文件消息,地理位置消息 2022-02-28 16:28:14 +08:00
39b8f158c0 更改发送消息模式为promise 2022-02-28 13:45:17 +08:00
bf94cca533 键盘高度计算,改善聊天页面内容少的时候推屏的问题,但是有点卡断 2022-02-28 12:15:11 +08:00
e8e496cf37 获取好友信息的时候,排除自己,但是还要把自己的信息加载到内存中 2022-02-28 10:26:48 +08:00
3e1275fc74 ... 2022-02-25 17:04:31 +08:00
033d0e6317 预览图片 2022-02-25 16:57:40 +08:00
fb3d8ff950 健康模块首页调整样式 2022-02-25 16:51:45 +08:00
76064b3ea2 替换个人信息页面图标 2022-02-25 16:36:42 +08:00
cd63785274 私人聊天右上角跳转到别人的介绍页面 2022-02-25 15:36:28 +08:00
唐明明
33f1899b75 merge 2022-02-25 15:20:40 +08:00
唐明明
76854d3714 修复发送文本消息成功后在次发送表情残留上次输入内容的bug 2022-02-25 15:20:17 +08:00
1b027783ea update 2022-02-25 15:15:53 +08:00
唐明明
0b61a8c7f4 merge 2022-02-25 15:13:05 +08:00
唐明明
17899df882 merge 2022-02-25 15:12:37 +08:00
c69722491c ... 2022-02-25 15:07:04 +08:00
e9184b90c1 群通知,更新群消息页面 2022-02-25 15:05:11 +08:00
748ff74731 Merge branch 'master' of https://git.yuzhankeji.cn/TmOct5/ZhHealth 2022-02-25 15:03:51 +08:00
d3b33e3c26 permission 2022-02-25 15:03:47 +08:00
唐明明
d9f379d489 merge 2022-02-25 14:50:21 +08:00
唐明明
92d43c50bc 新增表情包组件 2022-02-25 14:50:02 +08:00
39 changed files with 2196 additions and 499 deletions

BIN
.DS_Store vendored

Binary file not shown.

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.prototype.$store = store
usqlite.connect({
uni.$sql = usqlite.connect({
name: 'zh-health', // 数据库名称
path: '_doc/health.db', // 路径
}, (err, res) => {
@@ -40,7 +40,7 @@ usqlite.connect({
fail: () => {
contactModel.create((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",
"appid" : "__UNI__C29473D",
"description" : "ZH-HEALTH您手上的健康管理专家",
"versionName" : "1.0.20",
"versionName" : "1.0.22",
"versionCode" : 100,
"transformPx" : false,
/* 5+App */
@@ -47,6 +47,7 @@
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<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_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
@@ -59,7 +60,15 @@
"autoSdkPermissions" : true
},
/* ios */
"ios" : {},
"ios" : {
"privacyDescription" : {
"NSMicrophoneUsageDescription" : "发送语音消息以及音视频通话",
"NSCameraUsageDescription" : "发送图文消息以及视频通话",
"NSPhotoLibraryUsageDescription" : "发送图文消息",
"NSPhotoLibraryAddUsageDescription" : "保存图片消息",
"NSLocationWhenInUseUsageDescription" : "发送当前位置信息"
}
},
/* SDK */
"sdkConfigs" : {
"oauth" : {
@@ -104,33 +113,33 @@
},
"icons" : {
"android" : {
"hdpi" : "",
"xhdpi" : "",
"xxhdpi" : "",
"xxxhdpi" : ""
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "",
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "",
"app@2x" : "",
"notification" : "",
"notification@2x" : "",
"proapp@2x" : "",
"settings" : "",
"settings@2x" : "",
"spotlight" : "",
"spotlight@2x" : ""
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "",
"app@3x" : "",
"notification@2x" : "",
"notification@3x" : "",
"settings@2x" : "",
"settings@3x" : "",
"spotlight@2x" : "",
"spotlight@3x" : ""
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},

View File

@@ -373,6 +373,18 @@
{
"path": "pages/im/private/chat",
"style": {
"navigationBarTitleText": "",
"app-plus": {
"titleNView": {
"type": "default",
"buttons": [{
"float": "right",
"fontSrc": "/static/iconfont.ttf",
"text": "\ue607",
"fontSize": "20px"
}]
}
}
}
},
{
@@ -418,7 +430,7 @@
"path": "pages/im/friends/info",
"name": "imFriendsInfo",
"style": {
"navigationBarTitleText": "用户资料"
"navigationBarTitleText": ""
}
},
{

BIN
pages/.DS_Store vendored

Binary file not shown.

View File

@@ -7,33 +7,36 @@
<view class="preview" v-if="msg.objectName=='RC:TxtMsg'">
<text v-if="conversationType == 3">{{ user.name }}</text>{{ msg.content || '' }}
</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>[语音]
</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>[图片]
</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>[表情]
</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>[文件]
</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>[位置]
</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>[语音通话]
</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>[视频通话]
</view>
<view class="preview" v-if="msg.objectName=='RC:GrpNtf'">
<view class="preview" v-else-if="msg.objectName=='RC:GrpNtf'">
[{{ msg.message }}]
</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> 撤回了一条消息
</view>
<view class="preview" v-else>
{{ msg.objectName }}
</view>
</block>
</view>
</template>

View File

@@ -0,0 +1,87 @@
<template>
<view class="emoji--lay" v-show="show">
<scroll-view class="scroll" :scroll-y="true">
<view class="emoji-flex">
<view class="item" v-for="(item, index) in emojiArr" :key="index" @click="$emit('onEmoji', item)">
{{item.emoji}}
</view>
</view>
</scroll-view>
<view class="tool">
<!-- <view class="item" @click="$emit('delete')">删除</view> -->
<view class="item sent" @click="$emit('sent')">发送</view>
</view>
</view>
</template>
<script>
import emoji from '@/static/im/emoji'
export default {
props: {
show: {
type: Boolean,
default: () => {
return false
}
}
},
data() {
return {
emojiArr: emoji
}
}
}
</script>
<style lang="scss" scoped>
.emoji--lay {
height: 600rpx;
position: relative;
.scroll {
height: 600rpx;
.emoji-flex {
padding: 15rpx 15rpx 120rpx;
display: flex;
flex-wrap: wrap;
.item {
margin: 10rpx 15rpx;
font-size: 52rpx;
width: calc(12.5% - 30rpx);
box-sizing: border-box;
}
}
}
.tool {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-image: linear-gradient(to top, #FFF, rgba(255, 255, 255, .0));
display: flex;
justify-content: flex-end;
padding: 20rpx 30rpx 30rpx;
.item {
line-height: 70rpx;
border-radius: 35rpx;
width: 140rpx;
text-align: center;
font-size: 28rpx;
margin-left: 20rpx;
background: white;
border: solid 1rpx #f5f5f5;
box-sizing: border-box;
&.sent {
border-color: #34CE98;
background: #34CE98;
color: white;
}
}
}
}
</style>

View File

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

View File

@@ -1,7 +1,7 @@
<template>
<view class="sent--text">
<input class="input" type="text" :auto-blur="true" @focus="focus" @blur="blur" :focus="focusState"
v-model="inputTxt" confirm-type="send" @confirm="sent" cursor-spacing="10" />
<input class="input" type="text" :auto-blur="true" :focus="focusState" v-model="inputTxt" confirm-type="send"
cursor-spacing="10" @focus="focus" @blur="blur" @confirm="sent" />
</view>
</template>
@@ -27,7 +27,7 @@
computed: {
disabled() {
return this.inputTxt.length === 0
}
},
},
mounted() {
RongIMLib.getTextMessageDraft(this.conversationType, this.targetId, ({
@@ -46,10 +46,16 @@
inputTxt: ''
}
},
created() {
uni.$on('emojiValue', res => {
this.inputTxt = res.value
})
},
methods: {
sent() {
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)
this.$emit('success')
this.inputTxt = ''
@@ -59,10 +65,13 @@
focus() {
this.$emit('focus')
},
blur() {
blur(e) {
uni.hideKeyboard()
this.$emit('blur')
this.$emit('blur', e.detail)
}
},
destroyed() {
uni.$off('emojiValue')
}
}
</script>
@@ -72,10 +81,11 @@
display: flex;
flex-direction: row;
justify-content: space-between;
.input {
background: #F3F6FB;
height: 70rpx;
width: 460rpx;
width: 400rpx;
border-radius: 10rpx;
margin-right: 15rpx;
padding: 0 20rpx;

View File

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

View File

@@ -7,11 +7,19 @@
<image class="icon" src="@/static/icon/msg-icon.png" v-if="chatType === 1" mode="widthFix" />
</view>
<sent-voice v-if="chatType === 0" :conversationType="conversationType" :targetId="targetId" @success="onSuccess" />
<sent-text v-if="chatType === 1" :conversationType="conversationType" :targetId="targetId" @success="onSuccess" />
<view class="msg-type msg-popups" @click="showPopups = !showPopups"> <image class="icon" src="@/static/icon/popups-icon.png" /> </view>
<sent-text ref="textView" v-if="chatType === 1" :conversationType="conversationType" :targetId="targetId" @success="onSuccess" @blur="onBlur" />
<view class="msg-type msg-popups" @click="onShowEmoji">
<image class="icon" src="@/static/icon/emoji-icon.png" />
<!-- 考虑唤起键盘暂时保留v-show -->
<!-- <image v-show="!showEmoji" class="icon" src="@/static/icon/emoji-icon.png" /> -->
<!-- <image v-show="showEmoji" class="icon" src="@/static/icon/key-icon.png" /> -->
</view>
<view class="msg-type msg-popups" @click="() => {showPopups = !showPopups, showEmoji = false}"> <image class="icon" src="@/static/icon/popups-icon.png" /> </view>
</view>
<!-- 弹出层 -->
<sent-popups :show="showPopups" :conversationType="conversationType" :targetId="targetId" @success="() => {showPopups = false, onSuccess()}" />
<!-- 表情包 -->
<sent-emoji :show="showEmoji" @onEmoji="onEmoji" @delete="onDelete" @sent="onSent"></sent-emoji>
</view>
</template>
@@ -19,6 +27,7 @@
import sentText from './sent/sentText'
import sentVoice from './sent/sentVoice'
import sentPopups from './sent/sentPopups'
import sentEmoji from './sent/sentEmoji'
export default {
props: {
@@ -34,27 +43,69 @@
components: {
sentText,
sentVoice,
sentPopups
sentPopups,
sentEmoji
},
data() {
return {
chatType: 1, // 0 语音1 文本
showPopups: false
chatType : 1, // 0 语音1 文本
showPopups : false,
showEmoji : false,
chatText : {
value : "",
cursor : 0
}
}
},
methods: {
// 切换聊天类型,语音/文本
changeMessageType() {
this.chatType = this.chatType === 1 ? 0 : 1
if(this.showEmoji) this.showEmoji = false
if(this.showPopups) this.showPopups = false
},
onSuccess() {
this.$emit('onSuccess')
this.chatText = { value: "", cursor: 0}
},
// 处理弹出层
onHidePopus(){
if(this.showPopups){
this.showPopups = false
}
},
// 输入表情
onEmoji(e){
let atMsg = this.chatText
let newMsg = () => {
return atMsg.value.slice(0, atMsg.cursor) + e.emoji + atMsg.value.slice(atMsg.cursor)
}
atMsg.value = newMsg()
atMsg.cursor += 2
// 全局通讯
uni.$emit('emojiValue', atMsg)
},
// 删除表情
onDelete(){
console.log('删除')
},
// 发送消息
onSent(){
this.$refs.textView.sent()
this.chatText = {
value : "",
cursor : 0
}
},
// 获取输入框文字最新状态
onBlur(e){
this.chatText = e
},
// 显示emoji表情
onShowEmoji(){
this.showEmoji = !this.showEmoji
this.chatType = 1
if(this.showPopups) this.showPopups = false
}
}
}

View File

@@ -2,8 +2,7 @@
<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" v-if="msg.mediaType == 1" />
<uni-icons type="phone" size="40rpx" v-else />
<uni-icons type="phone" size="44rpx" />
{{ label }}
</view>
</view>
@@ -18,7 +17,6 @@
mixins: [
imBase
],
name: 'showText',
props: {
message: {
type: Object,
@@ -31,23 +29,18 @@
default: false
}
},
mounted() {
},
computed: {
msg() {
return JSON.parse(this.message.content.message)
},
label() {
return this.msg.connected ? '通话时长:' + duration : '未接通'
return this.message.content.customFields.status == 1 ? '通话时长:' + duration : '未接通'
},
isRemote() {
return this.message.messageDirection == 2
},
duration() {
if (this.message.duration > 3600) {
return moment.utc(this.message.duration * 1000).format('HH:mm:ss')
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.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'">
{{ contact(message.senderUserId).name }} 撤回了一条消息
</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']">
<u-avatar class="avatar" @click="toUser(message)" :size="avatarSize" shape="square"
:src="contact(message.senderUserId).portraitUrl" />
@@ -15,7 +18,9 @@
<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-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="">
[未处理的消息类型 {{ message.objectName }}]
</view>
@@ -33,7 +38,8 @@
import showVoice from './show/showVoice'
import showImage from './show/showImage'
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 imBase from '../mixins/imBase.js'
@@ -42,10 +48,11 @@
imBase
],
components: {
showCall,
showVoice,
showImage,
showText
showText,
showFile,
showNormal
},
props: {
message: {

View File

@@ -3,9 +3,10 @@
<!-- 用户信息 -->
<view class="info-flex">
<u-avatar :src="userInfo.portraitUrl || require('@/static/user/cover.png')" shape="square"
:size="rpx2px(100)" bg-color="#fff"></u-avatar>
:size="rpx2px(100)" bg-color="#fff" @click="previeImg(userInfo.portraitUrl)" />
<view class="info-text">
<view class="nickname">{{ contact(targetId).name }} ({{ userInfo.name }})</view>
<view class="nickname">{{ contact(targetId).name }} </view>
<view class="address" @longpress="copyAddress">昵称{{ userInfo.name }}</view>
<view class="address" @longpress="copyAddress">地址{{ userInfo.address }}</view>
</view>
</view>
@@ -37,7 +38,7 @@
<view class="footer">
<view class="footer-item" @click="deleteFriend">
<view class="icon">
<u-icon class="icon-u" name="close-circle-fill" color="#fff" size="30" />
<u-icon class="icon-u" name="minus-people-fill" color="#fff" size="30" />
</view>
<view class="text">删除好友</view>
</view>
@@ -49,7 +50,7 @@
</view>
<view class="footer-item" @click="callShow = true">
<view class="icon">
<u-icon class="icon-u" name="camera-fill" color="#fff" size="30" />
<u-icon class="icon-u" :name="require('@/static/imgs/tel-call.png')" color="#fff" size="30" />
</view>
<view class="text">/视频通话</view>
</view>
@@ -127,9 +128,9 @@
this.userInfo = res
// 获取到用户信息之后,去检查一下要不要更新
this.$store.dispatch('updateContact', res)
uni.setNavigationBarTitle({
title: res.name
})
// uni.setNavigationBarTitle({
// title: res.name
// })
})
RongIMLib.getConversationNotificationStatus(this.conversationType, this.targetId, ({
status
@@ -157,6 +158,11 @@
}
})
},
previeImg(url){
uni.previewImage({
urls:[url]
})
},
toPrivate() {
uni.navigateTo({
url: '/pages/im/private/chat?targetId=' + this.targetId
@@ -310,7 +316,7 @@
bottom: 0;
left: 0;
right: 0;
padding: $padding*2 $padding;
padding: $padding*2 $padding * 2 $padding*4 $padding *2;
display: flex;
justify-content: space-around;

View File

@@ -2,8 +2,7 @@
<view class="pending">
<u-sticky>
<view class="header-search" @click="$Router.push({ name: 'SearchFriend' })">
<u-search placeholder="输入手机号搜索" searchIcon="search" inputAlign="center" bgColor="white"
:disabled="true" :show-action="false" />
<u-search placeholder=" 用户名/手机号搜索新朋友" searchIcon="search" inputAlign="center" bgColor="white" :disabled="true" :show-action="false" />
</view>
</u-sticky>
<block v-if="pendings.length > 0">

View File

@@ -1,6 +1,7 @@
<template>
<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="pop" :style="popStyle" :class="{'show':showPop}">
@@ -11,7 +12,8 @@
</view>
<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">
<show-message-cell :message="message" isGroup @messageAction="messageAction" />
</view>
@@ -51,7 +53,9 @@
messages: [],
groupInfo: {
name: ''
}
},
placeHeight: uni.getSystemInfoSync().windowHeight,
bottomHeihgt: 56
}
},
computed: {
@@ -69,6 +73,20 @@
this.initGroupInfo()
},
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.getMessageList()
@@ -138,14 +156,25 @@
this.$refs.messageBar.onHidePopus()
},
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(
this.conversationType,
this.targetId,
this.latestMessage.sentTime,
this.latestMessage.sentTime || 0,
10,
false,
(messages) => {
this.messages.unshift(...messages)
console.log(messages);
//
this.messages.unshift(...messages.reverse())
this.scrollBottom()
})
},
@@ -158,12 +187,9 @@
20,
true,
(messages) => {
console.log('获取消息列表', messages);
const msgs = messages.filter(item => item.receivedStatus == 0)
console.log('未读消息', msgs);
if (msgs.length) {
RongIMLib.sendReadReceiptResponse(3, this.targetId, msgs, (res) => {
console.error('发送群聊已读回执成功', res);
msgs.map(item => {
RongIMLib.setMessageReceivedStatus(item.messageId, 1)
})

View File

@@ -138,10 +138,12 @@
color: $text-color;
padding-bottom: 6rpx;
span {
color: $text-color;
font-size: $title-size-m +1;
padding-top: 20rpx;
padding-top: $padding - 10;
}
}
@@ -150,7 +152,7 @@
color: #Fff;
text-align: center;
font-size: $title-size-m;
padding: 6rpx 20rpx;
padding: $padding - 22 $padding - 10;
border-radius: 10rpx;
margin-left: 10rpx;
}

View File

@@ -20,8 +20,15 @@
</view>
<!-- content -->
<view v-if="$store.state.token !== ''">
<connection-status :connection="connection" />
<conversation-list @refresh="getConversationList()" :conversations="conversations" />
<block v-if="conversations.length>0">
<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 v-else class="vertical null-list">
@@ -55,6 +62,11 @@
connectionStatus
},
onLoad() {
RongIMLib.getCurrentUserId(({
userId
}) => {
console.log('getCurrentUserId', userId);
})
// 监听新的好友申请
uni.$on('onNewContactConversation', () => {
console.log('更新好友申请数量');
@@ -107,7 +119,7 @@
conversations
}) => {
if (code === 0) {
console.log(conversations,',,,,,')
console.log('获取会话列表', conversations);
this.conversations = conversations
}
})
@@ -215,4 +227,21 @@
.u-border-bottom {
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>

View File

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

View File

@@ -133,23 +133,7 @@
methods: {
afterHangup() {
clearInterval(this.interval)
const targetId = this.targetId
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)
}
// duration: this.duration
uni.$emit('onReceiveMessage_' + this.targetId, {
targetId: this.targetId
})

View File

@@ -1,7 +1,7 @@
<template>
<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="pop" :style="popStyle" :class="{'show':showPop}">
<view v-for="(item, index) in popButton" :key="index" @click="pickerMenu(item)">
@@ -9,10 +9,10 @@
</view>
</view>
</view>
<!-- chat -->
<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">
<show-message-cell :message="message" @messageAction="messageAction" />
</view>
@@ -48,7 +48,9 @@
name: '',
userId: '',
portraitUrl: ''
}
},
placeHeight: uni.getSystemInfoSync().windowHeight,
bottomHeihgt: 56
}
},
computed: {
@@ -62,12 +64,28 @@
}
}
},
onLoad(e) {
this.targetId = e.targetId
this.userInfo = this.$store.getters.contactInfo(this.targetId)
onShow() {
uni.setNavigationBarTitle({
title: this.contact(this.targetId).name
})
},
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.userInfo = this.$store.getters.contactInfo(this.targetId)
// 获取消息列表
this.getMessageList()
// 监听新消息
@@ -106,22 +124,41 @@
})
},
onUnload() {
uni.offKeyboardHeightChange(res => {
console.log('卸载监听键盘高度变化', res);
})
uni.$off('onUserDelete_' + this.targetId)
uni.$off('onReceiveMessage_' + this.targetId)
uni.$off('onRecallMessage_' + this.targetId)
uni.$off('onRecallMessage')
uni.$off('onReadReceiptReceived')
},
onNavigationBarButtonTap() {
uni.navigateTo({
url: '/pages/im/friends/info?targetId=' + this.targetId
})
},
methods: {
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(
this.conversationType,
this.targetId,
this.latestMessage.sentTime || 0,
1,
10,
false,
(messages) => {
this.messages.unshift(...messages)
console.log(messages);
//
this.messages.unshift(...messages.reverse())
this.scrollBottom()
})
},
@@ -155,6 +192,8 @@
</script>
<style scoped lang="scss">
.place {}
/* 窗口 */
.chat {
background: $window-color;

View File

@@ -14,7 +14,7 @@
<!-- 头像 -->
<view class="user" @click="$Router.back()">
<u-icon name="arrow-left" color="#525252" size="22" class="downIcon" :bold="true" />
<!-- <u-image class="avatar" width="90rpx" height="90rpx" :src="user.avatar ? user.avatar : require('../../static/imgs/avatar.png')" :lazy-load="true" shape="circle" />
<!-- <u-image class="avatar" width="90rpx" height="90rpx" :src="user.avatar ? user.avatar : require('@/static/imgs/avatar.png')" :lazy-load="true" shape="circle" />
<view class="nickname">{{user.nickname}}</view> -->
<!-- <u-icon name="arrow-down-fill" color="#525252" size="10" class="downIcon" :bold="true" space="1"/> -->
</view>
@@ -42,7 +42,6 @@
<!-- 体重管理模块 -->
<view class="weight-manage">
<!-- 体重管理 -->
<!-- @click="$Router.push({name:'EssentialInfo'})" -->
<view class="manage">体重管理</view>
<!-- 单位:公斤 -->
<u-icon class="eye" name="eye" color="#fff" size="14" :bold="true" label="单位 : 公斤" labelPos="left" labelSize="12" labelColor="#fff" space="6" />
@@ -81,13 +80,13 @@
</view>
<!-- 健康测评 -->
<u-image
:src="banner.cover || require('../../static/imgs/health1.png')"
:src="banner.cover || require('@/static/imgs/health1.png')"
class="eval-img"
@click="$Router.push({ name: 'EvaluationList' })"
:lazy-load="true"
radius="10rpx"
mode="widthFix"
width="100%"
height="300rpx"
/>
<!-- 健康记录 -->
<view class="title">健康记录</view>
@@ -101,7 +100,7 @@
千卡
</view>
</view>
<u-image :src="require('../../static/imgs/eat.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" />
<u-image class="h-icon" :src="require('@/static/imgs/eat.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="150rpx" height="150rpx"/>
</view>
<view class="health-2">
<view class="health" @click="$Router.push({ name: 'Drink' })">
@@ -115,7 +114,7 @@
毫升
</view>
</view>
<u-image :src="require('../../static/imgs/drink.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="110rpx" class="h-icon" />
<u-image :src="require('@/static/imgs/drink.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="120rpx" class="h-icon" height="120rpx" />
</view>
<view class="health" @click="$Router.push({ name: 'Weight' })">
<view>
@@ -127,18 +126,18 @@
公斤
</view>
</view>
<u-image :src="require('../../static/imgs/weight.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" class="h-icon" />
<u-image :src="require('@/static/imgs/weight.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" height="140rpx" class="h-icon" />
</view>
</view>
<!-- 营养管理 -->
<view class="title">营养管理</view>
<view class="nutrition">
<view class="--item" @click="$Router.push({ name: 'VipFoods' })">
<u-icon :name="require('../../static/icon/vip.png')" size="20" :bold="true" label="会员专享食谱" labelPos="right" labelSize="16" labelColor="#525252" space="10" />
<u-icon :name="require('@/static/icon/vip.png')" size="20" :bold="true" label="会员专享食谱" labelPos="right" labelSize="16" labelColor="#525252" space="10" />
<u-icon name="arrow-right" color="#999" />
</view>
<view class="--item mt20" @click="$Router.push({ name: 'topicIndex' })">
<u-icon :name="require('../../static/icon/helper.png')" size="20" :bold="true" label="营养小助手" labelPos="right" labelSize="16" labelColor="#525252" space="10" />
<u-icon :name="require('@/static/icon/helper.png')" size="20" :bold="true" label="营养小助手" labelPos="right" labelSize="16" labelColor="#525252" space="10" />
<u-icon name="arrow-right" color="#999" />
</view>
</view>
@@ -149,7 +148,7 @@
<view class="search" >
<!-- 头像 -->
<view class="user" @click="$Router.back()">
<!-- <u-image class="avatar" width="90rpx" height="90rpx" :src="require('../../static/imgs/avatar.png')" :lazy-load="true" shape="circle" />
<!-- <u-image class="avatar" width="90rpx" height="90rpx" :src="require('@/static/imgs/avatar.png')" :lazy-load="true" shape="circle" />
<u-icon name="arrow-down-fill" color="#525252" size="10" class="downIcon" :bold="true" space="1" /> -->
<u-icon name="arrow-left" color="#525252" size="22" class="downIcon" :bold="true"/>
</view>
@@ -201,7 +200,7 @@
</view>
</view>
<!-- 健康测评 -->
<u-image :src="banner.cover || require('../../static/imgs/health1.png')" class="eval-img" @click="Login" :lazy-load="true" radius="10rpx" mode="widthFix" width="100%" />
<u-image :src="banner.cover || require('@/static/imgs/health1.png')" class="eval-img" @click="Login" :lazy-load="true" radius="10rpx" mode="widthFix" width="100%" />
<!-- 健康记录 -->
<view class="title">健康记录</view>
<view class="health" @click="Login">
@@ -210,7 +209,7 @@
<!-- <view class="h-date">--</view> -->
<view class="h-eat"><span>--</span></view>
</view>
<u-image :src="require('../../static/imgs/eat.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" />
<u-image :src="require('@/static/imgs/eat.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" />
</view>
<view class="health-2">
<view class="health" @click="Login">
@@ -219,7 +218,7 @@
<!-- <view class="h-date">--</view> -->
<view class="h-eat"><span>--</span></view>
</view>
<u-image :src="require('../../static/imgs/drink.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="110rpx" class="h-icon" />
<u-image :src="require('@/static/imgs/drink.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="110rpx" class="h-icon" />
</view>
<view class="health" @click="Login">
<view>
@@ -227,18 +226,18 @@
<!-- <view class="h-date">--</view> -->
<view class="h-eat"><span>--</span></view>
</view>
<u-image :src="require('../../static/imgs/weight.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" class="h-icon" />
<u-image :src="require('@/static/imgs/weight.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" class="h-icon" />
</view>
</view>
<!-- 营养管理 -->
<view class="title">营养管理</view>
<view class="nutrition">
<view class="--item" @click="Login">
<u-icon :name="require('../../static/icon/vip.png')" size="24" :bold="true" label="会员专享食谱" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon :name="require('@/static/icon/vip.png')" size="24" :bold="true" label="会员专享食谱" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon name="arrow-right" color="#999" />
</view>
<view class="--item mt20" @click="Login">
<u-icon :name="require('../../static/icon/helper.png')" size="24" :bold="true" label="营养小助手" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon :name="require('@/static/icon/helper.png')" size="24" :bold="true" label="营养小助手" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon name="arrow-right" color="#999" />
</view>
</view>
@@ -249,7 +248,7 @@
<view class="search" >
<!-- 头像 -->
<view class="user" @click='$Router.back()'>
<!-- <u-image class="avatar" width="90rpx" height="90rpx" :src="require('../../static/imgs/avatar.png')" :lazy-load="true" shape="circle" />
<!-- <u-image class="avatar" width="90rpx" height="90rpx" :src="require('@/static/imgs/avatar.png')" :lazy-load="true" shape="circle" />
<u-icon name="arrow-down-fill" color="#525252" size="10" class="downIcon" :bold="true" space="1" /> -->
<u-icon name="arrow-left" color="#525252" size="22" class="downIcon" :bold="true"/>
</view>
@@ -302,7 +301,7 @@
</view>
<!-- 健康测评 -->
<u-image
:src="banner.cover || require('../../static/imgs/health1.png')"
:src="banner.cover || require('@/static/imgs/health1.png')"
class="eval-img"
@click="toCreateInfo"
:lazy-load="true"
@@ -318,7 +317,7 @@
<!-- <view class="h-date">--</view> -->
<view class="h-eat"><span>--</span></view>
</view>
<u-image :src="require('../../static/imgs/eat.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" />
<u-image :src="require('@/static/imgs/eat.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" />
</view>
<view class="health-2">
<view class="health" @click="toCreateInfo">
@@ -327,7 +326,7 @@
<!-- <view class="h-date">--</view> -->
<view class="h-eat"><span>--</span></view>
</view>
<u-image :src="require('../../static/imgs/drink.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="110rpx" class="h-icon" />
<u-image :src="require('@/static/imgs/drink.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="110rpx" class="h-icon" />
</view>
<view class="health" @click="toCreateInfo">
<view>
@@ -335,18 +334,18 @@
<!-- <view class="h-date">--</view> -->
<view class="h-eat"><span>--</span></view>
</view>
<u-image :src="require('../../static/imgs/weight.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" class="h-icon" />
<u-image :src="require('@/static/imgs/weight.png')" :lazy-load="true" radius="10rpx" mode="widthFix" width="140rpx" class="h-icon" />
</view>
</view>
<!-- 营养管理 -->
<view class="title">营养管理</view>
<view class="nutrition">
<view class="--item" @click="toCreateInfo">
<u-icon :name="require('../../static/icon/vip.png')" size="24" :bold="true" label="会员专享食谱" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon :name="require('@/static/icon/vip.png')" size="24" :bold="true" label="会员专享食谱" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon name="arrow-right" color="#999" />
</view>
<view class="--item mt20" @click="toCreateInfo">
<u-icon :name="require('../../static/icon/helper.png')" size="24" :bold="true" label="营养小助手" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon :name="require('@/static/icon/helper.png')" size="24" :bold="true" label="营养小助手" labelPos="right" labelSize="17" labelColor="#525252" space="10" />
<u-icon name="arrow-right" color="#999" />
</view>
</view>
@@ -498,7 +497,7 @@ export default {
// 体重管理
.weight-manage {
height: 288rpx;
background-image: url(../../static/imgs/banner-bg.png);
background-image: url(@/static/imgs/banner-bg.png);
background-repeat: no-repeat;
background-size: cover;
border-radius: $radius + 1;

BIN
static/.DS_Store vendored

Binary file not shown.

BIN
static/icon/emoji-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

795
static/im/emoji.js Normal file
View File

@@ -0,0 +1,795 @@
var EmojiFactory = {
"u1F603": {
"en": "Smiley Face",
"zh": "绗戣劯",
"tag": "\uD83D\uDE03",
"position": "-75px 0px"
},
"u1F600": {
"en": "Grinning Face",
"zh": "绗戝樆鍢<E6A886>",
"tag": "\uD83D\uDE00",
"position": "0px 0px"
},
"u1F60A": {
"en": "Smiley",
"zh": "寰瑧",
"tag": "\uD83D\uDE0A",
"position": "-1725px 0px"
},
"u263A": {
"en": "Cute",
"zh": "钀岃悓鍝<E68293>",
"tag": "\u263A",
"position": "-2950px 0px"
},
"u1F609": {
"en": "Winking Face",
"zh": "鐪ㄧ溂",
"tag": "\uD83D\uDE09",
"position": "-200px 0px"
},
"u1F60D": {
"en": "Heart Eyes",
"zh": "鑹茶糠杩<E7B3A0>",
"tag": "\uD83D\uDE0D",
"position": "-1800px 0px"
},
"u1F618": {
"en": "Blowing Kiss",
"zh": "椋炲惢",
"tag": "\uD83D\uDE18",
"position": "-375px 0px"
},
"u1F61A": {
"en": "Kiss Face",
"zh": "涔堜箞鍝<E7AE9E>",
"tag": "\uD83D\uDE1A",
"position": "-1875px 0px"
},
"u1F61C": {
"en": "Crazy Face",
"zh": "璋冪毊",
"tag": "\uD83D\uDE1C",
"position": "-1900px 0px"
},
"u1F61D": {
"en": "Tongue Out",
"zh": "鍚愯垖澶<E59E96>",
"tag": "\uD83D\uDE1D",
"position": "-1925px 0px"
},
"u1F633": {
"en": "Flushed Face",
"zh": "鑴哥孩",
"tag": "\uD83D\uDE33",
"position": "-625px 0px"
},
"u1F601": {
"en": "Grinning With Smiling",
"zh": "闇查娇鑰岀瑧",
"tag": "\uD83D\uDE01",
"position": "-25px 0px"
},
"u1F614": {
"en": "Pensive",
"zh": "娌夋€<E5A48B>",
"tag": "\uD83D\uDE14",
"position": "-300px 0px"
},
"u1F60C": {
"en": "Pleased",
"zh": "婊℃剰",
"tag": "\uD83D\uDE0C",
"position": "-1775px 0px"
},
"u1F612": {
"en": "Dissatisfied",
"zh": "涓嶆弧",
"tag": "\uD83D\uDE12",
"position": "-250px 0px"
},
"u1F61F": {
"en": "Worried Face",
"zh": "鑻︾摐鑴<E69190>",
"tag": "\uD83D\uDE1F",
"position": "-1975px 0px"
},
"u1F61E": {
"en": "Disappointed Face",
"zh": "澶辨湜",
"tag": "\uD83D\uDE1E",
"position": "-1950px 0px"
},
"u1F623": {
"en": "Helpless Face",
"zh": "鏃犲姪",
"tag": "\uD83D\uDE23",
"position": "-450px 0px"
},
"u1F62D": {
"en": "Crying",
"zh": "浼ゅ績",
"tag": "\uD83D\uDE22",
"position": "-425px 0px"
},
"u1F602": {
"en": "Laughing Tears",
"zh": "鍠滄瀬鑰屾常",
"tag": "\uD83D\uDE02",
"position": "-50px 0px"
},
"u1F622": {
"en": "Sobbing",
"zh": "鍝常",
"tag": "\uD83D\uDE2D",
"position": "-2075px 0px"
},
"u1F62A": {
"en": "Sleepy Face",
"zh": "鍥<>",
"tag": "\uD83D\uDE2A",
"position": "-2000px 0px"
},
"u1F630": {
"en": "Cold Sweat",
"zh": "鍐锋睏",
"tag": "\uD83D\uDE30",
"position": "-550px 0px"
},
"u1F605": {
"en": "Happy Sweat",
"zh": "灏村艾",
"tag": "\uD83D\uDE05",
"position": "-100px 0px"
},
"u1F613": {
"en": "Sweat",
"zh": "姹<>",
"tag": "\uD83D\uDE13",
"position": "-275px 0px"
},
"u1F62B": {
"en": "Tired Face",
"zh": "鎶撶媯",
"tag": "\uD83D\uDE2B",
"position": "-2025px 0px"
},
"u1F629": {
"en": "Weary Face",
"zh": "鐤叉儷",
"tag": "\uD83D\uDE29",
"position": "-525px 0px"
},
"u1F628": {
"en": "Fearful Face",
"zh": "鍙€<EE889B>",
"tag": "\uD83D\uDE28",
"position": "-500px 0px"
},
"u1F631": {
"en": "Scream",
"zh": "灏栧彨",
"tag": "\uD83D\uDE31",
"position": "-575px 0px"
},
"u1F621": {
"en": "Angry Face",
"zh": "鐢熸皵",
"tag": "\uD83D\uDE21",
"position": "-400px 0px"
},
"u1F624": {
"en": "Mad Face",
"zh": "鎬掓皵鍐插啿",
"tag": "\uD83D\uDE24",
"position": "-475px 0px"
},
"u1F616": {
"en": "Confounded Face",
"zh": "钂欑緸",
"tag": "\uD83D\uDE16",
"position": "-350px 0px"
},
"u1F606": {
"en": "Big Grin",
"zh": "澶х瑧",
"tag": "\uD83D\uDE06",
"position": "-125px 0px"
},
"u1F60B": {
"en": "Hungry",
"zh": "棣<>",
"tag": "\uD83D\uDE0B",
"position": "-1750px 0px"
},
"u1F637": {
"en": "Mask Face",
"zh": "鍙g僵",
"tag": "\uD83D\uDE37",
"position": "-725px 0px"
},
"u1F60E": {
"en": "Sunglasses",
"zh": "澧ㄩ暅",
"tag": "\uD83D\uDE0E",
"position": "-1825px 0px"
},
"u1F634": {
"en": "Sleeping",
"zh": "鐫$湢",
"tag": "\uD83D\uDE34",
"position": "-650px 0px"
},
"u1F635": {
"en": "Dizzy Face",
"zh": "澶存檿鐪艰姳",
"tag": "\uD83D\uDE35",
"position": "-675px 0px"
},
"u1F632": {
"en": "Shocked Face",
"zh": "闇囨儕",
"tag": "\uD83D\uDE32",
"position": "-600px 0px"
},
"u1F608": {
"en": "Purple Devil",
"zh": "灏忔伓榄<E4BC93>",
"tag": "\uD83D\uDE08",
"position": "-175px 0px"
},
"u1F47F": {
"en": "Devil",
"zh": "鎭堕瓟",
"tag": "\uD83D\uDC7F",
"position": "-1600px 0px"
},
"u1F62F": {
"en": "Surprised Face",
"zh": "鎯婂憜",
"tag": "\uD83D\uDE2F",
"position": "-2100px 0px"
},
"u1F62C": {
"en": "Grimacing Face",
"zh": "鎵鑴<EE8397>",
"tag": "\uD83D\uDE2C",
"position": "-2050px 0px"
},
"u1F615": {
"en": "Confused",
"zh": "鍥版儜",
"tag": "\uD83D\uDE15",
"position": "-325px 0px"
},
"u1F636": {
"en": "Mouthless",
"zh": "鏃犲彛",
"tag": "\uD83D\uDE36",
"position": "-700px 0px"
},
"u1F607": {
"en": "Halo",
"zh": "澶╀娇鍏夌幆",
"tag": "\uD83D\uDE07",
"position": "-150px 0px"
},
"u1F60F": {
"en": "Smirking Face",
"zh": "鍌荤瑧",
"tag": "\uD83D\uDE0F",
"position": "-1850px 0px"
},
"u1F611": {
"en": "Expressionless Face",
"zh": "闈㈡棤琛ㄦ儏",
"tag": "\uD83D\uDE11",
"position": "-225px 0px"
},
"u1F648": {
"en": "See No Monkey",
"zh": "涓嶇湅",
"tag": "\uD83D\uDE48",
"position": "-2675px 0px"
},
"u1F649": {
"en": "Hear No Monkey",
"zh": "涓嶅惉",
"tag": "\uD83D\uDE49",
"position": "-2700px 0px"
},
"u1F64A": {
"en": "No Speaking",
"zh": "闂槾",
"tag": "\uD83D\uDE4A",
"position": "-2125px 0px"
},
"u1F47D": {
"en": "Alien",
"zh": "澶栨槦浜<E6A7A6>",
"tag": "\uD83D\uDC7D",
"position": "-1575px 0px"
},
"u1F4A9": {
"en": "Pile Of Poo",
"zh": "渚夸究",
"tag": "\uD83D\uDCA9",
"position": "-1025px 0px"
},
"u1F494": {
"en": "Broken Heart",
"zh": "蹇冪",
"tag": "\uD83D\uDC94",
"position": "-2600px 0px"
},
"u1F525": {
"en": "Fire",
"zh": "鐏<>",
"tag": "\uD83D\uDD25",
"position": "-2625px 0px"
},
"u1F4A2": {
"en": "Anger",
"zh": "鎰ゆ€<E38286>",
"tag": "\uD83D\uDCA2",
"position": "-950px 0px"
},
"u1F4A4": {
"en": "Zzz",
"zh": "ZZZ",
"tag": "\uD83D\uDCA4",
"position": "-1000px 0px"
},
"u1F6AB": {
"en": "Prohibited",
"zh": "绂佹",
"tag": "\uD83D\uDEAB",
"position": "-1175px 0px"
},
"u2B50": {
"en": "Star",
"zh": "鏄熸槦",
"tag": "\u2B50",
"position": "-2750px 0px"
},
"u26A1": {
"en": "Lightning Bolt",
"zh": "闂數",
"tag": "\u26A1",
"position": "-2825px 0px"
},
"u1F319": {
"en": "Drescent Moon",
"zh": "寮湀",
"tag": "\uD83C\uDF19",
"position": "-2175px 0px"
},
"u2600": {
"en": "Sunny",
"zh": "鏅存湕",
"tag": "\u2600",
"position": "-3075px 0px"
},
"u26C5": {
"en": "Cloudy",
"zh": "澶氫簯",
"tag": "\u26C5",
"position": "-2900px 0px"
},
"u2601": {
"en": "Cloud",
"zh": "浜戝僵",
"tag": "\u2601",
"position": "-3100px 0px"
},
"u2744": {
"en": "Snowflake",
"zh": "闆姳",
"tag": "\u2744",
"position": "-3175px 0px"
},
"u2614": {
"en": "Umbrella",
"zh": "闆ㄤ紴",
"tag": "\u2614",
"position": "-3125px 0px"
},
"u26C4": {
"en": "Snowman",
"zh": "闆汉",
"tag": "\u26C4",
"position": "-2875px 0px"
},
"u1F44D": {
"en": "Thumbs Up",
"zh": "璧<>",
"tag": "\uD83D\uDC4D",
"position": "-1400px 0px"
},
"u1F44E": {
"en": "Thumbs Down",
"zh": "鍠濆€掑僵",
"tag": "\uD83D\uDC4E",
"position": "-1425px 0px"
},
"u1F91D": {
"en": "Handshake",
"zh": "鎻℃墜",
"tag": "\uD83E\uDD1D",
"position": "-3200px 0px"
},
"u1F44C": {
"en": "Ok Hand",
"zh": "娌¢棶棰<E6A3B6>",
"tag": "\uD83D\uDC4C",
"position": "-1375px 0px"
},
"u1F44A": {
"en": "Raised Fist",
"zh": "涓捐捣鎷冲ご",
"tag": "\u270A",
"position": "-2975px 0px"
},
"u270A": {
"en": "Oncoming Fist",
"zh": "鍑绘嫵",
"tag": "\uD83D\uDC4A",
"position": "-1350px 0px"
},
"u270C": {
"en": "Victory Hand",
"zh": "鑰<>",
"tag": "\u270C",
"position": "-3025px 0px"
},
"u270B": {
"en": "Raised Hand",
"zh": "涓炬墜",
"tag": "\u270B",
"position": "-3000px 0px"
},
"u1F64F": {
"en": "Folded Hands",
"zh": "绁堢シ",
"tag": "\uD83D\uDE4F",
"position": "-2150px 0px"
},
"u261D": {
"en": "Pointing Up",
"zh": "绗竴",
"tag": "\u261D",
"position": "-2925px 0px"
},
"u1F44F": {
"en": "Clapping Hands",
"zh": "榧撴帉",
"tag": "\uD83D\uDC4F",
"position": "-1450px 0px"
},
"u1F4AA": {
"en": "Flexed Biceps",
"zh": "鑲岃倝",
"tag": "\uD83D\uDCAA",
"position": "-1050px 0px"
},
"u1F46A": {
"en": "Family",
"zh": "瀹跺涵",
"tag": "\uD83D\uDC6A",
"position": "-1475px 0px"
},
"u1F46B": {
"en": "Couple",
"zh": "鎯呬荆",
"tag": "\uD83D\uDC6B",
"position": "-1500px 0px"
},
"u1F47C": {
"en": "Baby Angel",
"zh": "瀹濊礉澶╀娇",
"tag": "\uD83D\uDC7C",
"position": "-1550px 0px"
},
"u1F434": {
"en": "Horse",
"zh": "椹<>",
"tag": "\uD83D\uDC34",
"position": "-2475px 0px"
},
"u1F436": {
"en": "Dog",
"zh": "鐙<>",
"tag": "\uD83D\uDC36",
"position": "-2500px 0px"
},
"u1F437": {
"en": "Pig",
"zh": "鐚<>",
"tag": "\uD83D\uDC37",
"position": "-2525px 0px"
},
"u1F47B": {
"en": "Ghost",
"zh": "楝<>",
"tag": "\uD83D\uDC7B",
"position": "-1525px 0px"
},
"u1F339": {
"en": "Rose",
"zh": "鐜懓",
"tag": "\uD83C\uDF39",
"position": "-2225px 0px"
},
"u1F33B": {
"en": "Sunflower",
"zh": "鍚戞棩钁<E6A3A9>",
"tag": "\uD83C\uDF3B",
"position": "-1250px 0px"
},
"u1F332": {
"en": "Pine Tree",
"zh": "鏉炬爲",
"tag": "\uD83C\uDF32",
"position": "-2200px 0px"
},
"u1F384": {
"en": "Christmas Tree",
"zh": "鍦癁鏍<E79981>",
"tag": "\uD83C\uDF84",
"position": "-2400px 0px"
},
"u1F381": {
"en": "Wrapped Gift",
"zh": "绀肩墿",
"tag": "\uD83C\uDF81",
"position": "-2350px 0px"
},
"u1F389": {
"en": "Party Popper",
"zh": "鑱氫細绀艰姳",
"tag": "\uD83C\uDF89",
"position": "-2425px 0px"
},
"u1F4B0": {
"en": "Money Bag",
"zh": "閽辫",
"tag": "\uD83D\uDCB0",
"position": "-1075px 0px"
},
"u1F382": {
"en": "Birthday Cake",
"zh": "鐢熸棩铔嬬硶",
"tag": "\uD83C\uDF82",
"position": "-2375px 0px"
},
"u1F356": {
"en": "Barbecue",
"zh": "BBQ",
"tag": "\uD83C\uDF56",
"position": "-2275px 0px"
},
"u1F35A": {
"en": "Cooked Rice",
"zh": "绫抽キ",
"tag": "\uD83C\uDF5A",
"position": "-1275px 0px"
},
"u1F366": {
"en": "Ice Cream",
"zh": "鍐版穱娣<E7A9B1>",
"tag": "\uD83C\uDF66",
"position": "-2300px 0px"
},
"u1F36B": {
"en": "Chocolate Bar",
"zh": "宸у厠鍔<E58EA0>",
"tag": "\uD83C\uDF6B",
"position": "-1300px 0px"
},
"u1F349": {
"en": "Watermelon",
"zh": "瑗跨摐",
"tag": "\uD83C\uDF49",
"position": "-2250px 0px"
},
"u1F377": {
"en": "Wine Glass",
"zh": "绾㈤厭",
"tag": "\uD83C\uDF77",
"position": "-2325px 0px"
},
"u1F37B": {
"en": "Cheers",
"zh": "骞叉澂",
"tag": "\uD83C\uDF7B",
"position": "-1325px 0px"
},
"u2615": {
"en": "Coffee",
"zh": "鍜栧暋",
"tag": "\u2615",
"position": "-3150px 0px"
},
"u1F3C0": {
"en": "Basketball",
"zh": "绡悆",
"tag": "\uD83C\uDFC0",
"position": "-825px 0px"
},
"u26BD": {
"en": "Soccer Ball",
"zh": "瓒崇悆",
"tag": "\u26BD",
"position": "-2850px 0px"
},
"u1F3C2": {
"en": "Snowboarder",
"zh": "鍗曟澘婊戦洩",
"tag": "\uD83C\uDFC2",
"position": "-850px 0px"
},
"u1F3A4": {
"en": "Microphone",
"zh": "楹﹀厠椋<E58EA0>",
"tag": "\uD83C\uDFA4",
"position": "-750px 0px"
},
"u1F3B5": {
"en": "Musical Note",
"zh": "闊充箰",
"tag": "\uD83C\uDFB5",
"position": "-800px 0px"
},
"u1F3B2": {
"en": "Game Die",
"zh": "楠板瓙",
"tag": "\uD83C\uDFB2",
"position": "-775px 0px"
},
"u1F004": {
"en": "Mahjong Red Dragon",
"zh": "楹诲皢",
"tag": "\uD83C\uDC04",
"position": "-900px 0px"
},
"u1F451": {
"en": "Crown",
"zh": "鐜嬪啝",
"tag": "\uD83D\uDC51",
"position": "-2550px 0px"
},
"u1F484": {
"en": "Lipstick",
"zh": "鍙g孩",
"tag": "\uD83D\uDC84",
"position": "-2575px 0px"
},
"u1F48B": {
"en": "Kiss",
"zh": "鍚<>",
"tag": "\uD83D\uDC8B",
"position": "-1650px 0px"
},
"u1F48D": {
"en": "Ring",
"zh": "鎴掓寚",
"tag": "\uD83D\uDC8D",
"position": "-1675px 0px"
},
"u1F4DA": {
"en": "Books",
"zh": "涔︾睄",
"tag": "\uD83D\uDCDA",
"position": "-1100px 0px"
},
"u1F393": {
"en": "Graduation Cap",
"zh": "姣曚笟甯<E7AC9F>",
"tag": "\uD83C\uDF93",
"position": "-2450px 0px"
},
"u270F": {
"en": "Pencil",
"zh": "閾呯瑪",
"tag": "\u270F",
"position": "-3050px 0px"
},
"u1F3E1": {
"en": "House With Garden",
"zh": "鎴垮瓙",
"tag": "\uD83C\uDFE1",
"position": "-875px 0px"
},
"u1F6BF": {
"en": "Shower",
"zh": "娣嬫荡",
"tag": "\uD83D\uDEBF",
"position": "-1200px 0px"
},
"u1F4A1": {
"en": "Light Bulb",
"zh": "鐏场",
"tag": "\uD83D\uDCA1",
"position": "-925px 0px"
},
"u1F4DE": {
"en": "Telephone Receiver",
"zh": "鐢佃瘽鍚瓛",
"tag": "\uD83D\uDCDE",
"position": "-1125px 0px"
},
"u1F4E2": {
"en": "Loudspeaker",
"zh": "鎵╅煶鍣<E785B6>",
"tag": "\uD83D\uDCE2",
"position": "-1150px 0px"
},
"u1F556": {
"en": "Clock",
"zh": "琛<>",
"tag": "\uD83D\uDD56",
"position": "-2650px 0px"
},
"u23F0": {
"en": "Alarm Clock",
"zh": "闂归挓",
"tag": "\u23F0",
"position": "-2775px 0px"
},
"u23F3": {
"en": "Hourglass",
"zh": "娌欐紡",
"tag": "\u23F3",
"position": "-2800px 0px"
},
"u1F4A3": {
"en": "Bomb",
"zh": "鐐稿脊",
"tag": "\uD83D\uDCA3",
"position": "-975px 0px"
},
"u1F52B": {
"en": "Pistol",
"zh": "鎵嬫灙",
"tag": "\uD83D\uDD2B",
"position": "-1700px 0px"
},
"u1F48A": {
"en": "Capsule",
"zh": "鑽<>",
"tag": "\uD83D\uDC8A",
"position": "-1625px 0px"
},
"u1F680": {
"en": "Rocket",
"zh": "鐏",
"tag": "\uD83D\uDE80",
"position": "-2725px 0px"
},
"u1F30F": {
"en": "Globe",
"zh": "鍦扮悆",
"tag": "\uD83C\uDF0F",
"position": "-1225px 0px"
}
};
let EmojiList = []
function setEmojiList() {
EmojiList.length = 0;
for (var unicode in EmojiFactory) {
var detail = EmojiFactory[unicode];
if (detail.tag) {
var lang = 'en';
var symbol = detail[lang];
EmojiList.push({
unicode: unicode,
symbol: '[' + symbol + ']',
emoji: detail.tag,
});
}
}
}
setEmojiList()
export default EmojiList

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

BIN
static/imgs/tel-call.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

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

Binary file not shown.

View File

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

View File

@@ -55,7 +55,8 @@ const notifyMsgTypes = [
IMLib.ObjectName.Location,
IMLib.ObjectName.Voice,
IMLib.ObjectName.HQVoice,
IMLib.ObjectName.Sight
IMLib.ObjectName.Sight,
'RC:IWNormalMsg'
]
const imLibListeners = () => {
@@ -92,6 +93,8 @@ const imLibListeners = () => {
uni.$emit('onReceiveMessage', message)
}
} else if (message.objectName === IMLib.ObjectName.GroupNotification) {
// 这个是为了更新消息列表页的
uni.$emit('onReceiveMessage_' + message.targetId, message)
// 解散群
if (message.content.operation === 'Dismiss') {
IMLib.cleanHistoryMessages(3, message.targetId, message.sentTime,

View File

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