rongcloud.js 这个是我对融云模块的封装整合
链接融云的步骤login -> 初始化IM -> 链接
下面要使用的一些资源链接链接:pan.baidu.com/s/1tOcHOA1d… 提取码:ubs7
rongcloud.js
var appKey = "你的appkey";
var appSecret = "你的appSecret";
var statusDesc = {
CONNECTED: "连接成功",
CONNECTING: "连接中",
DISCONNECTED: "断开连接",
KICKED: "用户账户在其他设备登录,本机会被踢掉线",
NETWORK_UNAVAILABLE: "网络不可用",
SERVER_INVALID: "服务器异常或无法连接",
TOKEN_INCORRECT: "Token 不正确",
}
var disConnectReasonDesc = {
1: '己方取消已发出的通话请求',
2: '己方拒绝收到的通话请求',
3: '己方挂断',
4: '己方忙碌',
5: '己方未接听',
6: '当前引擎不支持',
7: '己方网络出错',
8: '己方摄像头初始化错误,可能是没有打开使用摄像头权限',
9: '其他端已经接听',
11: '对方取消已发出的通话请求',
12: '对方拒绝收到的通话请求',
13: '通话过程对方挂断',
14: '对方忙碌',
15: '对方未接听',
16: '对方引擎不支持',
17: '对方网络错误',
18: 'im ipc服务已断开',
}
function RongCloud() {
this.appReception = true
this.nowTargetId = ''
this.rong = api.require('rongCloud2');
this.messageType = {
'RC:VSTMsg': '[视频通话]',
'RC:ImgMsg': '[图片]',
'RC:VcMsg': '[语音消息]'
}
}
function stringifyParse(stringify) {
return JSON.parse(stringify)
}
function date_format(micro_second) {
// 总秒数
var second = Math.floor(micro_second / 1000);
// 天数
// var day = Math.floor(second / 3600 / 24);
// 小时
var hr = Math.floor(second / 3600 % 24);
// 分钟
var min = Math.floor(second / 60 % 60);
// 秒
var sec = Math.floor(second % 60);
return (hr < 10 ? '0' + hr : hr) + ":" + (min < 10 ? '0' + min : min) + ":" + (sec < 10 ? '0' + sec : sec);
};
RongCloud.prototype.login = function (id, zh, tx, callback) {
//获取token
var userId = id;
//会员id
var name = zh;
//会员昵称
var portraitUri = tx;
//会员头像
var nonce = Math.floor(Math.random() * 1000000);
//随机数
var timestamp = Date.now();
//时间戳
var signature = sha1("" + appSecret + nonce + timestamp);
//数据签名(通过哈希加密计算)
api.ajax({
url: "http://api.cn.ronghub.com/user/getToken.json",
method: "post",
headers: {
"RC-App-Key": appKey,
"RC-Nonce": "" + nonce,
"RC-Timestamp": "" + timestamp,
"RC-Signature": "" + signature,
"Content-Type": "application/x-www-form-urlencoded"
},
data: {
values: {
userId: userId,
name: name,
portraitUri: portraitUri
}
}
}, function (ret, err) {
if (ret) {
callback(ret)
} else {
api.toast({
msg: '通讯链接失败🔗~',
duration: 3000,
location: 'bottom'
});
}
});
}
RongCloud.prototype.stopVideo = function () {
var that = this
api.stopPlay();
clearInterval(that.timer)
}
RongCloud.prototype.startVideo = function () {
var that = this
api.startPlay({
path: 'widget://image/chat/voice.amr' //声音放在call文件夹里面,如果要改位置,注意这里也要更改
}, function (ret, err) { });
that.timer = setInterval(function () {
api.startPlay({
path: 'widget://image/chat/voice.amr' //声音放在call文件夹里面,如果要改位置,注意这里也要更改
}, function (ret, err) { });
}, 5000)
}
RongCloud.prototype.removeConversation = function (targetId, winName, functionName) {
var that = this;
that.rong.removeConversation({
conversationType: 'PRIVATE',
targetId: targetId
}, function (ret, err) {
api.execScript({
name: winName,
script: 'vm.' + functionName + '('+ JSON.stringify(ret) +')'
});
});
}
RongCloud.prototype.init = function (callback) {
var that = this;
that.rong.init({}, function (ret, err) {
if (ret.status == 'success') {
that.rong.setConnectionStatusListener(function (ret, err) {
mineAlert(statusDesc[ret.result.connectionStatus])
});
that.setCallListener()
apiAddEventListener('removeConversation', function (ret, err) {
that.removeConversation(ret.value.targetId, ret.value.winName, ret.value.functionName)
});
apiAddEventListener('pause', function (ret, err) {
that.appReception = true
});
apiAddEventListener('resume', function (ret, err) {
that.appReception = false
});
apiAddEventListener('setNowTargetId', function (ret, err) {
if (ret.value.targetId) {
that.nowTargetId = ret.value.targetId
} else {
that.nowTargetId = ''
}
});
apiAddEventListener('startVideo', function (ret, err) {
that.startVideo()
});
apiAddEventListener('stopVideo', function (ret, err) {
that.stopVideo()
});
apiAddEventListener('noticeclicked', function (ret, err) {
if (ret.value) {
var value = JSON.parse(ret.value);
if (ret.type == 0) {
newOpenWindow(pageUrl.chat, {
targetId: value.message.targetId
})
//APICloud推送内容
} else if (ret.type == 1) {
newOpenWindow(pageUrl.chat, {
targetId: value.message ? value.message.targetId : value.targetId
})
//开发者自定义消息
}
}
});
that.rong.setOnReceiveMessageListener(function (ret) {
apiSendEvent('receiveMessage', ret.result)
if ((ret.result.message.targetId == that.nowTargetId) && that.appReception) {
that.setMessageReceivedStatus({
messageId: ret.result.message.messageId,
receivedStatus: 'READ'
}, function () {
apiSendEvent('getConversationList')
})
} else {
apiSendEvent('notificationYN', ret.result)
apiSendEvent('getConversationList')
}
// console.log(JSON.stringify(ret))
});
apiAddEventListener('notificationYN', function (ret) {
api.notification();
api.notification({
notify: {
title: '湃安心理',
content: ret.value.message.objectName == 'RC:TxtMsg' ? ret.value.message.content.text : ('您有一条' + that.messageType[ret.value.message.objectName] + '消息'),
extra: ret.value
}
});
})
}
callback(ret, err)
});
}
RongCloud.prototype.setCallListener = function () {
var that = this;
//收到来电的事件
that.rong.addCallReceiveListener({
target: 'didReceiveCall'
}, function (ret, err) {
var callId = ret.callSession.callId;
var uid = ret.callSession.targetId;
// //这里就是进入视频界面,uid、callId在这里不需要更改。callStatus是按钮状态,3表示来电显示。
newOpenWindow(pageUrl.showVideo, {
uid: uid,
callId: callId,
callStatus: 3,
mediaType: ret.callSession.mediaType
})
console.log('来电' + JSON.stringify(ret))
//播放声音
api.startPlay({
path: 'widget://image/chat/voice.amr' //声音放在call文件夹里面,如果要改位置,注意这里也要更改
}, function (ret, err) { });
that.timer = setInterval(function () {
api.startPlay({
path: 'widget://image/chat/voice.amr' //声音放在call文件夹里面,如果要改位置,注意这里也要更改
}, function (ret, err) { });
}, 5000)
});
// //通话已接通的事件
that.rong.addCallSessionListener({
target: 'didConnect'
}, function (ret) {
console.log('通话已接通的事件' + JSON.stringify(ret))
//关闭声音
api.stopPlay();
clearInterval(that.timer)
});
// //对端用户加入了通话的事件
that.rong.addCallSessionListener({
target: 'remoteUserDidJoin'
}, function (ret) {
console.log('对端用户加入了通话的事件' + JSON.stringify(ret))
that.rong.getCallSession(function (ret) {
console.log('对话信息' + JSON.stringify(ret))
apiSendEvent('myRemoteUserDidJoin', ret)
//电话接通执行的代码放在这里,不能放到上面的didConnect里面。
// api.execScript({
// name: 'showVideo_win',
// frameName: 'showVideo_frm',
// script: 'window.rootVue.setCallStatus('+2+');' //showVideo_win页面也在call文件夹里,这里更改callStatus为2,即接通
// });
//callerUserId 拨打电话的用户ID
//selfUserId 自己的ID
//targetId 对方的ID
// api.execScript({
// name: 'showVideo_win',
// script: 'window.rootVue.showVideo("'+ret.selfUserId+'","'+ret.targetId+'");' //这里的selfUserId和targetId也不要动,就这么写。
// });
//重新打开showVideo_frm,将按钮的frame提到video的前面来
// api.execScript({
// name: 'showVideo_win',
// script: 'openFram();'
// });
});
//关闭声音
api.stopPlay();
clearInterval(that.timer)
});
// //对端用户正在振铃的事件
that.rong.addCallSessionListener({
target: 'remoteUserDidRing'
}, function (ret) {
console.log('对端用户正在振铃的事件' + JSON.stringify(ret))
});
// //对端用户切换了媒体类型的事件
that.rong.addCallSessionListener({
target: 'remoteUserDidChangeMediaType'
}, function (ret) {
console.log('对端用户切换了媒体类型的事件' + JSON.stringify(ret))
});
// //对端用户开启或关闭了摄像头的状态的事件
that.rong.addCallSessionListener({
target: 'remoteUserDidDisableCamera'
}, function (ret) {
console.log('对端用户开启或关闭了摄像头的状态的事件' + JSON.stringify(ret))
});
// //通话已结束的事件
that.rong.addCallSessionListener({
target: 'didDisconnect'
}, function (ret) {
console.log('通话已结束的事件' + JSON.stringify(ret))
api.stopPlay();
clearInterval(that.timer)
apiSendEvent('didDisconnect', {
targetId: ret.userId,
messageDirection: ret.callerUserId == ret.userId ? 'RECEIVE' : 'SEND',
objectName: 'RC:VSTMsg',
sentTime: new Date().getTime(),
content: {
activeTime: ret.startTime,
endTime: ret.endTime,
hangupReason: ret.disConnectReason,
mediaType: ret.mediaType,
}
})
api.closeWin({
name: 'showVideo'
});
mineAlert(disConnectReasonDesc[ret.disConnectReason])
});
//对端用户挂断
that.rong.addCallSessionListener({
target: 'remoteUserDidLeft'
}, function (ret) {
console.log('对端用户挂断' + JSON.stringify(ret))
api.stopPlay();
clearInterval(that.timer)
api.closeWin({
name: 'showVideo'
});
mineAlert(disConnectReasonDesc[ret.disConnectReason])
});
}
////////////////////////////视频语音 监听/////////////////////////////
RongCloud.prototype.connect = function (token, callback) {
var that = this;
that.rong.connect({
token: token
}, function (ret, err) {
callback(ret, err)
});
}
RongCloud.prototype.startCall = function (params, callback) {
var that = this;
newHasPermission('该功能需要您授权麦克风和相机权限', [{
name: 'microphone',
failDesc: '授权麦克风权限失败'
}, {
name: 'camera',
failDesc: '授权相机权限失败'
}], function () {
that.rong.startCall(params, function (ret, err) {
// api.startPlay({
// path: 'widget://image/chat/voice.amr' //声音放在call文件夹里面,如果要改位置,注意这里也要更改
// }, function (ret, err) {});
// that.timer = setInterval(function () {
// api.startPlay({
// path: 'widget://image/chat/voice.amr' //声音放在call文件夹里面,如果要改位置,注意这里也要更改
// }, function (ret, err) {});
// }, 5000)
callback(ret, err)
});
})
}
RongCloud.prototype.setVideoView = function (params) {
var that = this;
if (!params.rect) {
params.rect = {
x: 0,
y: 0,
w: api.winWidth,
h: api.winHeight
}
}
if (!params.userId) {
mineAlert("缺少打开视频对象")
return false
}
that.rong.setVideoView({
rect: params.rect,
userId: params.userId,
bg: '#ff0000',
renderModel: 'hidden',
fixedOn: api.frameName,
fixed: true
});
}
RongCloud.prototype.accept = function (params) {
var that = this;
newHasPermission('该功能需要您授权麦克风和相机权限', [{
name: 'microphone',
failDesc: '授权麦克风权限失败'
}, {
name: 'camera',
failDesc: '授权相机权限失败'
}], function () {
params.mediaType ? '' : (params.mediaType = 'video');
that.rong.accept(params);
})
}
RongCloud.prototype.hangup = function () {
var that = this;
that.rong.hangup();
that.stopVideo()
}
RongCloud.prototype.getConversationList = function (callback) {
var that = this;
that.rong.getConversationList(function (ret, err) {
callback(ret)
})
}
RongCloud.prototype.setMessageReceivedStatus = function (params, callback) {
var that = this;
params.conversationType = 'PRIVATE'
that.rong.setMessageReceivedStatus(params, function (ret, err) {
callback(ret)
})
}
RongCloud.prototype.clearMessagesUnreadStatus = function (params, callback) {
var that = this;
params.conversationType = 'PRIVATE'
that.rong.clearMessagesUnreadStatus(params, function (ret, err) {
callback(ret)
})
}
RongCloud.prototype.sendTextMessage = function (params, callback) {
var that = this;
// PRIVATE (单聊)
// DISCUSSION (讨论组)
// GROUP (群组)
// CHATROOM(聊天室)
// CUSTOMER_SERVICE (客服)
// SYSTEM (系统)
params.conversationType = 'PRIVATE'
if (!params.targetId) {
mineAlert("缺少发送对象")
return false
}
if (!params.text) {
mineAlert("请输入要发送的内容")
return false
}
that.rong.sendTextMessage(params, callback)
}
RongCloud.prototype.sendVoiceMessage = function (params, callback) {
var that = this;
params.conversationType = 'PRIVATE'
if (!params.targetId) {
mineAlert("缺少发送对象")
return false
}
if (!params.voicePath) {
mineAlert("缺少发送内容")
return false
}
// conversationType: 'PRIVATE',
// targetId: '9527',
// oldestMessageId: 688,
// count: 20
that.rong.sendVoiceMessage(params, callback)
}
RongCloud.prototype.sendImageMessage = function (params, callback) {
var that = this;
params.conversationType = 'PRIVATE'
if (!params.targetId) {
mineAlert("缺少发送对象")
return false
}
if (!params.imagePath) {
mineAlert("缺少发送内容")
return false
}
// function(ret, err) {
// if (ret.status == 'prepare')
// api.toast({ msg: JSON.stringify(ret.result.message) });
// else if (ret.status == 'progress')
// api.toast({ msg: ret.result.progress });
// else if (ret.status == 'success')
// api.toast({ msg: ret.result.message.messageId });
// else if (ret.status == 'error')
// api.toast({ msg: err.code });
// }
that.rong.sendImageMessage(params, callback);
}
RongCloud.prototype.sendSightMessage = function (params, callback) {
var that = this;
params.conversationType = 'PRIVATE'
if (!params.targetId) {
mineAlert("缺少发送对象")
return false
}
if (!params.sightPath) {
mineAlert("缺少发送内容")
return false
}
// conversationType: 'PRIVATE',
// targetId: '9527',
// thumbPath: 'fs:///xxx/xxx/picture.jpg',
// sightPath:'',
// duration: 10,
// extra: ''
// function(ret, err) {
// if (ret.status == 'prepare')
// api.toast({ msg: JSON.stringify(ret.result.message) });
// else if (ret.status == 'progress')
// api.toast({ msg: ret.result.progress });
// else if (ret.status == 'success')
// api.toast({ msg: ret.result.message.messageId });
// else if (ret.status == 'error')
// api.toast({ msg: err.code });
// }
that.rong.sendSightMessage(params, callback);
}
RongCloud.prototype.getHistoryMessages = function (params, callback) {
var that = this;
params.conversationType = 'PRIVATE'
if (!params.targetId) {
mineAlert("缺少发送对象")
return false
}
that.rong.getHistoryMessages(params, callback);
}
RongCloud.prototype.getConnectionStatus = function (callback) {
this.rong.getConnectionStatus(callback);
}
RongCloud.prototype.getUnreadCount = function (params, callback) {
params.conversationType = 'PRIVATE'
this.rong.getUnreadCount(params, callback);
}
RongCloud.prototype.setMuted = function (muted) {
var that = this;
that.rong.setMuted({
muted: muted
}, function (ret) { })
}
RongCloud.prototype.setSpeakerEnabled = function (speakerEnabled) {
var that = this;
that.rong.setSpeakerEnabled({
speakerEnabled: speakerEnabled
}, function (ret) {
})
}
RongCloud.prototype.logout = function (callback) {
var that = this;
that.rong.logout(function (ret, err) {
callback(ret)
})
}
function encodeUTF8(s) {
var i, r = [],
c, x;
for (i = 0; i < s.length; i++)
if ((c = s.charCodeAt(i)) < 0x80) r.push(c);
else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F));
else {
if ((x = c ^ 0xD800) >> 10 == 0) //对四字节UTF-16转换为Unicode
c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000,
r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F));
else r.push(0xE0 + (c >> 12 & 0xF));
r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
};
return r;
}
// 字符串加密成 hex 字符串
function sha1(s) {
var data = new Uint8Array(encodeUTF8(s))
var i, j, t;
var l = ((data.length + 8) >>> 6 << 4) + 16,
s = new Uint8Array(l << 2);
s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer);
for (t = new DataView(s.buffer), i = 0; i < l; i++) s[i] = t.getUint32(i << 2);
s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8);
s[l - 1] = data.length << 3;
var w = [],
f = [
function () {
return m[1] & m[2] | ~m[1] & m[3];
},
function () {
return m[1] ^ m[2] ^ m[3];
},
function () {
return m[1] & m[2] | m[1] & m[3] | m[2] & m[3];
},
function () {
return m[1] ^ m[2] ^ m[3];
}
],
rol = function (n, c) {
return n << c | n >>> (32 - c);
},
k = [1518500249, 1859775393, -1894007588, -899497514],
m = [1732584193, -271733879, null, null, -1009589776];
m[2] = ~m[0], m[3] = ~m[1];
for (i = 0; i < s.length; i += 16) {
var o = m.slice(0);
for (j = 0; j < 80; j++)
w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1),
t = rol(m[0], 5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0,
m[1] = rol(m[1], 30), m.pop(), m.unshift(t);
for (j = 0; j < 5; j++) m[j] = m[j] + o[j] | 0;
};
t = new DataView(new Uint32Array(m).buffer);
for (var i = 0; i < 5; i++) m[i] = t.getUint32(i << 2);
var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function (e) {
return (e < 16 ? "0" : "") + e.toString(16);
}).join("");
return hex;
}
vm.rong.login(用户的唯一标识, 用户姓名, 用户头像,
function (res) {
if (res.code == 200 && res.token) {
var token = res.token
apiAddEventListener('rongLogout', function (ret) {
vm.rong.logout(function (ret) {
})
});
vm.rong.init(function (ret, err) {
vm.rong.connect(token, function (ret, err) {
if (ret.status == 'success') {
onlineAndOffline(1, function () {
})
apiSendEvent('getConversationList'); // 重新登录后刷新消息菜单的列表
// apiAddEventListener('setConversationList', function (ret) {
// vm.rong.getConversationList(function (ret) {
// apiSendEvent('getConversationList', ret);
// })
// });
// apiAddEventListener('setHistoryMessages', function (ret) {
// vm.rong.getHistoryMessages(ret.value,function (ret) {
// apiSendEvent('getHistoryMessages', ret);
// })
// });
} else {
mineAlert("通讯登录错误,请重新登录")
}
})
})
} else {
mineAlert("通讯链接失败🔗")
}
}
)
这里聊天界面
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
<meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
<title></title>
<link rel="stylesheet" type="text/css" href="../../css/aui.css" />
<link rel="stylesheet" type="text/css" href="../../css/common.css" />
<link rel="stylesheet" type="text/css" href="../../css/aui-flex.css" />
<link rel="stylesheet" type="text/css" href="../../css/index.css" />
<style>
html,
body {
background: #EBEBEB;
}
input,
textarea {
/* -webkit-user-select: auto; */
/*webkit浏览器*/
/* margin: 0px;
padding: 0px;
outline: none; */
}
.emoji:active {
background: rgba(0, 0, 0, 0.09);
}
.backgroundR {
background: rgba(0, 0, 0, 0.09);
}
.aui-chat .aui-chat-content {
color: #444
}
.aui-chat .aui-chat-left .aui-chat-content {
background-color: #fff;
}
.aui-chat .aui-chat-left .aui-chat-arrow {
background: #fff !important;
}
.aui-chat .aui-chat-right .aui-chat-content {
background-color: #4070FF;
color: #fff
}
.aui-chat .aui-chat-right .aui-chat-arrow {
background: #4070FF !important;
}
.van-image {
display: flex;
align-content: flex-start;
}
</style>
</head>
<body>
<div v-cloak id="app">
<van-overlay :custom-style="{'height':'calc( 100vh - ' + keyboardHeight + 'px )'}" :show="recordingStatus">
</van-overlay>
<div @touchstart="emojiShow = false;addShow = false;recordStatus = false;blur()"
:style="{'height': '100vh','overflow':(chatBoxStatus ? 'hidden' : 'auto')}" id="chatBox">
<!-- translateStatus && -->
<div :style="{'transform': 'translateY('+ (((emojiShow || recordStatus || focusStatus || addShow)) ? -keyboardHeight : 0) +'px)'}"
id="chat" class="box_relative">
<van-pull-refresh pulling-text="下拉查看更多历史记录..." loosing-text="释放即可加载..." v-model="isLoading"
@refresh="onRefresh">
<section id="chat1" @click="emojiShow = false;addShow = false" class="aui-chat">
<div v-if="showTop">
<div
class="aui-margin-t-10 aui-margin-b-10 aui-chat-header aui-flex-col aui-flex-center aui-flex-middle">
<div class=" color_999 aui-font-size-13 aui-padded-l-5 aui-padded-r-5">
~没有更多历史消息了~
</div>
</div>
</div>
<template :key="index" v-for="(item,index) in messagesList">
<div>
<div class="aui-chat-header aui-flex-col aui-flex-center aui-flex-middle">
<div class="bg_CCC color_fff aui-font-size-13 aui-padded-l-5 aui-padded-r-5"
style="border-radius: 0.21rem;">
{{dateFtt1(item.sentTime)}}
</div>
</div>
</div>
<div
:class="['aui-chat-item', item.messageDirection == 'RECEIVE' ? 'aui-chat-left' : 'aui-chat-right']">
<div class="aui-chat-media">
<van-image round width="2rem" height='2rem' fit="cover"
:src="item.messageDirection == 'RECEIVE' ? otherInfo.headPortrait : userInfo.headPortrait">
</van-image>
</div>
<div class="aui-chat-inner">
<div class="aui-chat-name">{{item.messageDirection == 'RECEIVE' ? otherInfo.nickName : userInfo.name}}</div>
<div class="aui-chat-content">
<div :style="item.objectName == 'RC:VSTMsg' ? 'width:auto':''"
class="aui-chat-arrow"></div>
<template v-if="item.objectName == 'RC:TxtMsg'">
<template
v-if="item.content.extra && stringifyParse(item.content.extra).type && stringifyParse(item.content.extra).type == 'call'">
<div @click="startCall" style="flex-wrap: nowrap;"
class="aui-flex-col aui-flex-middle">
<img style="width: 0.85rem;" class="aui-margin-r-5"
:src=" item.messageDirection == 'RECEIVE' ? '../../image/chat/callyou.png' : '../../image/chat/callme.png'" />
<div></div>
{{item.content ?
item.content.text : ''}}
</div>
</template>
<div v-else>
{{item.content ?
item.content.text : ''}}
</div>
</template>
<template v-else-if="item.objectName == 'RC:VSTMsg'">
<div @click="startCall" style="flex-wrap: nowrap;"
class="aui-flex-col aui-flex-middle">
<img style="width: 0.85rem;" class="aui-margin-r-5"
:src=" item.messageDirection == 'RECEIVE' ? '../../image/chat/callyou.png' : '../../image/chat/callme.png'" />
<div style="white-space: nowrap;"
v-if="item.content.hangupReason != 11 && item.content.activeTime != 0 && item.content.endTime != 0">
通话结束{{date_format(item.content.endTime - item.content.activeTime)}}
</div>
<div v-else>
{{disConnectReasonDesc[item.content.hangupReason]}}
</div>
</div>
</template>
<template v-else-if="item.objectName == 'RC:ImgMsg'">
<div class="box_relative">
<div v-if="item.progress && (item.progress != 100 || item.fail == 1)"
class="box_absolute aui-flex-col aui-flex-middle aui-font-size-14 color_fff aui-flex-center"
style="z-index:100;left: 0;width: 100%;top: 0;height: 100%;background: rgba(0, 0, 0, 0.39);">
{{item.progress}}%
</div>
<van-image @click="chatPhoto(index)" fit="cover"
:src="item.content ? item.content.imageUrl : ''">
</van-image>
</div>
</template>
<template v-if="item.objectName == 'RC:VcMsg'">
<div class="aui-flex-col aui-flex-middle aui-flex-center"
@click="startPlay(index,item.content.voicePath)">
<img style="width: 1.2rem;" class="aui-margin-r-5"
:src="item.start ? '../../image/chat/playing.gif' : item.messageDirection == 'RECEIVE' ? '../../image/chat/stop.png' : '../../image/chat/myS.png'" />
{{item.content ? item.content.duration : ''}}s
</div>
</template>
</div>
<div v-if="item.fail == 1" class="aui-chat-status">
<i class="aui-iconfont aui-icon-info aui-text-danger"></i>
</div>
<div v-if="item.loading == 1" class="aui-chat-status">
<van-loading size="0.78rem"></van-loading>
</div>
</div>
</div>
</template>
<!-- "{'height': 'calc( 5rem + ' + ((emojiShow) ? keyboardHeight : 0 ) + 'px )'}" -->
<div class="aui-chat-item aui-font-size-15" :style="{'height': 'calc( 5rem )'}">
</div>
</section>
</van-pull-refresh>
</div>
<!-- -->
</div>
<footer @touchstart="chatBoxStatus = true" @touchmove="touchmove" @touchend="chatBoxStatus = false" id="textBox"
ref="footer" style="bottom: 0;left: 0;width: 100%;" class="bg_EBEBEB box_fixed footer">
<div class="aui-flex-col aui-flex-between aui-padded-r-10 aui-padded-l-10 aui-flex-middle"
style="flex-wrap: nowrap;border-top: 1px solid #e2e2e2;border-bottom: 1px solid #e2e2e2;">
<div @click="recordStatus = !recordStatus">
<img style="width: 1.36rem;"
:src="recordStatus ? '../../image/chat/auido_acitve.png' : '../../image/chat/audio.png'" />
</div>
<div class="aui-flex-col aui-flex-auto aui-padded-10">
<div class="bg_F5F5F5 aui-padded-10" style="border-radius: 0.32rem;width: 100%;height:100%;">
<textarea @click="showList = [0,current];emojiShow = false" @blur="blur" @focus="focus"
ref="textarea" v-model="content" id="textarea" class="message"
style="height: 1.5em;"></textarea>
</div>
</div>
<div style="flex-wrap: nowrap;" class="aui-flex-col aui-flex-middle">
<div class="aui-flex-col aui-flex-middle"
@click="setTimeout(function(){emojiShow = !emojiShow},10) ">
<img style="width: 1.36rem;"
:src="emojiShow ? '../../image/chat/expression_active.png' : '../../image/chat/expression.png'" />
</div>
<div class="aui-flex-auto" v-if="content">
<van-button @click="sendTextMessage" class="aui-margin-l-10"
style="height:1.496rem;width: auto;" block :color="themeColor" type="primary">
<span class="aui-font-size-15 color_fff ">发送</span>
</van-button>
</div>
<div v-else @click="setTimeout(function(){addShow = !addShow},10) "
class="aui-flex-col aui-flex-middle aui-padded-l-10">
<img style="width: 1.36rem;"
:src="addShow ? '../../image/chat/add_active.png' : '../../image/chat/add.png'" />
</div>
</div>
</div>
<!-- <transition name="van-slide-up"> -->
<div :style="'height:calc(' + keyboardHeight + 'px );'" v-show="recordStatus">
<div class="aui-flex-col aui-padded-30">
<div class="aui-flex-row aui-flex-middle aui-flex-center" style="margin-top: 10%;width: 100%;">
<div class="aui-text-center aui-margin-b-10 aui-font-size-14 color_666">{{recordingStatus ?
'释放发送' : '按住说话'}}</div>
<div :class="recordingStatus ? 'backgroundR' : 'bg_fff'" @touchstart="startRecord"
@touchend="stopRecord(sendRecord)"
class="aui-shadow aui-flex-col aui-flex-middle aui-flex-center"
style="height: 4.2rem;width: 4.2rem;border-radius: 50%;">
<img style="width: 60%;" src="../../image/record.png" />
</div>
</div>
</div>
</div>
<div :style="'height:calc(' + keyboardHeight + 'px );'" v-show="addShow">
<div class="aui-flex-col aui-padded-30">
<div @click="selectPic1(1,sendImage)" style="width: 3.4rem;height:3.4rem;border-radius: 0.45rem;"
class="aui-margin-r-15 emoji aui-flex-col aui-flex-center aui-flex-middle bg_fff">
<img style="width: 56%;" src="../../image/crame.png" />
</div>
<div @click="selectPic1(2,sendImage,3)" style="width: 3.4rem;height:3.4rem;border-radius: 0.45rem;"
class="emoji aui-margin-r-15 aui-flex-col aui-flex-center aui-flex-middle bg_fff">
<img style="width: 56%;" src="../../image/photo2.png" />
</div>
<!-- <div @click="startCall" style="width: 3.4rem;height:3.4rem;border-radius: 0.45rem;"
class="emoji aui-flex-col aui-flex-center aui-flex-middle bg_fff">
<img style="width: 56%;" src="../../image/videoPlay.png" />
</div> -->
</div>
</div>
<!-- </transition> -->
<!-- <transition name="van-slide-up"> -->
<div id="emojiBox1" ref="emojiBox" @click="stop" class="">
<van-swipe :touchable="touchable" v-show="emojiShow" ref="swipe" @change="onChange">
<template v-for="(item,index) in emojiconfig" :key="index">
<van-swipe-item :style="'height:calc(' + keyboardHeight + 'px - 1.96rem);overflow: scroll;'"
class="content">
<template v-if="showList.indexOf(index) != -1">
<div style="line-height: 2.2rem;font-size: 1.25rem;"
class="aui-text-center aui-flex-col">
<div :value="items" class="emoji" style="width: 12.5%;height: 2.2rem"
v-for="(items,i) in item.alias">
{{items}}
</div>
</div>
</template>
</van-swipe-item>
</template>
<template slot="indicator">
<div id="myTab" style="flex-wrap: nowrap;overflow-y: scroll;" class="aui-flex-col">
<div :key="index" v-for="(item,index) in emojiconfig">
<van-button :class="'tab' + index" style="height:1.96rem" @click="current = index"
:color="current == index ? themeColor : ''" type="default">
{{item.name}}</van-button>
</div>
</div>
</template>
</van-swipe>
</div>
<!-- </transition> -->
</footer>
</div>
</body>
<script type="text/javascript" src="../../script/api.js"></script>
<script type="text/javascript" src="../../script/vue.js"></script>
<script type="text/javascript" src="../../script/jq.js"></script>
<script type="text/javascript" src="../../script/common.js"></script>
<script type="text/javascript" src="../../script/component.js"></script>
<script type="text/javascript" src="../../script/vant.min.js"></script>
<script type="text/javascript" src="../../script/js/emojisort.js"></script>
<script type="text/javascript" src="../../script/js/textarea.js"></script>
<script type="text/javascript" src="../../script/rongcloud.js"></script>
<script type="text/javascript">
if (!HTMLElement.prototype.addTapEvent) {
HTMLElement.prototype.addTapEvent = function (callback) {
var tapStartTime = 0,
tapEndTime = 0,
tapTime = 250, //tap等待时间,在此事件下松开可触发方法
tapStartClientX = 0,
tapStartClientY = 0,
tapEndClientX = 0,
tapEndClientY = 0,
tapScollHeight = 0, //水平或垂直方向移动超过15px测判定为取消(根据chrome浏览器默认的判断取消点击的移动量)
cancleClick = false;
this.addEventListener('touchstart', function (event) {
tapStartTime = event.timeStamp;
var touch = event.changedTouches[0];
tapStartClientX = touch.clientX;
tapStartClientY = touch.clientY;
cancleClick = false;
})
this.addEventListener('touchmove', function () {
var touch = event.changedTouches[0];
tapEndClientX = touch.clientX;
tapEndClientY = touch.clientY;
if ((Math.abs(tapEndClientX - tapStartClientX) > tapScollHeight) || (Math.abs(tapEndClientY - tapStartClientY) > tapScollHeight)) {
cancleClick = true;
}
})
this.addEventListener('touchend', function (event) {
tapEndTime = event.timeStamp;
if (!cancleClick && (tapEndTime - tapStartTime) <= tapTime) {
callback(event);
}
})
}
}
var emojiconfigElement = []
for (var key in emojiconfig) {
emojiconfigElement.push(emojiconfig[key])
}
var innerHeight = window.innerHeight
var vm = new Vue({
el: "#app",
data: function () {
return {
showTop: false,
rong: null,
targetId: "",
count: 8,
messagesList: [],
content: "",
textareaHeight: 0,
footHeight: 0,
keyboardHeight: 346,
textBoxRect: {},
emojiShow: false,
emojiconfig: emojiconfigElement,
current: 0,
showList: [0],
touchable: true,
textBoxRect: {},
textarea: null,
focusStatus: false,
addShow: false,
chatBoxStatus: false,
recordStatus: false,
recordingStatus: false,
isLoading: false,
fontSize: null,
translateStatus: true,
userInfo:{},
otherInfo:{}
}
},
watch: {
translateStatus: function (newValue) {
console.log(newValue)
if (!newValue) {
vm.$nextTick(function () {
chatBox.scrollTo(0, chat1.offsetHeight)
})
}
},
current: function (newValue) {
if (vm.showList.indexOf(newValue) == -1) {
vm.showList.push(newValue)
}
this.$refs.swipe.swipeTo(newValue)
this.offsetLeft()
},
addShow: function (newValue) {
if (newValue) {
vm.emojiShow = false
vm.recordStatus = false
}
},
recordStatus: function (newValue) {
if (newValue) {
vm.emojiShow = false
vm.addShow = false
}
},
emojiShow: function (newValue) {
// if(newValue)this.$refs.swipe.resize();
this.$nextTick(function () {
if (newValue) {
vm.addShow = false
vm.recordStatus = false
vm.$refs.swipe.resize();
vm.$refs.swipe.swipeTo(vm.current)
vm.offsetLeft()
// window.scrollTo(0, window.scrollY + vm.keyboardHeight + vm.footHeight)
console.log(window.scrollY)
console.log(vm.keyboardHeight, vm.footHeight)
} else {
if (window.scrollY + innerHeight < chat.offsetHeight) {
// window.scrollTo(0, window.scrollY - (vm.keyboardHeight + vm.footHeight))
}
}
})
},
footHeight: {
handler: function () {
this.$nextTick(function () {
// vm.textareaHeight = this.$refs.footer.offsetHeight
})
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
immediate: true
},
keyboardHeight: function (newValue) {
}
},
mixins: [mix],
mounted: function () {
// this.$nextTick(function () {
// vm.init()
// })
},
methods: {
chatPhoto(index) {
var imageUrlList = []
var findIndex = 0
vm.messagesList.forEach(function (ele, i) {
if (ele.objectName == 'RC:ImgMsg') {
imageUrlList.push(vm.messagesList[i].content.imageUrl)
}
})
findIndex = imageUrlList.findIndex(function (ele) {
return ele == vm.messagesList[index].content.imageUrl
})
photoBrowser(imageUrlList, findIndex)
},
startRecord: function () {
// 自定义申请权限的方法
hasPermission('发送语音消息需要使用麦克风录制音频权限', 'microphone', function (flag) {
if (flag) {
vm.recordingStatus = true
var savePath = 'fs://paxl_' + (+new Date()) + '.amr';
api.startRecord({
path: savePath
});
}
})
// api.notification();
},
startPlay(index, voicePath) {
vm.messagesList.forEach(function (ele) {
if (ele.start) {
Vue.set(ele, 'start', false)
}
})
api.stopPlay()
vm.messagesList[index].start = true
Vue.set(vm.messagesList, index, vm.messagesList[index])
api.startPlay({
path: voicePath
}, function (ret, err) {
if (ret) {
vm.messagesList[index].start = false
Vue.set(vm.messagesList, index, vm.messagesList[index])
} else {
mineAlert("播放失败")
}
});
},
sendRecord: function (ret, err) {
if (ret.duration <= 1) {
mineAlert("按键时间太短")
return false
}
vm.sendVoiceMessage({ duration: ret.duration, voicePath: ret.path })
return false
},
stopRecord: function (callback) {
vm.recordingStatus = false
api.stopRecord(callback);
},
touchmove: function () {
// event.preventDefault()
event.stopPropagation()
// console.log(event.target)
// chat.style.overflow="hidden"
// event.cancelBubble()
},
insertText: function (val) {
var textarea = this.$refs.textarea
var str = val;
var startPos;
var endPos;
if (document.selection) {
var sel = document.selection.createRange();
sel.text = str;
} else if (typeof textarea.selectionStart === 'number' && typeof textarea.selectionEnd === 'number') {
startPos = textarea.selectionStart;
endPos = textarea.selectionEnd;
var tmpStr = textarea.value;
textarea.value = tmpStr.substring(0, startPos) + str + tmpStr.substring(endPos, tmpStr.length);
} else {
textarea.value += str;
}
textarea.focus();
this.content = textarea.value
if (api.systemType != "ios") {
textarea.focus();
textarea.selectionStart = startPos + str.length;
textarea.selectionEnd = endPos + str.length;
textarea.blur();
}
},
onChange(index) {
this.current = index;
},
offsetLeft: function () {
let offsetLeft = 0
if (this.emojiconfig.length / 2 + 1 >= this.current) {
offsetLeft = $('.tab' + this.current)[0].offsetLeft - $('.tab1')[0].offsetLeft * 1.25
} else {
offsetLeft = $('.tab' + this.current)[0].offsetLeft
}
$('#myTab').animate({ scrollLeft: (offsetLeft) }, 200);
},
stop: function (e) {
if (api.systemType != "ios") {
let target = e.target ? e.target : e.srcElement
let value = target.getAttribute('value')
value && vm.insertText(value)
}
},
focus: function () {
vm.countKeyboardHeight()
vm.$nextTick(function () {
vm.focusStatus = true
vm.addShow = false
vm.recordStatus = false
if (window.scrollY + innerHeight < chat.offsetHeight) {
// window.scrollTo(0, window.scrollY + vm.keyboardHeight + vm.footHeight)
}
})
},
blur: function () {
vm.$nextTick(function () {
this.$refs.textarea.blur()
vm.focusStatus = false
if (window.scrollY + innerHeight < chat.offsetHeight) {
// window.scrollTo(0, window.scrollY - (vm.keyboardHeight + vm.footHeight))
}
})
},
toBottom() {
setTimeout(function () {
vm.$nextTick(function () {
chatBox.scrollTo(0, chat1.offsetHeight)
})
}, 300)
},
countKeyboardHeight: function () {
vm.$nextTick(function () {
if (api.systemType == "ios") {
vm.$refs.emojiBox.addTapEvent(function (e) {
// console.log(event)
let target = e.target ? e.target : e.srcElement
let value = target.getAttribute('value')
value && vm.insertText(value)
})
vm.touchable = false
var textBoxRect = textBox.getBoundingClientRect()
if (vm.textBoxRect.y - textBoxRect.y > 0) {
vm.keyboardHeight = vm.textBoxRect.y - textBoxRect.y
}
}
})
},
init: function () {
var fontSize = parseInt(window.getComputedStyle(document.getElementsByTagName('html')[0]).fontSize)
fontSize = (isNaN(fontSize) ? 20 : fontSize);
vm.fontSize = fontSize
autoTextarea(textarea, 0, fontSize * 3, function (height) {
vm.footHeight = height
})
vm.getHistoryMessages(function () {
vm.$nextTick(function () {
vm.toBottom()
if (api.systemType != "ios") {
const h = api.winHeight
window.onresize = function () { // 如果当前窗口小于一开始记录的窗口高度,那就让当前窗口等于一开始窗口的高度
var keyboardHeight = h - api.winHeight
if (keyboardHeight > 0) {
setTimeout(function () {
vm.keyboardHeight = keyboardHeight
}, 0)
}
}
} else {
vm.textBoxRect = textBox.getBoundingClientRect()
}
})
})
chatBox.onscroll = function () {
var windowH = document.documentElement.clientHeight;
var documentH = chat1.offsetHeight;
var scrollH = chatBox.scrollTop;
console.log(windowH, documentH, scrollH)
if (windowH + scrollH >= documentH - 20) {
//do something
vm.translateStatus = false
} else {
vm.translateStatus = true
}
}
vm.clearMessagesUnreadStatus()
// vm.getUnreadCount()
},
getUnreadCount() {
// 统计当前聊天对象的所有未读消息
var obj = {
targetId: vm.targetId,
}
vm.rong.getUnreadCount(obj, function (ret) {
// alert(JSON.stringify(ret))
})
},
clearMessagesUnreadStatus() {
// 清除当前聊天对象的所有未读消息
var obj = {
targetId: vm.targetId,
}
vm.rong.clearMessagesUnreadStatus(obj, function (ret) {
// alert(JSON.stringify(ret))
})
},
startCall() {
return false
var params = {
targetId: vm.targetId + '',
mediaType: 'video',
conversationType: 'PRIVATE',
userIdList: [vm.targetId + '']
}
vm.rong.startCall(params, function (ret) {
vm.sendTextMessage(1, "发起了视频通话", { type: 'call' })
apiSendEvent('startVideo')
newOpenWindow(pageUrl.showVideo, { uid: vm.targetId, callId: ret.callSession.callId, callStatus: 1, mediaType: params.mediaType })
})
},
getHistoryMessages(callback) {
var obj = {
targetId: vm.targetId,
oldestMessageId: vm.messagesList.length > 0 ? vm.messagesList[0].messageId : -1,
count: vm.count,
}
vm.rong.getHistoryMessages(obj, function (ret) {
if (ret.result) {
ret.result.reverse()
vm.messagesList = [].concat(ret.result, vm.messagesList)
console.log(JSON.stringify(vm.messagesList))
} else {
vm.showTop = true
}
if (!!callback) {
callback(ret)
}
})
},
sendImage(ret) {
if (typeof ret == "string") {
vm.sendImageMessage(ret)
} else {
ret.forEach(function (element) {
vm.sendImageMessage(element)
});
}
},
sendVoiceMessage(params) {
var obj = {
targetId: vm.targetId,
voicePath: params.voicePath,
duration: params.duration,
extra: {
}
}
var length = 0
vm.rong.sendVoiceMessage(obj, function (ret) {
// alert(JSON.stringify(ret.result))
var data = ret
switch (ret.status) {
case 'prepare':
data.result.message.loading = 1
vm.messagesList.push(data.result.message)
length = vm.messagesList.length
vm.toBottom()
break;
case 'progress':
vm.messagesList[length - 1].progress = ret.result.progress
break;
case 'success':
vm.messagesList[length - 1].loading = 0
break;
case 'error':
vm.messagesList[length - 1].fail = 1
vm.messagesList[length - 1].loading = 0
mineAlert("发送失败")
break;
}
// alert(JSON.stringify(ret))
})
},
sendImageMessage(imagePath) {
var obj = {
targetId: vm.targetId,
imagePath: imagePath,
extra: {
}
}
var length = 0
vm.rong.sendImageMessage(obj, function (ret) {
// alert(JSON.stringify(ret.result))
var data = ret
switch (ret.status) {
case 'prepare':
data.result.message.loading = 1
vm.messagesList.push(data.result.message)
length = vm.messagesList.length
vm.toBottom()
break;
case 'progress':
vm.messagesList[length - 1].progress = ret.result.progress
break;
case 'success':
vm.messagesList[length - 1].loading = 0
break;
case 'error':
vm.messagesList[length - 1].fail = 1
vm.messagesList[length - 1].loading = 0
mineAlert("发送失败")
break;
}
// alert(JSON.stringify(ret))
})
},
sendTextMessage(a, text, params) {
var obj = {
targetId: vm.targetId,
text: a == 1 ? text : vm.content,
extra: {
...params,
}
}
var length = 0
vm.rong.sendTextMessage(obj, function (ret) {
// alert(JSON.stringify(ret.status))
// alert(JSON.stringify(ret.result))
var data = ret
switch (ret.status) {
case 'prepare':
data.result.message.loading = 1
vm.content = ""
if (vm.fontSize) {
textarea.style.height = vm.fontSize + 'px'
}
vm.messagesList.push(data.result.message)
length = vm.messagesList.length
vm.toBottom()
break;
case 'success':
vm.messagesList[length - 1].loading = 0
break;
case 'error':
vm.messagesList[length - 1].fail = 1
vm.messagesList[length - 1].loading = 0
mineAlert("发送失败")
break;
}
// alert(JSON.stringify(ret))
})
},
onRefresh: function () {
vm.getHistoryMessages(function () {
vm.isLoading = false
})
}
}
})
apiready = function () {
getLoginInfo(function (res) {
vm.userInfo = res
})
apiAddEventListener('upDateUserInfo', function () {
getLoginInfo(function (res) {
vm.userInfo = res
})
})
vm.targetId = api.pageParam.targetId
getAccount(vm.targetId,function(res){
vm.otherInfo = res
})
vm.rong = new RongCloud()
apiSendEvent('setNowTargetId', { targetId: vm.targetId });
vm.rong.getConnectionStatus(function (ret) {
// alert(JSON.stringify(ret))
// alert(statusDesc[ret.result.connectionStatus])
if (ret.result.connectionStatus == 'CONNECTED') {
} else {
mineAlert("聊天初始化失败,请重新登录")
}
})
apiAddEventListener('didDisconnect', function (ret) {
vm.messagesList.push(ret.value)
vm.toBottom()
});
apiAddEventListener('receiveMessage', function (ret) {
if (ret.value.message.senderUserId == vm.targetId) {
vm.messagesList.push(ret.value.message)
vm.toBottom()
}
});
vm.init();
// api.setRefreshHeaderInfo({
// bgColor: '#ccc',
// textColor: '#fff',
// textDown: '下拉加载更多...',
// textUp: '松开加载...',
// textLoading: "加载中..."
// }, function (ret, err) {
// //在这里从服务器加载数据,加载完成后调用方法恢复组件到默认状态
// //
// });
}
</script>
</html>
视频通话界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
<meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
<title></title>
</head>
<body>
<div id="app">
</div>
</body>
<script type="text/javascript" src="../../script/api.js"></script>
<script type="text/javascript" src="../../script/vue.js"></script>
<script type="text/javascript" src="../../script/common.js"></script>
<script type="text/javascript" src="../../script/vant.min.js"></script>
<script type="text/javascript" src="../../script/rongcloud.js"></script>
<script>
//初始化vue
var vm = new Vue({
el: '#app',
data: function () {
return {
uid: '',
callId: '',
mediaType:""
}
},
methods: {
//打开视频
showVideo: function (uid1, uid2) { //uid自己的id,uid2别人的id
rong.setVideoView({
rect: {
x: 0,
y: 0,
w: api.winWidth,
h: api.winHeight
},
userId: uid2,
bg: '#ff0000',
renderModel: 'hidden',
fixed: true
});
//打开自己的视频
rong.setVideoView({
rect: {
x: api.winWidth - 130,
y: api.safeArea.top + 20,
w: 110,
h: 180
},
userId: uid1,
bg: '#ff0000',
renderModel: 'hidden',
fixed: true
});
},
//重新打开视频
resetVideoView: function (uid) {
var rong = api.require('rongCloud2');
rong.resetVideoView({
userId: uid
});
}
},
// mounted: function () {
// setTimeout(function () {
// openFram();
// }, 500)
// }
});
apiready = function () {
vm.callStatus = api.pageParam.callStatus
vm.callId = api.pageParam.callId
vm.mediaType = api.pageParam.mediaType
vm.uid = api.pageParam.uid
open_frame(api.pageParam.url, api.pageParam.name, false,{callId:api.pageParam.callId,callStatus:api.pageParam.callStatus,mediaType:api.pageParam.callStatus,uid:vm.uid});
api.addEventListener({
name: 'keyback'
}, function (ret, err) {
api.execScript({
frameName: api.pageParam.name,
script: 'window.vm.hangup();'
});
});
}
</script>
</html>
悬浮在通话界面上的操作按钮 区分了是拨打用户还是被拨打用户
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
<meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
<title></title>
<link rel="stylesheet" type="text/css" href="../../css/aui.css" />
<link rel="stylesheet" type="text/css" href="../../css/common.css" />
<link rel="stylesheet" type="text/css" href="../../css/aui-flex.css" />
<link rel="stylesheet" type="text/css" href="../../script/index.css" />
<style>
html {
background-color: rgba(0, 0, 0, 0.49)
}
body {
background: transparent;
height: 100vh;
}
</style>
</head>
<body>
<!--
callStatus===1、拨打电话,应该显示接听电话人的头像
callStatus===3、接听电话,应该显示拨打电话人的头像
-->
<div id="app" style="height: 100%;" class="aui-flex-row aui-flex-between" v-cloak>
<div class="aui-clearfix ">
<div style="margin-top: 13.6vh;" class="aui-flex-row aui-flex-center aui-flex-middle">
<van-image fit='cover' style="border-radius: 0.24rem;overflow: hidden" width='4.71rem' height='4.71rem'
:src="headPortrait">
</van-image>
<div class="aui-margin-t-10 aui-text-center color_fff aui-font-size-18 aui-font-weight">
{{name}}
</div>
</div>
</div>
<div style="padding-bottom: 5vh;" class="nor_box color_fff aui-font-size-13">
<template v-if="start">
<div class="aui-padded-l-15 aui-padded-r-15 aui-flex-col aui-flex-between">
<div @click='muted = !muted' class="aui-text-center ">
<img style="width: 3.3rem;"
:src="muted ? '../../image/chat/call3-close.png' : '../../image/chat/call3-on.png'" />
<div class="aui-margin-t-5">
静音
</div>
</div>
<div @click="hangup" class="aui-text-center ">
<img style="width: 3.3rem;" src="../../image/chat/call2.png" />
<div class="aui-margin-t-5">
挂断
</div>
</div>
<div @click='speakerEnabled = !speakerEnabled' class="aui-text-center ">
<img style="width: 3.3rem;"
:src="speakerEnabled ? '../../image/chat/call1-on.png' :'../../image/chat/call1-close.png'" />
<div class="aui-margin-t-5">
免提
</div>
</div>
</div>
</template>
<template v-else>
<template v-if="callStatus == 1">
<div class="aui-padded-l-15 aui-padded-r-15 aui-flex-col aui-flex-center">
<div @click="hangup" class="aui-text-center ">
<img style="width: 3.3rem;" src="../../image/chat/call2.png" />
<div class="aui-margin-t-5">
挂断
</div>
</div>
</div>
</template>
<template v-else>
<div class="aui-padded-l-15 aui-padded-r-15 aui-flex-col aui-flex-between">
<div @click="hangup" class="aui-text-center ">
<img style="width: 3.3rem;" src="../../image/chat/call2.png" />
<div class="aui-margin-t-5">
挂断
</div>
</div>
<div @click="accept" class="aui-text-center ">
<img style="width: 3.3rem;" src="../../image/chat/call4.png" />
<div class="aui-margin-t-5">
接听
</div>
</div>
</div>
</template>
</template>
</div>
</div>
</body>
<script type="text/javascript" src="../../script/api.js"></script>
<script type="text/javascript" src="../../script/vue.js"></script>
<script type="text/javascript" src="../../script/common.js"></script>
<script type="text/javascript" src="../../script/vant.min.js"></script>
<script type="text/javascript" src="../../script/rongcloud.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: function () {
return {
rong: null,
mediaType: "",
callId: "",
callStatus: "1",
muted: false,
speakerEnabled: false,
start: false,
uid:"",
headPortrait: "",
name: ""
}
},
watch: {
muted: function (newValue) {
vm.rong.setMuted(newValue, function () { })
},
speakerEnabled: function (newValue) {
vm.rong.setSpeakerEnabled(newValue, function () { })
}
},
methods: {
init: function () {
},
accept: function () {
vm.rong.accept({ mediaType: vm.mediaType, callId: vm.callId })
},
hangup() {
vm.rong.hangup()
apiSendEvent('stopVideo');
api.closeWin();
}
}
});
apiready = function () {
vm.callStatus = api.pageParam.callStatus
vm.callId = api.pageParam.callId
vm.mediaType = api.pageParam.mediaType
vm.rong = new RongCloud()
vm.uid = api.pageParam.uid
getAccount(vm.uid, function (res) {
if (res) {
vm.name = res.nickName
vm.headPortrait = res.headPortrait
}
})
vm.init()
apiAddEventListener('myRemoteUserDidJoin', function (ret) {
vm.start = true
vm.rong.setVideoView({
userId: ret.value.targetId,
});
//打开自己的视频
vm.rong.setVideoView({
rect: {
x: api.winWidth - 130,
y: api.safeArea.top + 20,
w: 110,
h: 180
},
userId: ret.value.selfUserId,
});
myOpenFrame('callphone_frm',api.pageParam)
});
}
</script>
</html>