// tim组件工具模块
var timToolsModule = (function(initEmoji){
const defaultImage = 'https://imgcache.qq.com/open/qcloud/video/act/webim-avatar/avatar-2.png';
const c2cType = 'C2C'; //新会话类型,基本都是单聊形式
const groupType = 'GROUP'; //群组类型
const allowType = {
"text": "TIMTextElem",
"image": "TIMImageElem",
"video": "TIMVideoFileElem",
"file": "TIMFileElem",
// "custom": "TIMCustomElem",
};
// img onerror事件,当无法拿到动态图片是 自动去拿默认图片
function onerrorFN(_img){
_img.onerror = function(e){
var e = e || window.event;
var img = e.srcElement;
img.src = defaultImage;
img.οnerrοr=null; //控制不要一直跳动
}
}
// 时间显示规则,当天只显示时:分,之前的时间显示年-月-日 时:分, 传入的是秒数
function showTime(_time){
let time = _time*1000
let YMD = timToolsModule.getDate(new Date(time))
if(YMD == timToolsModule.getDate(new Date())){
return timToolsModule.getTime(new Date(time))
}
// return YMD +'\xa0\xa0'+ timToolsModule.getTime(new Date(time))
return getDate(new Date(time))
}
/**
* 返回年月日
* @export
* @param {Date} date
* @param {string} [splitor='-']
* @returns
*/
function getDate(date, splitor = '-') {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
return `${year}${splitor}${addZeroPrefix(month)}${splitor}${addZeroPrefix(day)}`;
}
/**
* 返回时分秒/时分
* @export
* @param {*} date
* @param {boolean} [withSecond=false]
* @returns
*/
function getTime(date, withSecond = false) {
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return withSecond ? `${addZeroPrefix(hour)}:${addZeroPrefix(minute)}:${addZeroPrefix(second)}` : `${hour}:${addZeroPrefix(minute)}`
}
/**
* 个位数,加0前缀
* @param {*} number
* @returns
*/
function addZeroPrefix(number) {
return number < 10 ? `0${number}`:number
}
// 判断事件是否是今天
function isToday(time) {
return new Date(time * 1000).toDateString() === new Date().toDateString()
}
// 比较两个时间是否间隔超过3分钟
function compareTimeExceed(curTime, preTime){
return (curTime - preTime) > 3 * 60;
}
// 比较两个时间是否是同一天的
function compareTime(curTime, preTime){
return getDate(new Date(curTime * 1000)) == getDate(new Date(preTime * 1000));
}
// 拿到 头像 图片
function getAvatarImg(conversationItem) {
switch (conversationItem.type) {
case groupType:
return defaultAvatarImg(conversationItem.groupProfile.avatar);
case c2cType:
return defaultAvatarImg(conversationItem.userProfile.avatar);
default:
return '';
}
}
// 当图片没有的时候,给一个默认图片
function defaultAvatarImg(imgSrc){
return imgSrc || defaultImage;
}
// 重新装载一次各类型图片
function getMsgObj(msgItem){
var obj = {};
obj.tiem = msgItem.time;
obj.flow = msgItem.flow;
obj.ID = msgItem.ID;
switch(msgItem.type){
case allowType["text"]:
obj.type = msgItem.type;
obj.text = msgItem.payload.text;
break;
case allowType["image"]:
obj.type = msgItem.type;
obj.height = msgItem.payload.imageInfoArray[0].height;
obj.width = msgItem.payload.imageInfoArray[0].width;
obj.imageUrl = msgItem.payload.imageInfoArray[0].imageUrl;
break;
case allowType["video"]:
obj.type = msgItem.type;
obj.thumbHeight = msgItem.payload.thumbHeight;
obj.thumbWidth = msgItem.payload.thumbWidth;
obj.thumbUrl = msgItem.payload.thumbUrl;
obj.videoUrl = msgItem.payload.videoUrl;
break;
case allowType["file"]:
obj.type = msgItem.type;
obj.fileName = msgItem.payload.fileName;
obj.fileSize = msgItem.payload.fileSize;
obj.fileUrl = msgItem.payload.fileUrl;
obj.uuid= msgItem.payload.uuid;
break;
default:
obj.type = allowType["text"];
obj.text = '暂不支持的消息类型,请在手机端查看';
break;
}
return obj;
}
// 判断是否是表情
function isEmoji(t_value){
var param = /^\[.*\]$/;
if(param.test(t_value) && initEmoji.emojiMap[t_value] && initEmoji.emojiMap[t_value] != ''){
return initEmoji.emojiUrl + initEmoji.emojiMap[t_value]
}else{
return ''
}
}
// 生成 guid
function guid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// 计算文件 具体大小
function getFileSize(fileSize) {
const size = fileSize;
if (size > 1024) {
if (size / 1024 > 1024) {
return `${toFixed(size / 1024 / 1024)} Mb`;
}
return `${toFixed(size / 1024)} Kb`;
}
return `${toFixed(size / 1)}B`;
}
// 保留几位小数
function toFixed(number, precision = 2) {
return number.toFixed(precision)
}
// 等到文件的 默认icon
function fileCover(fileUrl, fileName, baseHead_url) {
var cover;
// const postfix = fileUrl.substring(fileUrl.lastIndexOf('.') + 1, fileUrl.length)
const postfix = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length)
switch(postfix){
case 'pdf':
cover = baseHead_url + 'ntalk_tim/images/pdf.png';
break;
case 'zip':
cover = baseHead_url + 'ntalk_tim/images/zip.png';
break;
case 'doc':
cover = baseHead_url + 'ntalk_tim/images/doc.png';
break;
case 'docx':
cover = baseHead_url + 'ntalk_tim/images/doc.png';
break;
case 'xls':
cover = baseHead_url + 'ntalk_tim/images/xls.png';
break;
case 'xlsx':
cover = baseHead_url + 'ntalk_tim/images/xls.png';
break;
case 'ppt':
cover = baseHead_url + 'ntalk_tim/images/ppt.png';
break;
case 'pptx':
cover = baseHead_url + 'ntalk_tim/images/ppt.png';
break;
default:
cover = baseHead_url + 'ntalk_tim/images/txt.png';
break;
}
return cover
}
function getProfileName(item){
if(item.conversationID.indexOf(c2cType) !== -1){
return item.userProfile.nick;
}else if(item.conversationID.indexOf(groupType) !== -1){
return item.groupProfile.name;
}
return '';
}
// 判断是否是链接
function isHttpOrHttps(val){
if(val && val != '' && (val.startsWith("http") || val.startsWith("https"))){
return true;
}
return false;
}
// 删除文字首尾两边空格
function tirm(str){
return str.replace(/(^\s*)|(\s*$)/g, "");
}
// set localStorage数据
function setlocalStorageItem(_id, _name){
if(_id == '' || _name == '') return;
let localStorageStr = localStorage.getItem('$NTALK_IMSDK') || '{}';
let localStorageTab = JSON.parse(localStorageStr);
localStorageTab[_id] = _name;
localStorage.setItem('$NTALK_IMSDK', JSON.stringify(localStorageTab));
}
// get localStorage数据
function getlocalStorageItem(_id){
if(_id == '') return '';
let localStorageStr = localStorage.getItem('$NTALK_IMSDK') || '{}';
let localStorageTab = JSON.parse(localStorageStr);
return localStorageTab[_id] || '';
}
return {
onerrorFN: onerrorFN,
showTime: showTime,
getDate: getDate,
getTime: getTime,
isToday: isToday,
compareTime: compareTime,
compareTimeExceed: compareTimeExceed,
getAvatarImg: getAvatarImg,
defaultAvatarImg: defaultAvatarImg,
getMsgObj: getMsgObj,
isEmoji: isEmoji,
guid: guid,
getFileSize: getFileSize,
fileCover: fileCover,
getProfileName: getProfileName,
isHttpOrHttps: isHttpOrHttps,
tirm: tirm,
setlocalStorageItem: setlocalStorageItem,
getlocalStorageItem: getlocalStorageItem,
}
})(initEmoji);
// 组件对象,主要逻辑操作都封装在这里
;(function(document, timToolsModule, initEmoji){
const defaultImage = 'https://imgcache.qq.com/open/qcloud/video/act/webim-avatar/avatar-2.png'; // 默认图片
let loadingImage = '{{baseHead_url}}ntalk_tim/images/loading.gif'; // loading图片
const c2cType = 'C2C'; // 新会话类型,基本都是单聊形式
const groupType = 'GROUP'; // 群组类型
let curLoginPortrait; // 保存当前登录用户的头像
let currentSelectConversation; // 保存当前选中的会话
const allowType = {
"text": "TIMTextElem",
"image": "TIMImageElem",
"video": "TIMVideoFileElem",
"file": "TIMFileElem",
// "custom": "TIMCustomElem",
};
const tqlHtml = `
回到最新位置
`;
// 初始化对象
var TimComponent = function(opt) {
this.SDKAppID = opt.SDKAppID;
this.userId = opt.userId;
this.userSig = opt.userSig;
this.privateChatId = opt.privateChatId;
this.privateChatName = opt.privateChatName;
this.timPosition = opt.timPosition; // 位置状态:1、居中;2、左上;3、左下;4、右上;5、右下
this.baseHead_url = opt.baseHead_url || ''; // 模板类型
this.unreadListener = opt.unreadListener || undefined; // 回调函数
this.unreadChangeListener = opt.unreadChangeListener || undefined; // 回调函数
this.tim;
// 记录会话列表
this.conversationListData = [];
// 记录当前消息列表
this.currentMsgData = [];
// 记录当前消息列表 是否已加载完成
this.isCompleted = true;
// 记录当前消息列表未加载完成的 分页续拉ID
this.nextReqMessageID = '';
// 记录上一次点击的会话
this.lastTimeConversationID = '';
// 记录私聊用户信息
this.privateChatOpt = {
userID: '',
nick: '',
avatar: '',
selfSignature: ''
}
var options = {
SDKAppID: this.SDKAppID // 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
};
// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
this.tim = TIM.create(options);
// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
this.tim.setLogLevel(4); // 普通级别,日志量较多,接入时建议使用
// tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
// 注册腾讯云即时通信 IM 上传插件,即时通信 IM SDK 发送图片、语音、视频、文件等消息需要使用上传插件,将文件上传到腾讯云对象存储
// this.tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});
// 注册 cos
this.tim.registerPlugin({ 'cos-js-sdk': COS })
this.bindTimEvent(this);
this.isLogin = false;
this.J_timContainer = document.querySelector('#J_timContainer');
this.J_timLeft;
this.J_timLeft_portrait,
this.J_timLeft_switch;
this.J_timRight;
this.J_timRTop_info_img;
this.J_timRTop_info_name_fir;
this.J_timRTop_info_name_sec;
this.J_timRTop_reduce;
this.J_inputMsg;
this.icon_happy;
this.J_timSend;
this.emojis;
this.J_timRBottom_image;
this.J_imagePicker;
this.J_timAmplify;
this.J_timAmplify_img;
this.J_timRBottom_file
this.J_videoPicker;
this.J_filePicker;
this.J_timTips;
this.J_timTips_span;
this.J_timLoading;
this.J_timReturn_newMsg;
this.J_timMsg_moreHandle;
this.J_timRMiddle;
this.copyEle;
this.forwardEle;
this.recallEle;
this.downloadEle;
this.J_timForward_layer;
this.J_timForward_list;
this.J_timForward_btn_close;
this.J_timForward_btn_forward;
}
// SDK 登录
TimComponent.prototype.handleLogin = function(opt){
var _this = this;
let userId = opt.userId;
let promise = this.tim.login({userID: opt.userId, userSig: opt.userSig});
promise.then(function(imResponse) {
console.log('login success===========================>>')
_this.initDOM();
// _this.tipsShow('登录成功');
_this.isLogin = true;
_this.J_timContainer.style.display = 'flex';
_this.initParam(opt);
_this.handleTimPosition(_this.timPosition);
if (imResponse.data.repeatLogin === true) {
// 标识账号已登录,本次登录操作为重复登录。v2.5.1 起支持
_this.tipsShow(imResponse.data.errorInfo);
}
}).catch(function(imError) {
_this.isLogin = false;
console.warn('login error:', imError); // 登录失败的相关信息
});
}
// 加载 dom节点模板
TimComponent.prototype.initDOM = function(){
this.J_timContainer.innerHTML = '';
// J_timTql = document.querySelector('#J_timTql');
this.J_timContainer.innerHTML = tqlHtml.replace(/{{baseHead_url}}/g, this.baseHead_url);
loadingImage = loadingImage.replace(/{{baseHead_url}}/g, this.baseHead_url);;
this.J_timLeft = this.J_timContainer.querySelector('.J_timLeft');
this.J_timLeft_portrait = this.J_timLeft.querySelector('.J_timLeft_portrait'),
this.J_timLeft_switch = this.J_timLeft.querySelector('.J_timLeft_switch');
this.J_timRight = this.J_timContainer.querySelector('.J_timRight');
// this.J_timRTop_info_img = this.J_timRight.querySelector('.J_timRTop_info img');
this.J_timRTop_info_name_fir = this.J_timRight.querySelectorAll('.J_timRTop_info_name span')[0];
// this.J_timRTop_info_name_sec = this.J_timRight.querySelectorAll('.J_timRTop_info_name span')[1];
this.J_timRTop_reduce = this.J_timRight.querySelector('.J_timRTop_reduce');
this.J_inputMsg = this.J_timRight.querySelector('#J_inputMsg');
this.icon_happy = this.J_timRight.querySelector('.J_timRBottom_emojis');
this.J_timSend = this.J_timRight.querySelector('.J_timSend');
this.emojis = this.J_timContainer.querySelector('.emojis');
this.J_timRBottom_image = this.J_timRight.querySelector('.J_timRBottom_image');
this.J_imagePicker = this.J_timContainer.querySelector('#J_imagePicker');
this.J_timAmplify = this.J_timContainer.querySelector('.J_timAmplify');
this.J_timAmplify_img = this.J_timContainer.querySelector('.J_timAmplify img');
this.J_timRBottom_file = this.J_timRight.querySelector('.J_timRBottom_file');
this.J_videoPicker = this.J_timContainer.querySelector('#J_videoPicker');
this.J_filePicker = this.J_timContainer.querySelector('#J_filePicker');
this.J_timTips = this.J_timContainer.querySelector('.J_timTips');
this.J_timTips_span = this.J_timContainer.querySelector('.J_timTips span');
this.J_timLoading = this.J_timContainer.querySelector('.J_timLoading');
this.J_timReturn_newMsg = this.J_timContainer.querySelector('.J_timReturn_newMsg');
this.J_timMsg_moreHandle = this.J_timContainer.querySelector('.J_timMsg_moreHandle');
this.J_timRMiddle = this.J_timContainer.querySelector('.J_timRMiddle');
this.copyEle = this.J_timMsg_moreHandle.querySelector('.copy');
this.forwardEle = this.J_timMsg_moreHandle.querySelector('.forward');
this.recallEle = this.J_timMsg_moreHandle.querySelector('.recall');
this.downloadEle = this.J_timMsg_moreHandle.querySelector('.download');
this.J_timForward_layer = this.J_timContainer.querySelector('.J_timForward_layer');
this.J_timForward_list = this.J_timForward_layer.querySelector('.J_timForward_list');
this.J_timForward_btn_close = this.J_timForward_layer.querySelectorAll('.J_timForward_btn button')[0];
this.J_timForward_btn_forward = this.J_timForward_layer.querySelectorAll('.J_timForward_btn button')[1];
// this.bindTimEvent();
this.bindEleEvent();
this.renderEmojiList();
//首次让从左边滑过来
// this.reduceClick();
this.initMousedown();
}
// 理论上update 是切换新的私聊操作
TimComponent.prototype.updateOpt = function(opt){
var _this = this;
// this.privateChatId = opt.privateChatId;
// currentSelectConversation = c2cType + this.privateChatId;
this.initParam(opt);
this.getPrivateChatProfile(this.privateChatId);
// 获得会话列表
this.getConversationList();
// 当切换用户的时候 再获得一次新用户的 会话列表
if(_this.privateChatId == ''){
setTimeout(function(){
_this.getMsgList(c2cType + _this.privateChatId);
}, 1000)
}else{
_this.getMsgList(c2cType + _this.privateChatId);
}
// 判断私聊用户是不是一个新的会话
this.isNewConversation();
}
// 无论实例是否是第一次初始化,或者是第一次登录,或者更新切换新的私聊 都需要重置的值
TimComponent.prototype.initParam = function(opt){
this.privateChatId = opt.privateChatId;
this.privateChatName = opt.privateChatName;
timToolsModule.setlocalStorageItem(this.privateChatId, this.privateChatName);
currentSelectConversation = this.privateChatId != '' ? c2cType + this.privateChatId : '';
this.conversationListData = [];
this.currentMsgData = [];
this.isCompleted = true;
this.nextReqMessageID = '';
this.lastTimeConversationID = '';
this.privateChatOpt = {
userID: '',
nick: '',
avatar: '',
selfSignature: ''
}
this.timPosition = opt.timPosition;
this.unreadListener = opt.unreadListener || undefined;
this.unreadChangeListener = opt.unreadChangeListener || undefined; // 回调函数
this.isMaxContainer();
}
TimComponent.prototype.getPrivateChatProfile = function(_userid){
if(_userid == ''){
return
}
var _this = this;
let promise = this.tim.getUserProfile({
userIDList: [_userid]
});
promise.then(function(imResponse) {
// console.log(imResponse.data); // 存储用户资料的数组 - [Profile]
_this.privateChatOpt = {
userID: imResponse.data[0].userID,
nick: imResponse.data[0].nick || imResponse.data[0].userID,
avatar: imResponse.data[0].avatar,
selfSignature: imResponse.data[0].selfSignature
}
}).catch(function(imError) {
console.warn('getUserProfile error:', imError); // 获取其他用户资料失败的相关信息
});
}
// 绑定tim 事件
TimComponent.prototype.bindTimEvent = function(_this){
this.tim.on(TIM.EVENT.SDK_READY, this.onReadyEvent.bind(this));
this.tim.on(TIM.EVENT.SDK_NOT_READY, this.onNotReadyEvent.bind(this));
this.tim.on(TIM.EVENT.KICKED_OUT, this.onKickedOutEvent.bind(this), this);
this.tim.on(TIM.EVENT.NET_STATE_CHANGE, this.onNetStateChangeEvent.bind(this), this);
this.tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.onMsgReceivedEvent.bind(_this), _this);
this.tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onUpdateConversationListEvent.bind(this), this);
this.tim.on(TIM.EVENT.ERROR, this.onErrorEvent.bind(this));
this.tim.on(TIM.EVENT.MESSAGE_REVOKED, this.onMessageRevokedEvent.bind(this), this);
}
// 取消tim 事件监听,有点问题好像不会生效
TimComponent.prototype.destroyBindTimEvent = function(){
this.tim.off(TIM.EVENT.SDK_READY, this.onReadyEvent.bind(this));
this.tim.off(TIM.EVENT.SDK_NOT_READY, this.onNotReadyEvent.bind(this));
this.tim.off(TIM.EVENT.KICKED_OUT, this.onKickedOutEvent.bind(this));
this.tim.off(TIM.EVENT.NET_STATE_CHANGE, this.onNetStateChangeEvent.bind(this));
this.tim.off(TIM.EVENT.MESSAGE_RECEIVED, this.onMsgReceivedEvent.bind(this));
this.tim.off(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onUpdateConversationListEvent.bind(this));
this.tim.off(TIM.EVENT.ERROR, this.onErrorEvent.bind(this));
this.tim.off(TIM.EVENT.MESSAGE_REVOKED, this.onMessageRevokedEvent.bind(this), this);
}
TimComponent.prototype.onMessageRevokedEvent = function(event){
// 收到消息被撤回的通知。使用前需要将SDK版本升级至v2.4.0或更高版本。
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
console.log('MESSAGE_REVOKED', event.data)
if(event.data[0].conversationID == currentSelectConversation){
this.updateRevokedMsgList(event.data[0]);
}else{
this.conversationListData.forEach( item => {
if(event.data[0].conversationID == item.conversationID){
item.unreadCount += 1;
}
})
//更新会话
this.createLeftInfoList(this.conversationListData, {
updateList: true
});
}
}
// SDK 发生错误时事件监听
TimComponent.prototype.onErrorEvent = function(event){
// 收到 SDK 发生错误通知,可以获取错误码和错误信息
// event.name - TIM.EVENT.ERROR
// event.data.code - 错误码
// event.data.message - 错误信息
console.log('TIM.EVENT.ERROR',event)
}
// SDK not ready时事件监听
TimComponent.prototype.onNotReadyEvent = function(event) {
// 收到 SDK 进入 not ready 状态通知,此时 SDK 无法正常工作
// event.name - TIM.EVENT.SDK_NOT_READY
// this.tipsShow('小壹暂时无法正常工作,先帮您提前下线~');
// this.J_timLeft_switch.click();
console.log('SDK_NOT_READY');
};
// SDK 收到被踢下线监听
TimComponent.prototype.onKickedOutEvent = function(event) {
// 收到被踢下线通知
// event.name - TIM.EVENT.KICKED_OUT
// event.data.type - 被踢下线的原因,例如 :
// - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢
// - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢
// - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢(v2.4.0起支持)。
console.log('onKickedOut',event)
switch(event.data.type){
case TIM.TYPES.KICKED_OUT_MULT_ACCOUNT:
this.handleLogout('多终端登录,此处被下线~');
break;
case TIM.TYPES.KICKED_OUT_MULT_DEVICE:
this.handleLogout('多终端登录,此处被下线~');
break;
case TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED:
this.handleLogout('签名过期,此处被下线~');
break;
default:
break;
}
this.isLogin = false;
};
// SDK 收到网络状态更改
TimComponent.prototype.onNetStateChangeEvent = function(event) {
// 网络状态发生改变(v2.5.0 起支持)。
// event.name - TIM.EVENT.NET_STATE_CHANGE
// event.data.state 当前网络状态,枚举值及说明如下:
// - TIM.TYPES.NET_STATE_CONNECTED - 已接入网络
// - TIM.TYPES.NET_STATE_CONNECTING - 连接中。很可能遇到网络抖动,SDK 在重试。接入侧可根据此状态提示“当前网络不稳定”或“连接中”
// - TIM.TYPES.NET_STATE_DISCONNECTED - 未接入网络。接入侧可根据此状态提示“当前网络不可用”。SDK 仍会继续重试,若用户网络恢复,SDK 会自动同步消息
switch(event.data.state){
case TIM.TYPES.NET_STATE_CONNECTING:
this.tipsShow('网络连接中~');
break;
case TIM.TYPES.NET_STATE_DISCONNECTED:
this.tipsShow('未连接网络~');
break;
default:
break;
}
};
// SDK 收到会话列表更新
TimComponent.prototype.onUpdateConversationListEvent = function(event){
// 收到会话列表更新通知,可通过遍历 event.data 获取会话列表数据并渲染到页面
// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
// event.data - 存储 Conversation 对象的数组 - [Conversation]
console.log('CONVERSATION_LIST_UPDATED',event.data)
this.updateConversationList(event.data, {
updateList: true
});
let unreadCount = 0;
event.data.forEach(item => {
unreadCount += item.unreadCount;
});
this.unreadListener && unreadCount >= 0 && this.unreadListener(unreadCount);
}
// SDK 收到单聊,群聊新消息提示
TimComponent.prototype.onMsgReceivedEvent = function(event){
// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面
// event.name - TIM.EVENT.MESSAGE_RECEIVED
// event.data - 存储 Message 对象的数组 - [Message]
console.log('MESSAGE_RECEIVED',event.data)
if(event.data[0].conversationID == currentSelectConversation){
this.updateCurrentMsgList(event.data[0]);
}
}
// SDK ready状态
TimComponent.prototype.onReadyEvent = function(event) {
var _this = this;
this.getPrivateChatProfile(this.privateChatId);
// 获得会话列表
this.getConversationList();
// this.getFriendList();
// 获得首个消息列表 现在写死成私聊成员
if(_this.privateChatId == ''){
setTimeout(function(){
_this.getMsgList(c2cType + _this.privateChatId);
}, 1000)
}else{
_this.getMsgList(c2cType + _this.privateChatId);
}
// 判断私聊用户是不是一个新的会话
this.isNewConversation();
}
// 判断私聊用户是否在 已有会话中
TimComponent.prototype.isNewConversation = function(){
if(this.privateChatId == ''){
return
}
var _this = this;
var isNew = this.conversationListData.some( item => {
return item.conversationID == c2cType + _this.privateChatId;
})
!isNew && this.getUserProfile(c2cType + _this.privateChatId);
}
// 获得好友列表
TimComponent.prototype.getFriendList = function(){
this.tim.getFriendList().then(({ data: friendList }) => {
console.log('friendList',...friendList);
})
}
// 获得会话列表
TimComponent.prototype.getConversationList = function(){
// 拉取会话列表
var _this = this;
let getConversationListPromise = this.tim.getConversationList();
getConversationListPromise.then(function(imResponse) {
const conversationList = imResponse.data.conversationList; // 会话列表,用该列表覆盖原有的会话列表
_this.updateConversationList(conversationList, {
updateList: false
});
}).catch(function(imError) {
console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
});
}
// 更改会话列表
TimComponent.prototype.updateConversationList = function(conversationList, opt){
var _this = this;
let arr = [];
for (let i in this.conversationListData) {
let flag = 0;
for (let a in conversationList) {
if (
_this.conversationListData[i].conversationID ==
conversationList[a].conversationID
) {
flag = 1;
}
}
if (!flag) {
//若没有则存入
arr.push(_this.conversationListData[i]);
}
}
_this.conversationListData = arr.concat(conversationList);
//更新会话
_this.createLeftInfoList(_this.conversationListData, {
updateList: opt.updateList
});
}
// 更改当前消息列表,添加一条消息的时候
TimComponent.prototype.updateCurrentMsgList = function(lastMsg){
this.currentMsgData.push(lastMsg);
this.renderMsgList(this.currentMsgData);
}
// 更改当前消息列表,撤销状态更改
TimComponent.prototype.updateRevokedMsgList = function(msgItem){
this.currentMsgData.forEach(item => {
if(msgItem.ID == item.ID){
item.isRevoked = msgItem.isRevoked;
}
})
this.renderMsgList(this.currentMsgData);
}
// 创建左边栏信息,主要是 会话信息
TimComponent.prototype.createLeftInfoList = function(dataList, opt){
var _this = this;
// 先清空数据
this.J_timLeft_portrait.innerHTML = '';
var d = document.createDocumentFragment();
let _newC2C = this.privateChatId;
let newC2CIndex = -1;
if(_newC2C && _newC2C !== ''){
newC2CIndex = dataList.findIndex(item => {
return item.conversationID == c2cType + _newC2C;
})
if(newC2CIndex === -1){
_this.createNewConversation({
conversationID: c2cType + _newC2C,
img: _this.privateChatOpt.avatar,
unreadCount: 0
}, d);
}
}
dataList.forEach(item => {
_this.createNewConversation({
conversationID: item.conversationID,
img: timToolsModule.getAvatarImg(item),
unreadCount: item.unreadCount
}, d);
});
this.J_timLeft_portrait.appendChild(d);
let currentSelectConIndex = -1;
if(currentSelectConversation && currentSelectConversation !== ''){
for(var i = 0; i < this.J_timLeft_portrait.children.length; i++){
if(this.J_timLeft_portrait.children[i].dataset.conversationid == currentSelectConversation){
currentSelectConIndex = i;
}
}
}
// 模拟点击选中
// 1、私聊,私聊人员不在列表中,会加载到第一个,默认选中私聊
// 2、私聊,如果私聊人员在会话列表中则选中 私聊人员
// 3、不是私聊,默认选中上一次选中的item
// 4、不是私聊,第一次打开也是默认选中 第一个
let selectIndex = currentSelectConIndex;
// updateList的时候 是更新列表 已选中的优先级更高
if(opt.updateList){
selectIndex = currentSelectConIndex === -1
? newC2CIndex === -1 ? 0 : newC2CIndex
: currentSelectConIndex;
}else{
if(_newC2C && _newC2C !== ''){
selectIndex = newC2CIndex === -1 ? 0 : newC2CIndex;
}else{
selectIndex = currentSelectConIndex === -1 ? 0 : currentSelectConIndex;
}
}
this.J_timLeft_portrait.children.forEach((item, i) => {
if( i == selectIndex ){
item.className += ' hoverC';
_this.updateProfile(item.dataset.conversationid, item);
currentSelectConversation = item.dataset.conversationid;
var _span = item.getElementsByTagName('span');
if(_span[0].dataset.unreadCount > 0 && item.dataset.conversationid == currentSelectConversation){
if(this.J_timRight.style.opacity == 0){
_span[0].style.display = 'block';
}else{
this.sendMsgRead(item.dataset.conversationid);
_span[0].dataset.unreadCount = 0;
_span[0].style.display = 'none';
}
}
}
item.addEventListener('click', _this.portraitItemClick.bind(_this), false);
})
// this.J_timLeft_portrait.children[selectIndex].click();
}
// 通过已知的会话列表 更新用户或者群组信息
TimComponent.prototype.updateProfile = function(conversationid, target){
var _this = this;
this.conversationListData.forEach( item => {
if(item.conversationID == conversationid){
_this.J_inputMsg.dataset.conversationid = conversationid;
if(conversationid.indexOf(c2cType) !== -1){
this.renderProfile({
img: timToolsModule.defaultAvatarImg(item.userProfile.avatar),
nick: item.userProfile.nick || item.userProfile.userID,
selfSignature: item.userProfile.userID, //selfSignature
userId: item.userProfile.userID,
},target)
// 切换会话时把信息回调
this.changeCallBack({
conversationID: conversationid,
userName: item.userProfile.nick || item.userProfile.userID,
});
}else if(conversationid.indexOf(groupType) !== -1){
this.renderProfile({
img: timToolsModule.defaultAvatarImg(item.groupProfile.avatar),
nick: item.groupProfile.name,
selfSignature: '这是一个群组',
userId: '',
},target)
// 切换会话时把信息回调
this.changeCallBack({
conversationID: conversationid,
userName: item.groupProfile.name,
});
}
}
})
}
// 创建左边列表Item,主要需要数据为 conversationID和img
/**
*
* @param {*} opt
* {
* conversationID: 会话id
* img: 图片
* unreadCount: 未读信息条数
* }
* @param {*} d 创建的文档碎片
*/
TimComponent.prototype.createNewConversation = function (opt, d){
var _div = document.createElement('div');
_div.dataset.conversationid = opt.conversationID;
_div.className = 'J_timLeft_portraitC';
var _img = document.createElement('img');
_img.src = opt.img;
_img.alt = '';
timToolsModule.onerrorFN(_img);
_div.appendChild(_img);
var _span = document.createElement('span');
_span.dataset.unreadCount = opt.unreadCount;
_span.style.display = opt.unreadCount > 0 ? 'block' : 'none';
_div.appendChild(_span);
d.appendChild(_div);
}
// 绑定左边各item的点击事件
TimComponent.prototype.portraitItemClick = function (e){
var e = e || window.event,
// target = e.target || e.srcElement;
target = e.currentTarget;
e.stopPropagation();
currentSelectConversation = target.dataset.conversationid;
this.J_timLeft_portrait.children.forEach(nodeItem => {
nodeItem.className = 'J_timLeft_portraitC';
})
target.className += ' hoverC';
var _span = target.getElementsByTagName('span');
if(_span[0].dataset.unreadCount > 0 && target.dataset.conversationid == currentSelectConversation){
this.sendMsgRead(target.dataset.conversationid);
_span[0].dataset.unreadCount = 0;
_span[0].style.display = 'none';
}else{
_span[0].style.display = 'none';
}
this.getUserProfile(target.dataset.conversationid, true);
this.getMsgList(target.dataset.conversationid);
this.isMaxContainer();
}
// 组装右边部分数据
TimComponent.prototype.getUserProfile = function(conversationID, switchFlag){
// const conversationID = tar.dataset.conversationid;
var _this = this;
this.J_inputMsg.dataset.conversationid = conversationID;
// this.bindInputkeypress();
if(conversationID.indexOf(c2cType) !== -1){
//获得个人的详细资料
let promise = this.tim.getUserProfile({
userIDList: [conversationID.replace(c2cType, '')] // 请注意:即使只拉取一个用户的资料,也需要用数组类型,例如:userIDList: ['user1']
});
promise.then(function(imResponse) {
// console.log('getUserProfile',imResponse.data); // 存储用户资料的数组 - [Profile]
_this.renderProfile({
img: timToolsModule.defaultAvatarImg(imResponse.data[0].avatar),
nick: imResponse.data[0].nick || imResponse.data[0].userID,
selfSignature: imResponse.data[0].userID, //selfSignature
userId: imResponse.data[0].userID,
})
// 切换会话时把信息回调
switchFlag && _this.changeCallBack({
conversationID: conversationID,
userName: imResponse.data[0].nick || imResponse.data[0].userID,
});
}).catch(function(imError) {
console.warn('getUserProfile error:', imError); // 获取其他用户资料失败的相关信息
});
}else if(conversationID.indexOf(groupType) !== -1){
//获得群组的详细资料
let promise = this.tim.getGroupProfile({ groupID: conversationID.replace(groupType, '') });
promise.then(function(imResponse) {
// console.log(imResponse.data.group);
_this.renderProfile({
img: timToolsModule.defaultAvatarImg(imResponse.data.avatar),
nick: imResponse.data.group.name + '(' + imResponse.data.group.memberCount + ')',
selfSignature: '群组',
userId: '',
})
// 切换会话时把信息回调
switchFlag && _this.changeCallBack({
conversationID: conversationID,
userName: imResponse.data.group.name + '(' + imResponse.data.group.memberCount + ')',
});
}).catch(function(imError) {
console.warn('getGroupProfile error:', imError); // 获取群详细资料失败的相关信息
});
}
}
// 渲染用户或者群组信息
TimComponent.prototype.renderProfile = function(opt){
// this.J_timRTop_info_img.src = opt.img;
// timToolsModule.onerrorFN(this.J_timRTop_info_img);
this.J_timRTop_info_name_fir.innerHTML = timToolsModule.getlocalStorageItem(opt.userId.replace(c2cType, '')) || opt.nick;
// this.J_timRTop_info_name_sec.innerHTML = opt.selfSignature; //imResponse.data.group.ownerID
// tar.querySelector('img').src = opt.img;
// timToolsModule.onerrorFN(tar.querySelector('img').src);
}
// 把信息回调
TimComponent.prototype.changeCallBack = function(opt){
let id;
let types;
if(opt.conversationID.indexOf(c2cType) !== -1){
id = opt.conversationID.replace(c2cType, '');
types = c2cType;
}else if(opt.conversationID.indexOf(groupType) !== -1){
id = opt.conversationID.replace(groupType, '');
types = groupType;
}
this.unreadChangeListener && this.unreadChangeListener(this.J_timRTop_info_name_fir,{
type: types,
userId: id,
userName: opt.userName,
})
}
// 组装当前选中第一次消息列表数据
TimComponent.prototype.getMsgList = function(conversationID){
if(conversationID == c2cType && this.conversationListData[0] && this.conversationListData[0].conversationID != ''){
conversationID = this.conversationListData[0].conversationID;
}else if(conversationID == this.lastTimeConversationID){
return;
}else if(conversationID == c2cType){
return;
}
this.lastTimeConversationID = conversationID;
var _this = this;
// const conversationID = conversationItem.dataset.conversationid;
// 打开某个会话时,第一次拉取消息列表
let promise = this.tim.getMessageList({conversationID: conversationID ,count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
_this.isCompleted = isCompleted;
if(!isCompleted){
_this.nextReqMessageID = nextReqMessageID || '';
}
_this.currentMsgData = messageList;
_this.renderMsgList(_this.currentMsgData);
});
}
// 组装当前选中消息列表 分页数据
TimComponent.prototype.getNextReqMsgList = function(){
var _this = this;
// const conversationID = conversationItem.dataset.conversationid;
const conversationID = currentSelectConversation;
// 打开某个会话时,第一次拉取消息列表
let promise = this.tim.getMessageList({conversationID: conversationID, nextReqMessageID: this.nextReqMessageID, count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
_this.isCompleted = isCompleted;
if(!isCompleted){
_this.nextReqMessageID = nextReqMessageID || '';
}
// _this.currentMsgData = messageList;
_this.updateAllCurrentMsgList(isCompleted, messageList)
_this.renderMsgList(_this.currentMsgData, true);
_this.msgMiddleFirstItem();
_this.switchReturnElement();
});
}
// 更新当前消息的所有信息
TimComponent.prototype.updateAllCurrentMsgList = function(isCompleted, messageList){
this.currentMsgData = [
// 更新当前消息列表,从头部插入
// 聊天记录 数组合并
...messageList,
...this.currentMsgData,
]
}
// 组装右边消息列表数据
TimComponent.prototype.renderMsgList = function(messageList, lastMsgFlag){
var _this = this;
// 先清空数据
_this.J_timRMiddle.innerHTML = '';
// 当isCompleted为false的时候,添加一个更多消息
if(!this.isCompleted){
_this.renderMoreMsgItem();
}
// let userId = localStorage.getItem('#userID');
messageList.forEach((item, index) => {
let timeFlag = false;
// 显示时间规则
// 1、首条消息显示时间
// 2、当天消息全部显示时间
// 3、之前的消息只显示一次时间
if(index == 0
|| (timToolsModule.isToday(item.time) && timToolsModule.compareTimeExceed(messageList[index].time, messageList[index - 1].time))
|| !timToolsModule.compareTime(messageList[index].time, messageList[index - 1].time)
){
timeFlag = true;
}
timeFlag && _this.renderMsgMiddleItem({
flag: true,
time: timToolsModule.showTime(item.time)
});
if(item.conversationType == groupType){
_this.renderGroupMsg(item);
}else if(item.conversationType == c2cType){
_this.renderC2CMsg(item);
}
})
if( !lastMsgFlag ){
setTimeout(function(){
_this.msgMiddleLastItem();
}, 1000)
}
}
// 渲染 群组的消息列表
TimComponent.prototype.renderGroupMsg = function(item){
var _this = this;
if(item.isRevoked && item.isRevoked == true){
_this.renderMsgMiddleItem({
flag: false,
htmlVal: (item.flow == 'out' ? '您 ' : item.nick + ' ') + '撤回了一条消息'
});
}else if(item.payload.data == 'group_create'){
_this.renderMsgMiddleItem({
flag: false,
htmlVal: item.payload.extension || item.payload.description
});
}else if(_this.userId == item.from){
_this.renderMsgRightItem({
item: timToolsModule.getMsgObj(item),
htmlVal: item.payload.text || item.payload.description,
img: timToolsModule.defaultAvatarImg(item.avatar)
});
}else{
_this.renderMsgLeftItem({
item: timToolsModule.getMsgObj(item),
htmlVal: item.payload.text || item.payload.description,
img: timToolsModule.defaultAvatarImg(item.avatar)
});
}
}
// 渲染 个人的消息列表
TimComponent.prototype.renderC2CMsg = function(item){
var _this = this;
if(item.isRevoked && item.isRevoked == true){
_this.renderMsgMiddleItem({
flag: false,
htmlVal: (item.flow == 'out' ? '您 ' : item.nick + ' ') + '撤回了一条消息'
});
}else if(_this.userId == item.from){
_this.renderMsgRightItem({
item: timToolsModule.getMsgObj(item),
htmlVal: item.payload.text || item.payload.description,
img: timToolsModule.defaultAvatarImg(item.avatar)
});
}else{
_this.renderMsgLeftItem({
item: timToolsModule.getMsgObj(item),
htmlVal: item.payload.text || item.payload.description,
img: timToolsModule.defaultAvatarImg(item.avatar)
});
}
}
// 渲染 中间更多消息
TimComponent.prototype.renderMoreMsgItem = function(){
var d = document.createDocumentFragment();
var J_timR_msgM = document.createElement('div');
J_timR_msgM.className = 'J_timR_msgM';
var J_timR_msgM_more = document.createElement('div');
J_timR_msgM_more.className = 'J_timR_msgM_more';
J_timR_msgM_more.innerHTML = '查看更多';
J_timR_msgM_more.addEventListener('click', this.getNextReqMsgList.bind(this), false);
J_timR_msgM.appendChild(J_timR_msgM_more);
d.appendChild(J_timR_msgM);
this.J_timRMiddle.appendChild(d);
}
// 组装消息列表左边数据
/**
*
* @param {*} opt
* {
* htmlVal: 显示信息
* img: 头像图片
* }
*/
TimComponent.prototype.renderMsgLeftItem = function(opt){
var d = document.createDocumentFragment();
var J_timR_msgL = document.createElement('div');
J_timR_msgL.className = 'J_timR_msgL';
var _img = document.createElement('img');
_img.src = opt.img;
timToolsModule.onerrorFN(_img);
J_timR_msgL.appendChild(_img);
var _div = document.createElement('div');
_div.className = 'J_timR_msgL_con';
// var _span = document.createElement('span');
// _span.innerHTML = opt.htmlVal;
// _div.appendChild(_span);
var msgObj = opt.item;
_div.appendChild(this.renderAllTypeMsg(msgObj));
J_timR_msgL.appendChild(_div);
d.appendChild(J_timR_msgL);
this.J_timRMiddle.appendChild(d);
}
// 组装消息列表中间数据
/**
*
* @param {} opt
* {
* flag: 判断是否是时间
* time: 时间秒数,基本时间和显示信息 二选一展示
* htmlVal: 显示信息
* }
*/
TimComponent.prototype.renderMsgMiddleItem = function(opt){
var d = document.createDocumentFragment();
var J_timR_msgM = document.createElement('div');
J_timR_msgM.className = 'J_timR_msgM';
var J_timR_msgM_con = document.createElement('div');
J_timR_msgM_con.className = 'J_timR_msgM_con';
if(opt.flag){
J_timR_msgM_con.innerHTML = opt.time;
}else{
J_timR_msgM_con.className = 'J_timR_msgM_con revoke';
J_timR_msgM_con.innerHTML = opt.htmlVal;
}
J_timR_msgM.appendChild(J_timR_msgM_con);
d.appendChild(J_timR_msgM);
this.J_timRMiddle.appendChild(d);
}
// 组装消息列表右边数据
/**
*
* @param {*} opt
* {
* htmlVal: 显示信息
* img: 头像图片
* }
*/
TimComponent.prototype.renderMsgRightItem = function(opt){
curLoginPortrait = opt.img;
var d = document.createDocumentFragment();
var J_timR_msgR = document.createElement('div');
J_timR_msgR.className = 'J_timR_msgR';
var _img = document.createElement('img');
_img.src = loadingImage;
_img.style.display = opt.loading ? 'block' : 'none';
J_timR_msgR.appendChild(_img);
var _div = document.createElement('div');
_div.className = 'J_timR_msgR_con';
var msgObj = opt.item;
_div.appendChild(this.renderAllTypeMsg(msgObj));
J_timR_msgR.appendChild(_div);
var _img = document.createElement('img');
_img.src = opt.img;
timToolsModule.onerrorFN(_img);
J_timR_msgR.appendChild(_img);
d.appendChild(J_timR_msgR);
this.J_timRMiddle.appendChild(d);
}
// 渲染所有类型的消息
TimComponent.prototype.renderAllTypeMsg = function(msgObj){
var ele;
if(msgObj.type == allowType["text"]){
if(timToolsModule.isHttpOrHttps(msgObj.text)){
var _a = document.createElement('a');
_a.href = msgObj.text;
_a.target = '_blank';
_a.innerHTML = msgObj.text;
_a.dataset.id = msgObj.ID;
_a.dataset.type = msgObj.type;
_a.addEventListener('contextmenu', this.initContextmenuEvent.bind(this, msgObj.flow), false);
ele = _a;
}else{
var _div = document.createElement('div');
_div.className = 'J_textElem';
let decodeText_d = document.createDocumentFragment();
this.decodeText(msgObj.text, decodeText_d);
_div.appendChild(decodeText_d);
_div.dataset.id = msgObj.ID;
_div.dataset.type = msgObj.type;
_div.addEventListener('contextmenu', this.initContextmenuEvent.bind(this, msgObj.flow), false);
ele = _div;
}
}else if(msgObj.type == allowType["image"]){
// 显示图片
var _img = document.createElement('img');
_img.className = 'J_imgElem';
_img.src = msgObj.imageUrl;
_img.dataset.id = msgObj.ID;
_img.dataset.type = msgObj.type;
_img.dataset.imageUrl = msgObj.imageUrl;
_img.addEventListener('contextmenu', this.initContextmenuEvent.bind(this, msgObj.flow), false);
_img.addEventListener('click', this.amplifyImgEvent.bind(this), false);
ele = _img;
}else if(msgObj.type == allowType["video"]){
var _video = document.createElement('video');
_video.controls = 'controls';
_video.src = msgObj.videoUrl;
_video.dataset.id = msgObj.ID;
_video.dataset.type = msgObj.type;
// _video.dataset.videoUrl = msgObj.videoUrl;
_video.addEventListener('contextmenu', this.initContextmenuEvent.bind(this, msgObj.flow), false);
ele = _video;
}else if(msgObj.type == allowType["file"]){
var _div = document.createElement('div');
_div.className = 'J_fileElem';
if(!msgObj.loading){
_div.title = '单击下载';
_div.addEventListener('click', this.downloadFile.bind(this, msgObj.fileUrl, msgObj.fileName),false);
_div.dataset.id = msgObj.ID;
_div.dataset.type = msgObj.type;
// _div.dataset.fileUrl = msgObj.fileUrl;
// _div.dataset.fileName = msgObj.fileName;
_div.addEventListener('contextmenu', this.initContextmenuEvent.bind(this, msgObj.flow), false);
}
var _img = document.createElement('img');
_img.src = timToolsModule.fileCover(msgObj.fileUrl, msgObj.fileName, this.baseHead_url);
_img.height = '45';
_img.width = '45';
_div.appendChild(_img);
var _divText = document.createElement('div');
_divText.className = 'J_fileElem_Text';
var _span = document.createElement('span');
_span.innerHTML = msgObj.fileName;
_divText.appendChild(_span);
var _spanSize = document.createElement('span');
_spanSize.innerHTML = timToolsModule.getFileSize(msgObj.fileSize);
_divText.appendChild(_spanSize);
_div.appendChild(_divText);
ele = _div;
}
return ele;
}
// text: 'AAA[龇牙]AAA[龇牙]AAA[龇牙AAA]'
TimComponent.prototype.decodeText = function(msgText, d) {
// 文本消息
let temp = msgText;
let left = -1;
let right = -1;
while (temp !== '') {
left = temp.indexOf('[');
right = temp.indexOf(']');
switch (left) {
case 0:
if (right === -1) {
let _span = document.createElement('span');
_span.innerHTML = temp;
d.appendChild(_span);
temp = ''
} else {
let _emoji = temp.slice(0, right + 1)
if (timToolsModule.isEmoji(_emoji) != '') {
let _img = document.createElement('img');
_img.src = timToolsModule.isEmoji(_emoji);
_img.height = 20;
_img.width = 20;
d.appendChild(_img);
temp = temp.substring(right + 1);
} else {
let _span = document.createElement('span');
_span.innerHTML = '[';
d.appendChild(_span);
temp = temp.slice(1);
}
}
break;
case -1:
let _span = document.createElement('span');
_span.innerHTML = temp;
d.appendChild(_span);
temp = '';
break;
default:
let default_span = document.createElement('span');
default_span.innerHTML = temp.slice(0, left);
d.appendChild(default_span);
temp = temp.substring(left);
break;
}
}
}
// 下载文件 预览文件
TimComponent.prototype.downloadFile = function(fileUrl, fileName) {
// 浏览器支持fetch则用blob下载,避免浏览器点击a标签,跳转到新页面预览的行为
if (window.fetch) {
fetch(fileUrl)
.then(res => res.blob())
.then(blob => {
let a = document.createElement('a');
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
})
} else {
let a = document.createElement('a');
// a.href = 'https://view.officeapps.live.com/op/view.aspx?src=' + fileUrl;
a.href = fileUrl;
a.target = '_blank';
a.download = fileName;
a.click();
}
}
// 发送消息
TimComponent.prototype.sendTextMsg = function(val){
var _this = this;
const conversationID = this.J_inputMsg.dataset.conversationid;
let id;
let types;
if(conversationID.indexOf(c2cType) !== -1){
id = conversationID.replace(c2cType, '');
types = TIM.TYPES.CONV_C2C;
}else if(conversationID.indexOf(groupType) !== -1){
id = conversationID.replace(groupType, '');
types = TIM.TYPES.CONV_GROUP;
}
// 发送文本消息,Web 端与小程序端相同
// 1. 创建消息实例,接口返回的实例可以上屏
let message = this.tim.createTextMessage({
to: id,
conversationType: types,
// 消息优先级,用于群聊(v2.4.2起支持)。如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
// 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
// priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
payload: {
text: val
},
// 消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到,v2.10.2起支持)
// cloudCustomData: 'your cloud custom data'
});
// 2. 发送消息
let promise = this.tim.sendMessage(message);
promise.then(function(imResponse) {
// 发送成功 渲染页面 渲染到 消息列表的右边
console.log(imResponse);
_this.updateCurrentMsgList(imResponse.data.message);
}).catch(function(imError) {
// 发送失败
console.warn('sendMessage error:', imError);
});
}
// 设置消息已读
TimComponent.prototype.sendMsgRead = function(conversationID){
var _this = this;
// 将某会话下所有未读消息已读上报
let promise = this.tim.setMessageRead({conversationID: conversationID});
promise.then(function(imResponse) {
console.log('sendMsgRead',imResponse)
// 已读上报成功,指定 ID 的会话的 unreadCount 属性值被置为0
_this.unreadListener && _this.getAllUnreadCount();
}).catch(function(imError) {
// 已读上报失败
console.warn('setMessageRead error:', imError);
});
}
TimComponent.prototype.getAllUnreadCount = function(){
var _this = this;
let getConversationListPromise = this.tim.getConversationList();
getConversationListPromise.then(function(imResponse) {
const conversationList = imResponse.data.conversationList; // 会话列表,用该列表覆盖原有的会话列表
let unreadCount = 0;
conversationList.forEach(item => {
unreadCount += item.unreadCount;
});
_this.unreadListener && unreadCount >= 0 && _this.unreadListener(unreadCount);
}).catch(function(imError) {
console.warn('getConversationList error:', imError); // 获取会话列表失败的相关信息
});
}
// 绑定 element事件
TimComponent.prototype.bindEleEvent = function(){
this.J_timRTop_reduce.addEventListener('click', this.reduceClick.bind(this), false);
this.J_timLeft_switch.addEventListener('click', this.logoutClick.bind(this), false);
this.J_inputMsg.addEventListener('keypress', this.bindInputkeypress.bind(this), false);
this.icon_happy.addEventListener('click', this.emojiClick.bind(this), false);
this.J_timRBottom_image.addEventListener('click',this.handleSendImageClick.bind(this), false);
this.J_imagePicker.addEventListener('change', this.sendImage.bind(this), false);
// this.J_timRBottom_file.addEventListener('click',this.handleSendVideoClick.bind(this), false);
this.J_videoPicker.addEventListener('change', this.sendVideo.bind(this), false);
this.J_timRBottom_file.addEventListener('click',this.handleSendFileClick.bind(this), false);
this.J_filePicker.addEventListener('change', this.sendFile.bind(this), false);
this.J_timSend.addEventListener('click', this.sendTextClick.bind(this), false);
this.J_timRMiddle.addEventListener("scroll", this.msgMiddleOnScroll.bind(this), false);
this.J_timReturn_newMsg.addEventListener('click', this.msgMiddleLastItem.bind(this), false);
// 缩小图片
this.J_timAmplify.addEventListener('click', this.hideAmplifyClick.bind(this), false);
// this.J_timAmplify_img.addEventListener('click', this.hideAmplifyClick.bind(this), false);
// 绑定右键的几个事件
this.copyEle.addEventListener('click', this.copyMsgClick.bind(this), false);
this.downloadEle.addEventListener('click', this.downloadFileClick.bind(this), false);
this.recallEle.addEventListener('click', this.recallClick.bind(this), false);
this.forwardEle.addEventListener('click', this.forwardClick.bind(this), false)
// 绑定转发的事件
this.J_timForward_btn_close.addEventListener('click', this.closeForwardClick.bind(this), false);
this.J_timForward_btn_forward.addEventListener('click', this.submitForwardClick.bind(this), false);
}
// 缩小对话框 点击事件
TimComponent.prototype.reduceClick = function(e){
var winWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var winHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// this.J_timContainer.style.right = '-430px';
// this.J_timContainer.style.transition= 'right 1s linear';
this.J_timContainer.style.left = (winWidth - 70) + 'px';
// this.J_timContainer.style.transition= 'left 1s linear';
this.J_timRight.style.opacity = 0;
this.J_timRight.style.transition = 'opacity 1s linear';
}
// SDK 登出
TimComponent.prototype.logoutClick = function(e){
var _this = this;
var e = e || window.event;
e.stopPropagation();
let promise = this.tim.logout();
promise.then(function(imResponse) {
_this.J_timContainer.innerHTML = '';
_this.handleLogout('登出成功');
console.log('登出成功');
localStorage.removeItem('$NTALK_IMSDK');
_this.isLogin = false;
// _this.destroyBindTimEvent();
}).catch(function(imError) {
console.warn('logout error:', imError);
});
}
// 登出操作
TimComponent.prototype.handleLogout = function(tipsInfo){
this.J_timLeft_portrait.innerHTML = '';
this.J_timRMiddle.innerHTML = '';
this.J_timContainer.style.display = 'none';
this.tipsShow(tipsInfo);
}
// 表情 列表显示隐藏事件
TimComponent.prototype.emojiClick = function(e){
var e = e || window.event;
e.stopPropagation();
var _display = this.emojis.style.display;
this.emojis.style.display = _display == 'flex' ? 'none' : 'flex';
}
// 提示消息展示
TimComponent.prototype.tipsShow = function(tipsInfo){
var _this = this;
this.J_timTips.style.display = 'flex';
this.J_timTips_span.innerHTML = tipsInfo;
setTimeout(function(){
_this.J_timTips.style.display = 'none';
_this.J_timTips_span.innerHTML = '';
}, 2000)
}
// 表情 列表隐藏
TimComponent.prototype.emojiHidden = function(){
this.emojis.style.display = 'none';
}
// 操作发送 图片点击事件
TimComponent.prototype.handleSendImageClick = function(){
this.J_imagePicker.click();
}
// 发送图片 SDK 具体操作
TimComponent.prototype.sendImage = function(e){
var e = e || window.event;
e.stopPropagation();
var _this = this;
let id;
let types;
if(currentSelectConversation.indexOf(c2cType) !== -1){
id = currentSelectConversation.replace(c2cType, '');
types = TIM.TYPES.CONV_C2C;
}else if(currentSelectConversation.indexOf(groupType) !== -1){
id = currentSelectConversation.replace(groupType, '');
types = TIM.TYPES.CONV_GROUP;
}
// Web 端发送图片消息示例1 - 传入 DOM 节点
// 1. 创建消息实例,接口返回的实例可以上屏
const message = this.tim.createImageMessage({
to: id,
conversationType: types,
payload: {
file: this.J_imagePicker
},
onProgress: function(event) {
console.log('file uploading:', event);
}
})
_this.sendMsgShowLoading('');
// 2. 发送消息
let promise = this.tim.sendMessage(message);
promise.then(function(imResponse) {
// 发送成功
console.log(imResponse);
_this.J_imagePicker.value = '';
_this.updateCurrentMsgList(imResponse.data.message);
}).catch(function(imError) {
// 发送失败
console.warn('sendMessage error:', imError);
});
}
// 操作发送 视频点击事件
TimComponent.prototype.handleSendVideoClick = function(){
this.J_videoPicker.click();
}
// 发送视频 SDK 具体操作
TimComponent.prototype.sendVideo = function(e){
var e = e || window.event;
e.stopPropagation();
var _this = this;
let id;
let types;
if(currentSelectConversation.indexOf(c2cType) !== -1){
id = currentSelectConversation.replace(c2cType, '');
types = TIM.TYPES.CONV_C2C;
}else if(currentSelectConversation.indexOf(groupType) !== -1){
id = currentSelectConversation.replace(groupType, '');
types = TIM.TYPES.CONV_GROUP;
}
// web 端发送视频消息示例(v2.6.0起支持):
// 1. 获取视频:传入 DOM 节点
// 2. 创建消息实例
const message = this.tim.createVideoMessage({
to: id,
conversationType: types,
payload: {
file: this.J_videoPicker
},
onProgress: function(event) {
console.log('file uploading:', event);
}
})
this.sendMsgShowLoading('');
// 2. 发送消息
let promise = this.tim.sendMessage(message);
promise.then(function(imResponse) {
// 发送成功
console.log(imResponse);
_this.J_videoPicker.value = '';
_this.updateCurrentMsgList(imResponse.data.message);
}).catch(function(imError) {
// 发送失败
console.warn('sendMessage error:', imError);
});
}
// 操作发送 文件点击事件
TimComponent.prototype.handleSendFileClick = function(){
this.J_filePicker.click();
}
// 发送文件 SDK 具体操作
TimComponent.prototype.sendFile = function(e){
var e = e || window.event;
e.stopPropagation();
let _fileSize = this.J_filePicker?.files[0].size;
if(Number(_fileSize) / 1024 / 1024 >= 100){
this.tipsShow('文件大小超过100M,无法发送')
this.J_filePicker.value = '';
return
}
var _this = this;
let id;
let types;
if(currentSelectConversation.indexOf(c2cType) !== -1){
id = currentSelectConversation.replace(c2cType, '');
types = TIM.TYPES.CONV_C2C;
}else if(currentSelectConversation.indexOf(groupType) !== -1){
id = currentSelectConversation.replace(groupType, '');
types = TIM.TYPES.CONV_GROUP;
}
// Web 端发送文件消息示例1 - 传入 DOM 节点
// 1. 创建文件消息实例,接口返回的实例可以上屏
const message = this.tim.createFileMessage({
to: id,
conversationType: types,
payload: {
file: _this.J_filePicker
},
onProgress: function(event) {
console.log('file uploading:', event);
}
})
this.sendMsgShowLoading('', allowType['file']);
// 2. 发送消息
let promise = this.tim.sendMessage(message);
promise.then(function(imResponse) {
// 发送成功
console.log(imResponse);
_this.J_filePicker.value = '';
_this.updateCurrentMsgList(imResponse.data.message);
}).catch(function(imError) {
// 发送失败
console.warn('sendMessage error:', imError);
});
}
// 发送消息后,填充一条loading消息
TimComponent.prototype.sendMsgShowLoading = function(showText, _type){
// this.renderMsgMiddleItem({
// flag: true,
// time: timToolsModule.getTime(new Date())
// });
if(_type == allowType['file']){
var fileLocal = this.J_filePicker.value;
var name = fileLocal.substring(fileLocal.lastIndexOf("\\")+1);
this.renderMsgRightItem({
item: {
type: allowType['file'],
fileName: name,
fileSize: "",
fileUrl: fileLocal,
loading: true,
flow:'out',
},
htmlVal: "",
img: curLoginPortrait,
loading: true
});
}else{
this.renderMsgRightItem({
item: {
type: allowType['text'],
text: showText
},
htmlVal: showText,
img: curLoginPortrait,
loading: true
});
}
this.msgMiddleLastItem();
}
// 绑定input输入框 回车发送消息
TimComponent.prototype.bindInputkeypress = function(){
var e = e || window.event;
if (e.keyCode == 13){ //回车按钮事件
this.sendTextClick();
}
}
TimComponent.prototype.sendTextClick = function(){
var inputMsg = timToolsModule.tirm(this.J_inputMsg.value);
if(inputMsg == ''){
this.tipsShow('请输入消息')
return
}else if(inputMsg.length > 500){
this.tipsShow('最多输入500个字,请重新输入')
return
}
this.sendTextMsg(inputMsg);
this.sendMsgShowLoading(inputMsg);
this.J_inputMsg.value = '';
this.emojiHidden();
}
TimComponent.prototype.msgMiddleOnScroll = function(e){
var e = e || window.event,
target = e.currentTarget;
if ( this.J_timRMiddle.scrollHeight - this.J_timRMiddle.clientHeight - target.scrollTop < 20 ){
this.J_timReturn_newMsg.style.display = 'none';
}
// if ( this.J_timRMiddle.scrollHeight - target.scrollTop > this.J_timRMiddle.clientHeight * 2 ){
// this.J_timReturn_newMsg.style.display = 'block';
// }
}
// 自动到 滚动区域 第一条数据
TimComponent.prototype.msgMiddleFirstItem = function(){
// 每次消息列表都显示在 滚动条 最后的位置上
this.J_timRMiddle.scrollTop = 0;
}
// 自动到 滚动区域 最后一条数据
TimComponent.prototype.msgMiddleLastItem = function(){
// 每次消息列表都显示在 滚动条 最后的位置
this.J_timRMiddle.scrollTop = this.J_timRMiddle.scrollHeight;
this.J_timReturn_newMsg.style.display = 'none';
}
TimComponent.prototype.switchReturnElement = function(){
var _display = this.J_timReturn_newMsg.style.display;
this.J_timReturn_newMsg.style.display = 'block';
}
// 判断 J_timContainer 容器 是否是最大的状态,不是则把 J_timContainer 容器放大至最初状态
TimComponent.prototype.isMaxContainer = function(){
// 点击左边item 判断对话框的状态
if(this.J_timRight.style.opacity != 1){
var winWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var winHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// this.J_timContainer.style.right = '10px';
// this.J_timContainer.style.transition= 'right 1s linear';
//获取J_timContainer x坐标
var rec = this.J_timContainer.getBoundingClientRect();
var x = rec.x;
var conWidth = this.J_timContainer.offsetWidth;
var leftWid = x < (winWidth - conWidth - 10 ) ? x : (winWidth - conWidth - 10);
this.J_timContainer.style.left = leftWid + 'px';
// this.J_timContainer.style.transition= 'left 1s linear';
this.J_timRight.style.opacity = 1;
this.J_timRight.style.transition = 'opacity 1s linear';
}
}
TimComponent.prototype.handleTimPosition = function(positionState){
this.J_timContainer.style.width = '500px';
this.J_timContainer.style.height = '500px';
var winWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var winHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
var conWidth = this.J_timContainer.offsetWidth;
var conHeight = this.J_timContainer.offsetHeight;
switch(positionState){
case 1:
this.J_timContainer.style.left = (winWidth - conWidth) * .5 + 'px';
this.J_timContainer.style.top = (winHeight - conHeight) * .5 + 'px';
break;
case 2:
this.J_timContainer.style.left = '0px';
this.J_timContainer.style.top = '0px';
break;
case 3:
this.J_timContainer.style.left = '0px';
this.J_timContainer.style.top = (winHeight - conHeight) - 10 + 'px';
break;
case 4:
this.J_timContainer.style.left = (winWidth - conWidth) - 10 + 'px';
this.J_timContainer.style.top = '0px';
break;
case 5:
this.J_timContainer.style.left = (winWidth - conWidth) - 10 + 'px';
this.J_timContainer.style.top = (winHeight - conHeight) - 10 + 'px';
break;
case 6:
this.J_timContainer.style.left = (winWidth - conWidth) - 10 + 'px';
this.J_timContainer.style.top = (winHeight - conHeight) - 10 + 'px';
this.reduceClick();
break;
default:
this.J_timContainer.style.left = (winWidth - conWidth) - 10 + 'px';
this.J_timContainer.style.top = (winHeight - conHeight) - 10 + 'px';
break;
}
}
// 渲染表情 列表
TimComponent.prototype.renderEmojiList = function(){
var _this = this;
var emojiList = initEmoji.emojiName;
var d = document.createDocumentFragment();
emojiList.forEach(item => {
var _div = document.createElement('div');
_div.className = 'emoji';
_div.dataset.value = item;
_div.addEventListener('click', _this.chooseEmoji.bind(_this), false);
var _img = document.createElement('img');
_img.src = initEmoji.emojiUrl + initEmoji.emojiMap[item];
_div.appendChild(_img);
d.appendChild(_div);
})
this.emojis.appendChild(d);
}
// 选中 表情
TimComponent.prototype.chooseEmoji = function(e){
var e = e || window.event,
target = e.currentTarget;
this.emojis.style.display = 'none';
var inputMsg = timToolsModule.tirm(this.J_inputMsg.value);
this.J_inputMsg.value = inputMsg != '' ? inputMsg + target.dataset.value : target.dataset.value;
}
// ntalk 登录
TimComponent.prototype.ntalkLogin = function(){
var uuid = timToolsModule.guid();
let _this = this;
axios({
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
token: '',
deviceType: '3',
deviceId: uuid
},
method: 'get',
url: 'https://tntalk.morewiscloud.com/gateway/rest/v1/chat/morewisCloud/login',
params: {
mobile: _this.userId,
password: 123456,
_deviceId: uuid
}
}).then(function (response) {
if (response.status === 200) {
console.log(response.data.data);
_this.userSig = response.data.data.userSig;
console.log('_this.userSig', _this.userSig)
_this.init();
}
}).catch(function (error) {
console.log(error)
})
}
// 初始化 J_timContainer 拖拽事件
TimComponent.prototype.initMousedown = function () {
var _this = this;
var oDiv = document.getElementById('J_timContainer');;
// oDiv.style.width = '500px';
var aSpan = oDiv.getElementsByTagName('span');
// 遍历为每一个span添加上drage事件
var spanList = ['.br', '.bl', '.tr', '.tl']
for (var i = 0; i < spanList.length; i++) {
dragFn(oDiv.querySelector(spanList[i]));
}
function dragFn(obj) {
// 按下鼠标的操作
obj.onmousedown = function (ev) {
var oEv = ev || event;
// 阻止事件的冒泡
oEv.stopPropagation();
// 获取移动前盒子的宽高,边角的鼠标坐标,和距离浏览器边界的距离
var oldWidth = oDiv.offsetWidth;
var oldHeight = oDiv.offsetHeight;
var oldX = oEv.clientX;
var oldY = oEv.clientY;
var oldLeft = oDiv.offsetLeft;
var oldTop = oDiv.offsetTop;
// 鼠标移动事件
document.onmousemove = function (ev) {
var oEv = ev || event;
// t top l left r right b bottom, 依次 tl 上左角
if (obj.className == 'tl') {
_this.isMaxContainer();
if(oldWidth - (oEv.clientX - oldX) > 1000
|| oldWidth - (oEv.clientX - oldX) < 500
|| oldHeight - (oEv.clientY - oldY) > 800
|| oldHeight - (oEv.clientY - oldY) < 500
){
return
}
// 代表的横向移动的距离,右为正,左为负
// 计算移动后盒子的宽 = 移动前盒子的宽度 - (移动后的横向坐标-移动前的横向坐标)
oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
// 高度同理
oDiv.style.height= oldHeight - (oEv.clientY - oldY) + 'px';
// 同理计算修改盒子的定位,这里很多人就不理解了,我明明动的角,为嘛不是修改span
// 我给你捋一捋,首先角和边是相对于父元素定位的,父元素也是一个绝对定位,这个时候
//我动态修改父元素的定位,父元素的位置就好跟着改变,那么子元素是相对父元素定位的,
// 那么在父元素最左边,不还是在最左边,这样就简单的实现了让所有定位元素跟着动
oDiv.style.left = oldLeft + (oEv.clientX - oldX) + 'px';
oDiv.style.top = oldTop + (oEv.clientY - oldY) + 'px';
}
else if (obj.className == 'bl') {
_this.isMaxContainer();
if(oldWidth - (oEv.clientX - oldX) > 1000
|| oldWidth - (oEv.clientX - oldX) < 500
|| oldHeight + (oEv.clientY - oldY) > 800
|| oldHeight + (oEv.clientY - oldY) < 500
){
return
}
oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
oDiv.style.height= oldHeight + (oEv.clientY - oldY) + 'px';
oDiv.style.left = oldLeft + (oEv.clientX - oldX) + 'px';
oDiv.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
}
else if (obj.className == 'tr') {
if(oldWidth + (oEv.clientX - oldX) > 1000
|| oldWidth + (oEv.clientX - oldX) < 500
|| oldHeight - (oEv.clientY - oldY) > 800
|| oldHeight - (oEv.clientY - oldY) < 500
){
return
}
oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
oDiv.style.height = oldHeight - (oEv.clientY - oldY)+'px';
oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
oDiv.style.top = oldTop + (oEv.clientY - oldY) + 'px';
}
else if (obj.className == 'br') {
if(oldWidth + (oEv.clientX - oldX) > 1000
|| oldWidth + (oEv.clientX - oldX) < 500
|| oldHeight + (oEv.clientY - oldY) > 800
|| oldHeight + (oEv.clientY - oldY) < 500
){
return
}
oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
oDiv.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
}
else if (obj.className == 't') {
oDiv.style.height= oldHeight-(oEv.clientY - oldY) + 'px';
oDiv.style.top = oldTop + (oEv.clientY - oldY) + 'px';
}
else if (obj.className == 'b') {
oDiv.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
oDiv.style.bottom = oldTop - (oEv.clientY + oldY) + 'px';
}
else if (obj.className == 'l') {
oDiv.style.height = oldHeight + 'px';
oDiv.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
oDiv.style.left = oldLeft + (oEv.clientX - oldX) + 'px';
}
else if (obj.className == 'r') {
oDiv.style.height = oldHeight + 'px';
oDiv.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
oDiv.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
}
// 边界判断
boundary()
};
// 松开鼠标时,移除移动的监听
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
};
// 阻止默认事件
return false;
};
}
var x = 0;
var y = 0;
var l = 0;
var t = 0;
var isDown = false;
var isUserSelect = false;
//鼠标按下事件
oDiv.onmousedown = function(e) {
var e = e || window.event;
target = e.target || e.srcElement;
if(target.className != 'J_timLeft' && target.className != 'J_timLeft_portrait' && target.className != 'J_timRTop' && target.className != 'J_timRBottom'){
isUserSelect = false;
return
}else{
isUserSelect = true;
}
// _this.J_timMsg_moreHandle.style.display = 'none';
//获取x坐标和y坐标
x = e.clientX;
y = e.clientY;
//获取左部和顶部的偏移量
l = oDiv.offsetLeft;
t = oDiv.offsetTop;
//开关打开
isDown = true;
//设置样式
oDiv.style.cursor = 'move';
}
//鼠标移动
window.onmousemove = function(e) {
var e = e || window.event;
target = e.target || e.srcElement;
if(isUserSelect){
e.preventDefault();
}
if (isDown == false) {
return;
}
//获取x和y
var nx = e.clientX;
var ny = e.clientY;
//计算移动后的左偏移量和顶部的偏移量
var nl = nx - (x - l);
var nt = ny - (y - t);
oDiv.style.left = nl + 'px';
oDiv.style.top = nt + 'px';
}
//鼠标抬起事件
oDiv.onmouseup = function() {
//开关关闭
isDown = false;
oDiv.style.cursor = 'default';
}
// 鼠标按下事件
oDiv.onclick = function(e) {
_this.J_timMsg_moreHandle.style.display = 'none';
}
// 边界判断事件
function boundary(){
let oDivWidth = oDiv.offsetWidth;
let oDivHeight = oDiv.offsetHeight;
let oDivLeft = oDiv.offsetLeft;
let oDivTop = oDiv.offsetTop;
// let bodyWidth = document.body.clientWidth
// let bodyHeight = document.body.clientHeight
let bodyWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
let bodyHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// 左边界
if(oDivLeft<=0){
oDiv.style.left = 0+'px'
}
// 右边界 多减5个像素减去的是防止滚动条会造成抖动
if((oDivLeft+oDivWidth)>=(bodyWidth-5)){
oDiv.style.left = bodyWidth - oDivWidth-5+ 'px'
}
//上边界
if(oDivTop<=0){
oDiv.style.top = 0+'px'
}
// 下边界 多减5个像素减去的是防止滚动条会造成抖动
if(oDivTop+oDivHeight>=bodyHeight-5){
oDiv.style.top = bodyHeight - oDivHeight-5 + 'px'
}
}
};
// 放大图片
TimComponent.prototype.amplifyImgEvent = function(e){
var e = e || window.event,
target = e.currentTarget;
e.preventDefault();
var imageUrl = target.dataset.imageUrl;
this.J_timAmplify_img.src = imageUrl;
this.J_timAmplify.style.display = 'flex';
}
// 隐藏放大图片区域
TimComponent.prototype.hideAmplifyClick = function(e){
var e = e || window.event;
e.preventDefault();
e.stopPropagation();
this.J_timAmplify.style.display = 'none';
}
// 添加右键 点击事件
TimComponent.prototype.initContextmenuEvent = function(flow, e){
var e = e || window.event,
target = e.currentTarget;
e.preventDefault();
e.stopPropagation();
this.copyEle.style.display = 'block';
this.recallEle.style.display = 'block';
this.downloadEle.style.display = 'block';
this.copyEle.dataset.id = target.dataset.id;
this.forwardEle.dataset.id = target.dataset.id;
this.recallEle.dataset.id = target.dataset.id;
this.downloadEle.dataset.id = target.dataset.id;
// this.downloadEle.dataset.type = target.dataset.type;
if(target.dataset.type == allowType["file"] || target.dataset.type == allowType["image"] || target.dataset.type == allowType["video"]){
this.copyEle.style.display = 'none';
}else if(target.dataset.type == allowType["text"]){
this.downloadEle.style.display = 'none';
this.copyEle.dataset.text = target.dataset.text;
}
if(flow != 'out'){
this.recallEle.style.display = 'none';
}
this.J_timMsg_moreHandle.style.left = e.clientX + 'px';
this.J_timMsg_moreHandle.style.top = e.clientY + 'px';
this.J_timMsg_moreHandle.style.display = 'block';
}
// 右键复制点击事件
TimComponent.prototype.copyMsgClick = function(e){
var e = e || window.event,
target = e.currentTarget;
// e.preventDefault();
e.stopPropagation();
var ID = target.dataset.id;
var message = this.currentMsgData.find( item => {
return item.ID == ID;
})
var copyMsg = message.payload.text;
if( copyMsg && copyMsg != ''){
var input = document.createElement('input');
input.setAttribute('readonly', 'readonly');
input.setAttribute('value', copyMsg);
document.body.appendChild(input);
input.select();
input.setSelectionRange(0, 9999);
document.execCommand('Copy');
this.tipsShow('消息复制成功');
document.body.removeChild(input);
this.J_timMsg_moreHandle.style.display = 'none';
}
}
// 右键下载点击事件
TimComponent.prototype.downloadFileClick = function(e){
var e = e || window.event,
target = e.currentTarget;
// e.preventDefault();
e.stopPropagation();
var ID = target.dataset.id;
var message = this.currentMsgData.find( item => {
return item.ID == ID;
})
var fileUrl;
var fileName;
if(message.type == allowType['image']){
fileUrl = message.payload.imageInfoArray[0].imageUrl;
fileName = 'image_' + new Date().getTime();
}else if(message.type == allowType['file']){
fileUrl = message.payload.fileUrl;
fileName = message.payload.fileName;
}else if(message.type == allowType['video']){
fileUrl = message.payload.videoUrl;
fileName = 'video_' + new Date().getTime();
}
if( fileUrl && fileUrl != ''){
this.downloadFile(fileUrl,fileName);
this.J_timMsg_moreHandle.style.display = 'none';
}
}
// 右键撤回点击事件
TimComponent.prototype.recallClick = function(e){
var e = e || window.event,
target = e.currentTarget;
// e.preventDefault();
e.stopPropagation();
var ID = target.dataset.id;
var message = this.currentMsgData.find( item => {
return item.ID == ID;
})
this.revokeMessage(message);
this.J_timMsg_moreHandle.style.display = 'none';
}
// tim撤回
TimComponent.prototype.revokeMessage = function(message){
var _this = this;
// 主动撤回消息
let promise = this.tim.revokeMessage(message);
promise.then(function(imResponse) {
// 消息撤回成功
// console.log(imResponse.data.message)
_this.updateRevokedMsgList(imResponse.data.message);
_this.tipsShow('撤回成功');
}).catch(function(imError) {
// 消息撤回失败
// console.warn('revokeMessage error:', imError);
_this.tipsShow('撤回失败:消息发送已超过2分钟撤回消息失败,时间已超过2分钟!');
});
}
TimComponent.prototype.forwardClick = function(){
var e = e || window.event,
target = e.currentTarget;
// e.preventDefault();
e.stopPropagation();
this.J_timForward_btn_forward.dataset.id = target.dataset.id;
this.createForwardList();
}
// 创建转发列表
TimComponent.prototype.createForwardList = function(){
var _this = this;
// 先清空数据
this.J_timForward_list.innerHTML = '';
var d = document.createDocumentFragment();
let _newC2C = this.privateChatId;
let newC2CIndex = -1;
if(_newC2C && _newC2C !== ''){
newC2CIndex = _this.conversationListData.findIndex(item => {
return item.conversationID == c2cType + _newC2C;
})
if(newC2CIndex === -1){
_this.createForwardItem({
conversationID: c2cType + _newC2C,
img: _this.privateChatOpt.avatar,
htmlVal: _this.privateChatOpt.nick
}, d);
}
}
_this.conversationListData.forEach(item => {
_this.createForwardItem({
conversationID: item.conversationID,
img: timToolsModule.getAvatarImg(item),
htmlVal: timToolsModule.getProfileName(item)
}, d);
})
this.J_timForward_list.appendChild(d);
this.J_timForward_layer.style.display = 'flex';
this.J_timMsg_moreHandle.style.display = 'none';
}
// 创建转发 item
TimComponent.prototype.createForwardItem = function(opt, d){
var _div = document.createElement('div');
_div.className = 'J_timForward_item';
// _div.addEventListener('click', this.checkboxCilck.bind(this), false);
var _input = document.createElement('input');
_input.type = 'checkbox';
_input.name = 'timChechbox';
_input.value = opt.conversationID;
_div.appendChild(_input);
var checkbox_text = document.createElement('div');
checkbox_text.className = 'content_div';
var _img = document.createElement('img');
_img.src = opt.img;
_img.alt = '';
timToolsModule.onerrorFN(_img);
checkbox_text.appendChild(_img);
var _span = document.createElement('span');
_span.innerHTML = opt.htmlVal
checkbox_text.appendChild(_span);
checkbox_text.addEventListener('click', this.checkboxCilck.bind(this), false);
_div.appendChild(checkbox_text);
d.appendChild(_div);
}
TimComponent.prototype.checkboxCilck = function(e){
var e = e || window.event,
target = e.currentTarget;
e.stopPropagation();
target.parentNode.children.timChechbox.checked = !target.parentNode.children.timChechbox.checked;
}
// 渲染转发 Item
// tim 取消转发
TimComponent.prototype.closeForwardClick = function(){
this.J_timForward_layer.style.display = 'none';
}
// tim 转发
TimComponent.prototype.submitForwardClick = function(e){
var e = e || window.event,
target = e.currentTarget;
// e.preventDefault();
e.stopPropagation();
var ID = target.dataset.id;
var _this = this;
var obj = document.getElementsByName('timChechbox');
var check_val = [];
obj.forEach(item => {
if(item.checked){
check_val.push(item.value);
}
})
if(check_val.length <= 0){
this.tipsShow('请选择转发对象');
}else{
this.showLoading();
check_val.forEach( (item, index) => {
_this.forwardMsg(item, ID, index == check_val.length - 1);
})
this.J_timForward_layer.style.display = 'none';
}
}
// 开始转发
TimComponent.prototype.forwardMsg = function(item, _id, _hideFlag){
var _this = this;
let id;
let types;
if(item.indexOf(c2cType) !== -1){
id = item.replace(c2cType, '');
types = TIM.TYPES.CONV_C2C;
}else if(item.indexOf(groupType) !== -1){
id = item.replace(groupType, '');
types = TIM.TYPES.CONV_GROUP;
}
var ID = _id;
var message = this.currentMsgData.find( item => {
return item.ID == ID;
})
let forwardMessage = this.tim.createForwardMessage({
to: id,
conversationType: types,
// 消息优先级,用于群聊,如果某个群的消息超过了频率限制,后台会优先下发高优先级的消息,详细请参考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
// 支持的枚举值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默认), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
// priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
payload: message, // 消息实例,已收到的或自己已发出的消息
// 消息自定义数据(云端保存,会发送到对端,程序卸载重装后还能拉取到,v2.10.2起支持)
// cloudCustomData: 'your cloud custom data'
});
if(item == currentSelectConversation){
this.sendMsgShowLoading('');
}
// 2. 发送消息
let promise = this.tim.sendMessage(forwardMessage);
promise.then(function(imResponse) {
// 发送成功
console.log(imResponse);
if(imResponse.data.message.conversationID == currentSelectConversation){
_this.updateCurrentMsgList(imResponse.data.message);
}else{
_this.tipsShow('转发成功!');
}
_hideFlag && _this.hideLoading();
}).catch(function(imError) {
// 发送失败
console.warn('sendMessage error:', imError);
_this.hideLoading();
});
}
// 显示loading
TimComponent.prototype.showLoading = function(){
this.J_timLoading.style.display = 'flex';
}
// 隐藏loading
TimComponent.prototype.hideLoading = function(){
this.J_timLoading.style.display = 'none';
}
window.TimComponent = TimComponent;
})(document, timToolsModule, initEmoji);
// 对外使用的模板,主要使用 getTimExample 方法获得唯一 TimComponent 实例
var initTimModule = (function(){
var timComponent;
function singleTim(opt){
if (timComponent == undefined){
timComponent = new TimComponent({
SDKAppID: opt.SDKAppID,
userId: opt.userId,
userSig: opt.userSig,
privateChatId: opt.privateChatId,
privateChatName: opt.privateChatName,
baseHead_url: opt.baseHead_url,
unreadListener: opt.unreadListener,
unreadChangeListener: opt.unreadChangeListener,
})
}
if(!timComponent.isLogin){
timComponent.handleLogin(opt);
}else{
timComponent.updateOpt(opt);
}
}
function getTimExample(opt){
singleTim(opt);
}
function logoutTim(){
if (timComponent != undefined){
if(timComponent.isLogin){
timComponent.logoutClick();
}
}
}
return {
getTimExample: getTimExample,
logoutTim: logoutTim,
}
})();