feat: email subscribe

feat: content copy
feat: localnetroom perf
feat: user table add flag field
feat: language perf
feat: token api resopnse perf
feat: icon perf
feat: doc update
This commit is contained in:
https://blog.iamtsm.cn
2023-11-04 12:49:32 +08:00
parent 653a987bdd
commit b4f79d4da8
48 changed files with 1126 additions and 356 deletions

View File

@@ -0,0 +1 @@
# 待完善补充...

View File

@@ -40,6 +40,10 @@ chatgpt聊天框的对话上下文的简单处理。
开启设置后,你创建的房间,同一个局域网用户进入网页后将看到你创建的房间。 开启设置后,你创建的房间,同一个局域网用户进入网页后将看到你创建的房间。
### 系统通知 (开发中) 【此设置刷新网页后有效,长久保存】
开启设置后,当收到消息或者提示时,会使用浏览器自带的桌面消息提示,进行及时的音效,横幅提示
### 文件分片传输大小 【此开关刷新网页后失效,需重新设置】 ### 文件分片传输大小 【此开关刷新网页后失效,需重新设置】
由于网站的文件传输是分片传输但是由于webrtc的数据传输通道有限制所以项目提供了一个合理范围的可选项用于自定义控制每次webrtc的数据通道发送数据时的分片大小。默认是 16KB最大可调整到64KB不同浏览器实现可能不同1664是我认为比较合适的可选范围 由于网站的文件传输是分片传输但是由于webrtc的数据传输通道有限制所以项目提供了一个合理范围的可选项用于自定义控制每次webrtc的数据通道发送数据时的分片大小。默认是 16KB最大可调整到64KB不同浏览器实现可能不同1664是我认为比较合适的可选范围

View File

@@ -22,50 +22,150 @@
* [配置简要说明](ENV_SETTING.md) * [配置简要说明](ENV_SETTING.md)
* [主要功能](FEATURE_LIST.md)
* [发送文字](FEATURE_LIST.md)
* [公共聊天](FEATURE_LIST.md)
* [群聊](FEATURE_LIST.md)
* [私聊](FEATURE_LIST.md)
* [文字复制](FEATURE_LIST.md)
* [富文本](FEATURE_LIST.md)
* [图片](FEATURE_LIST.md)
* [表情](FEATURE_LIST.md)
* [发送文件](FEATURE_LIST.md)
* [群发](FEATURE_LIST.md)
* [私发](FEATURE_LIST.md)
* [排队发](FEATURE_LIST.md)
* [同时发](FEATURE_LIST.md)
* [多文件拖拽](FEATURE_LIST.md)
* [indexedDb存储](FEATURE_LIST.md)
* [在线文件预览](FEATURE_LIST.md)
* [文件暂存](FEATURE_LIST.md)
* [自定义文件分片大小](FEATURE_LIST.md)
* [自定义文件预览大小](FEATURE_LIST.md)
* [屏幕共享](FEATURE_LIST.md)
* [多人共享](FEATURE_LIST.md)
* [屏幕开关](FEATURE_LIST.md)
* [音频开关](FEATURE_LIST.md)
* [视频通话](FEATURE_LIST.md)
* [多人视频](FEATURE_LIST.md)
* [视频开关](FEATURE_LIST.md)
* [摄像头切换](FEATURE_LIST.md)
* [音频开关](FEATURE_LIST.md)
* [开始直播](FEATURE_LIST.md)
* [视频直播](FEATURE_LIST.md)
* [屏幕直播](FEATURE_LIST.md)
* [视频开关](FEATURE_LIST.md)
* [摄像头切换](FEATURE_LIST.md)
* [音频开关](FEATURE_LIST.md)
* [开播端](FEATURE_LIST.md)
* [观众端](FEATURE_LIST.md)
* [语音连麦](FEATURE_LIST.md)
* [音频开关](FEATURE_LIST.md)
* [取件号码](FEATURE_LIST.md)
* [文件下载](FEATURE_LIST.md)
* [远程画笔](FEATURE_LIST.md)
* [多人画笔同步](FEATURE_LIST.md)
* [密码房间](FEATURE_LIST.md)
* [自定义密码](FEATURE_LIST.md)
* [屏幕录制](FEATURE_LIST.md)
* [录制文件下载](FEATURE_LIST.md)
* [chatGPT](FEATURE_LIST.md)
* [次要功能](FEATURE_LIST.md)
* [多语言版本](FEATURE_LIST.md)
* [微信扫码登录](FEATURE_LIST.md)
* [分享房间](FEATURE_LIST.md)
* [网站通知](FEATURE_LIST.md)
* [日志记录](FEATURE_LIST.md)
* [自定义日志数量限制](FEATURE_LIST.md)
* [中继设置](FEATURE_LIST.md)
* [自定义昵称](FEATURE_LIST.md)
* [在线人数统计](FEATURE_LIST.md)
* [消息红点开关](FEATURE_LIST.md)
* [固定房间号](FEATURE_LIST.md)
* [局域网房间扫描](FEATURE_LIST.md)
* [自定义socket地址](FEATURE_LIST.md)
* [后台管理统计](FEATURE_LIST.md)
* [后台开关设置](FEATURE_LIST.md)
* [敏感词过滤](FEATURE_LIST.md)
* [心跳检测](FEATURE_LIST.md)
* [webrtc连接展示](FEATURE_LIST.md)
* [tl-rtc-file-开发手册](README_DEV.md) * [tl-rtc-file-开发手册](README_DEV.md)
* [设计简介](dev/INTRO.md) * [设计简介](dev/INTRO.md)
* [客户端](dev/client/CLIENT.md) * [客户端](dev/CLIENT.md)
* [文字聊天](dev/client/CHAT.md)
* [文件传输](dev/client/FILE.md)
* [多人音视频](dev/client/VIDEO.md)
* [多人屏幕共享](dev/client/SCREEN.md)
* [单人直播](dev/client/LIVE.md)
* [多人语音](dev/client/AUDIO.md)
* [文件暂存/取件码](dev/client/FILE_CODE.md)
* [多人画笔](dev/client/DRAW.md)
* [屏幕录制](dev/client/RECODE.md)
* [服务端](dev/SVR.md) * [服务端](dev/SVR.md)
* [文字聊天](dev/svr/CHAT.md)
* [文件传输](dev/svr/FILE.md)
* [多人音视频](dev/svr/VIDEO.md)
* [多人屏幕共享](dev/svr/SCREEN.md)
* [单人直播](dev/svr/LIVE.md)
* [多人语音](dev/svr/AUDIO.md)
* [文件暂存/取件码](dev/svr/FILE_CODE.md)
* [多人画笔](dev/svr/DRAW.md)
* [屏幕录制](dev/svr/RECODE.md)
* [tl-rtc-file-设置选项说明](SETTING.md) * [tl-rtc-file-设置选项说明](SETTING.md)
* [tl-rtc-file-常见问题列表](FAQ.md) * [tl-rtc-file-常见问题列表](FAQ.md)

View File

@@ -1 +1,2 @@
# 项目设计简介 # 项目简介

View File

@@ -1 +0,0 @@
# 多人语音

View File

@@ -1 +0,0 @@
# 文字聊天

View File

@@ -1 +0,0 @@
# 多人画笔

View File

@@ -1 +0,0 @@
# 文件传输

View File

@@ -1 +0,0 @@
# 文件暂存/取件码

View File

@@ -1 +0,0 @@
# 单人直播

View File

@@ -1 +0,0 @@
# 屏幕录制

View File

@@ -1 +0,0 @@
# 多人屏幕共享

View File

@@ -1 +0,0 @@
# 多人音视频

View File

@@ -1 +0,0 @@
# 多人语音

View File

@@ -1 +0,0 @@
# 文字聊天

View File

@@ -1 +0,0 @@
# 多人画笔

View File

@@ -1 +0,0 @@
# 文件传输

View File

@@ -1 +0,0 @@
# 文件暂存/取件码

View File

@@ -1 +0,0 @@
# 单人直播

View File

@@ -1 +0,0 @@
# 屏幕录制

View File

@@ -1 +0,0 @@
# 多人屏幕共享

View File

@@ -1 +0,0 @@
# 多人音视频

View File

@@ -1,5 +1,5 @@
{ {
"version": "10.5.0", "version": "10.5.1",
"socket": { "socket": {
"port": "请到 tlrtcfile.env 中进行配置", "port": "请到 tlrtcfile.env 中进行配置",
"host": "请到 tlrtcfile.env 中进行配置" "host": "请到 tlrtcfile.env 中进行配置"

View File

@@ -5,6 +5,7 @@ const bussinessNotify = require("./../../bussiness/notify/notifyHandler")
const wxapi = require("./../../bussiness/wxapi/wxapi") const wxapi = require("./../../bussiness/wxapi/wxapi")
const { CookieKey } = require("./../../bussiness/cache/key") const { CookieKey } = require("./../../bussiness/cache/key")
const scanCache = require("./../../bussiness/cache/scan/scanCache") const scanCache = require("./../../bussiness/cache/scan/scanCache")
const utils = require("../../utils/utils");
const uuid = require("uuid") const uuid = require("uuid")
// 扫码状态 // 扫码状态
@@ -39,13 +40,14 @@ async function loginWechat(req, res) {
const { session_key, openid, unionid } = openIdInfo; const { session_key, openid, unionid } = openIdInfo;
const userId = await user.addWxUser({ const { userId, flag } = await user.addWxUser({
openid: openid, openid: openid,
avatar: userInfo.avatarUrl, avatar: userInfo.avatarUrl,
uname: userInfo.nickName, uname: userInfo.nickName,
pwd: '', pwd: '',
solt: '', solt: '',
role: 'user', role: 'user',
flag : 0,
}, tables, dbClient); }, tables, dbClient);
//设置登录信息缓存 //设置登录信息缓存
@@ -55,6 +57,7 @@ async function loginWechat(req, res) {
userId : userId, userId : userId,
avatar : userInfo.avatarUrl, avatar : userInfo.avatarUrl,
nickName : userInfo.nickName, nickName : userInfo.nickName,
flag : flag,
loginTime : Date.now(), loginTime : Date.now(),
}); });
@@ -226,10 +229,15 @@ async function getTokenState(req, res){
const loginInfo = scanCache.getLoginInfo(token); const loginInfo = scanCache.getLoginInfo(token);
const avatar = loginInfo.avatar || "/image/44826979.png"; const avatar = loginInfo.avatar || "/image/44826979.png";
const username = loginInfo.nickName || ""; const username = loginInfo.nickName || " -- ";
const flag = loginInfo.flag || 0;
const subscribeNotify = utils.checkBit(flag, req.ctx.tables.UserOther.Flag.IS_SUBSCRIBE_WEBSITE_NOTIFY)
if(Object.keys(loginInfo).length > 0){ if(Object.keys(loginInfo).length > 0){
res.json({ code: 200, login: true, token, avatar, username }); res.json({
code: 200, login: true, loginInfo,
token, avatar, username, subscribeNotify
});
}else{ }else{
res.json({ code: 200, login: false }); res.json({ code: 200, login: false });
} }
@@ -276,7 +284,10 @@ async function getLoginInfo(req, res){
const loginInfo = scanCache.getLoginInfo(token); const loginInfo = scanCache.getLoginInfo(token);
res.json({ code: 200, userId : loginInfo.userId }); res.json({ code: 200, userInfo :{
userId : loginInfo.userId,
flag : loginInfo.flag,
}});
} }

View File

@@ -39,14 +39,14 @@ async function addWxUser(params, tables, dbClient) {
role: params.role, role: params.role,
}); });
return data && data.dataValues ? data.dataValues.id : 0; return data && data.dataValues ? dataValues : { id : 0 };
} }
if(users && users.length === 1){ if(users && users.length === 1){
return users[0].dataValues.id; return users[0].dataValues;
} }
return 0; return { id : 0 };
}catch(e){ }catch(e){
console.error(e); console.error(e);
return {}; return {};
@@ -54,11 +54,46 @@ async function addWxUser(params, tables, dbClient) {
} }
/**
* 更新用户标识
* @param {*} params
* @param {*} tables
* @param {*} dbClient
*/
async function updateUserFlag(params, tables, dbClient){
if(!tables || !dbClient){
return {};
}
if(!params){
params = {};
}
if(!params.id){
return {};
}
let data = await tables.User.update({
flag: params.flag,
}, {
where: {
id: params.id
}
});
utils.tlConsole("更新用户标识 : ", params, data)
return data;
}
module.exports = dbOpen ? { module.exports = dbOpen ? {
addWxUser addWxUser, updateUserFlag
} : { } : {
addWxUser : function(){ addWxUser : function(){
return {} return {}
},
updateUserFlag : function(){
return {}
} }
} }

View File

@@ -20,6 +20,7 @@ const rtcHeartbeat = require("./rtcHeartbeat/heartbeat");
const rtcAddCodeFile = require("./rtcCodeFile/addCodeFile"); const rtcAddCodeFile = require("./rtcCodeFile/addCodeFile");
const rtcGetCodeFile = require("./rtcCodeFile/getCodeFile"); const rtcGetCodeFile = require("./rtcCodeFile/getCodeFile");
const rtcLocalNetRoom = require("./rtcLocalNetRoom/localNetRoom"); const rtcLocalNetRoom = require("./rtcLocalNetRoom/localNetRoom");
const rtcSubscribe = require("./rtcSubscribe/subscribe");
const rtcServerEvent = require("./rtcConstant").rtcServerEvent const rtcServerEvent = require("./rtcConstant").rtcServerEvent
const rtcToken = require("./rtcToken/token") const rtcToken = require("./rtcToken/token")
@@ -32,11 +33,6 @@ module.exports = (io, socket, tables, dbClient) => {
// 在线人数统计 // 在线人数统计
rtcCount.count(io, socket, tables, dbClient, {}) rtcCount.count(io, socket, tables, dbClient, {})
// 局域网房间发现列表
rtcLocalNetRoom.localNetRoom(io, socket, tables, dbClient, {
toCurrentSocket : true
})
// 断开连接 // 断开连接
socket.on(rtcServerEvent.disconnect, (data)=>{ socket.on(rtcServerEvent.disconnect, (data)=>{
rtcDisConnect.disconnect(io, socket, tables, dbClient, data) rtcDisConnect.disconnect(io, socket, tables, dbClient, data)
@@ -141,4 +137,14 @@ module.exports = (io, socket, tables, dbClient) => {
socket.on(rtcServerEvent.changeNickName, (data) => { socket.on(rtcServerEvent.changeNickName, (data) => {
rtcChangeNickName.changeNickName(io, socket, tables, dbClient, data) rtcChangeNickName.changeNickName(io, socket, tables, dbClient, data)
}); });
// 订阅网站通知
socket.on(rtcServerEvent.subscribeNofity, (data) => {
rtcSubscribe.subscribeNofity(io, socket, tables, dbClient, data)
});
// 局域网房间发现列表
socket.on(rtcServerEvent.localNetRoom, (data)=>{
rtcLocalNetRoom.localNetRoomForConnect(io, socket, tables, dbClient, data)
});
} }

View File

@@ -48,6 +48,10 @@ const rtcServerEvent = {
heartbeat : "heartbeat", heartbeat : "heartbeat",
//修改昵称 //修改昵称
changeNickName : "changeNickName", changeNickName : "changeNickName",
//订阅网站通知
subscribeNofity : "subscribeNofity",
//局域网房间发现列表
localNetRoom : "localNetRoom",
} }
/** /**
@@ -84,7 +88,7 @@ let rtcServerMessageEvent = {
//开始远程画笔 //开始远程画笔
startRemoteDraw : "startRemoteDraw", startRemoteDraw : "startRemoteDraw",
//结束远程画笔 //结束远程画笔
stopRemoteDraw : "stopRemoteDraw", stopRemoteDraw : "stopRemoteDraw"
} }
/** /**
@@ -134,6 +138,8 @@ let rtcClientEvent = {
changeNickName : "changeNickName", changeNickName : "changeNickName",
//局域网房间发现列表 //局域网房间发现列表
localNetRoom : "localNetRoom", localNetRoom : "localNetRoom",
//订阅网站通知
subscribeNofity : "subscribeNofity"
} }
/** /**

View File

@@ -1,7 +1,6 @@
const rtcConstant = require("../rtcConstant"); const rtcConstant = require("../rtcConstant");
const rtcClientEvent = rtcConstant.rtcClientEvent const rtcClientEvent = rtcConstant.rtcClientEvent
const utils = require("../../../src/utils/utils"); const utils = require("../../../src/utils/utils");
const rtcLocalNetRoom = require("../rtcLocalNetRoom/localNetRoom");
/** /**
* 在线人数统计广播 * 在线人数统计广播
@@ -18,11 +17,6 @@ async function count(io, socket, tables, dbClient, data){
io.sockets.emit(rtcClientEvent.count, { io.sockets.emit(rtcClientEvent.count, {
mc : allManCount mc : allManCount
}) })
rtcLocalNetRoom.localNetRoom(io, socket, tables, dbClient, {
toAll : true
});
}catch(e){ }catch(e){
utils.tlConsole(e) utils.tlConsole(e)
} }

View File

@@ -21,12 +21,12 @@ const rtcLocalNetRoom = require("../rtcLocalNetRoom/localNetRoom");
* @returns * @returns
*/ */
async function userCreateAndJoin(io, socket, tables, dbClient, data){ async function userCreateAndJoin(io, socket, tables, dbClient, data){
let {handshake, userAgent, ip, address} = utils.getSocketClientInfo(socket); let { handshake, userAgent, ip, address } = utils.getSocketClientInfo(socket);
let { let {
room = '', type = 'file', nickName = '', password = '', room = '', type = 'file', nickName = '', password = '',
langMode = 'zh', ua = '', network = '', liveShareRole = '', langMode = 'zh', ua = '', network = '', liveShareRole = '',
localNetRoom = false localNetRoom = false, ips = []
} = data; } = data;
if (room && room.length > 15) { if (room && room.length > 15) {
@@ -66,7 +66,7 @@ async function userCreateAndJoin(io, socket, tables, dbClient, data){
io.sockets.connected[socket.id].langMode = langMode; io.sockets.connected[socket.id].langMode = langMode;
io.sockets.connected[socket.id].ua = ua; io.sockets.connected[socket.id].ua = ua;
io.sockets.connected[socket.id].network = network; io.sockets.connected[socket.id].network = network;
io.sockets.connected[socket.id].ip = ip; io.sockets.connected[socket.id].ips = ips;
const joinTime = utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss") const joinTime = utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss")
io.sockets.connected[socket.id].joinTime = joinTime; io.sockets.connected[socket.id].joinTime = joinTime;
io.sockets.connected[socket.id].userAgent = userAgent; io.sockets.connected[socket.id].userAgent = userAgent;
@@ -120,26 +120,25 @@ async function userCreateAndJoin(io, socket, tables, dbClient, data){
}); });
//设置为房主 //设置为房主
io.sockets.connected[socket.id].owner = true; io.sockets.connected[socket.id].owner = true;
io.sockets.adapter.rooms[room].owner = socket.id;
//设置房主ip为房间号ip, address //设置房主上报的ip为房间号ip
io.sockets.adapter.rooms[room].ip = ip; io.sockets.adapter.rooms[room].ips = ips;
io.sockets.adapter.rooms[room].address = address;
//房间是否可以被局域网发现
io.sockets.adapter.rooms[room].localNetRoom = localNetRoom;
if(localNetRoom){
rtcLocalNetRoom.localNetRoom(io, socket, tables, dbClient, {
toAll : true
});
}
//设置房间类型 //设置房间类型
io.sockets.adapter.rooms[room].type = type; io.sockets.adapter.rooms[room].type = type;
//房间是否可以被局域网发现
io.sockets.adapter.rooms[room].localNetRoom = localNetRoom;
//密码房间设置密码 //密码房间设置密码
if(type === 'password'){ if(type === 'password'){
io.sockets.adapter.rooms[room].password = password io.sockets.adapter.rooms[room].password = password
} }
//房间创建时间
io.sockets.adapter.rooms[room].createTime = utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss");
}else { }else {
//加入时,房间类型不匹配,提示并退出 //加入时,房间类型不匹配,提示并退出
const createdRoomType = io.sockets.adapter.rooms[room].type; const createdRoomType = io.sockets.adapter.rooms[room].type;
@@ -244,9 +243,11 @@ async function userCreateAndJoin(io, socket, tables, dbClient, data){
}); });
} }
//人数变更通知
rtcCount.count(io, socket, tables, dbClient, data); rtcCount.count(io, socket, tables, dbClient, data);
io.sockets.adapter.rooms[room].createTime = utils.formateDateTime(new Date(), "yyyy-MM-dd hh:mm:ss") //局域网房间变动通知
rtcLocalNetRoom.localNetRoomForJoin(io, socket, tables, dbClient, { room });
if(password && password.length > 0){ if(password && password.length > 0){
bussinessNotify.sendCreateJoinPasswordRoomNotify({ bussinessNotify.sendCreateJoinPasswordRoomNotify({

View File

@@ -1,7 +1,8 @@
const daoRoom = require("./../../dao/room/room") const daoRoom = require("./../../dao/room/room")
const rtcCount = require("./../rtcCount/count"); const rtcCount = require("./../rtcCount/count");
const rtcConstant = require("../rtcConstant"); const rtcConstant = require("../rtcConstant");
const rtcClientEvent = rtcConstant.rtcClientEvent const rtcClientEvent = rtcConstant.rtcClientEvent;
const rtcLocalNetRoom = require("../rtcLocalNetRoom/localNetRoom");
/** /**
* 断开连接的操作 * 断开连接的操作
@@ -18,7 +19,7 @@ async function disconnect(io, socket, tables, dbClient, data){
await daoRoom.exitRoomBySid({ socket_id: socket.id }, tables, dbClient); await daoRoom.exitRoomBySid({ socket_id: socket.id }, tables, dbClient);
rtcCount.count(io, socket, tables, dbClient, data) rtcCount.count(io, socket, tables, dbClient, data);
} }
module.exports = { module.exports = {

View File

@@ -3,8 +3,8 @@ const bussinessNotify = require("./../../bussiness/notify/notifyHandler")
const rtcCount = require("./../rtcCount/count"); const rtcCount = require("./../rtcCount/count");
const utils = require("./../../utils/utils"); const utils = require("./../../utils/utils");
const rtcConstant = require("../rtcConstant"); const rtcConstant = require("../rtcConstant");
const rtcClientEvent = rtcConstant.rtcClientEvent const rtcClientEvent = rtcConstant.rtcClientEvent;
const rtcLocalNetRoom = require("../rtcLocalNetRoom/localNetRoom");
/** /**
* 退出房间 * 退出房间
@@ -48,6 +48,9 @@ async function exit(io, socket, tables, dbClient, data){
rtcCount.count(io, socket, tables, dbClient, data); rtcCount.count(io, socket, tables, dbClient, data);
//局域网房间变动通知
rtcLocalNetRoom.localNetRoomForExit(io, socket, tables, dbClient, { room });
} catch (e) { } catch (e) {
socket.emit(rtcClientEvent.tips, { socket.emit(rtcClientEvent.tips, {
room: data.room, room: data.room,

View File

@@ -2,134 +2,46 @@ const rtcConstant = require("../rtcConstant");
const rtcClientEvent = rtcConstant.rtcClientEvent const rtcClientEvent = rtcConstant.rtcClientEvent
const bussinessNotify = require("../../bussiness/notify/notifyHandler") const bussinessNotify = require("../../bussiness/notify/notifyHandler")
const utils = require("../../../src/utils/utils"); const utils = require("../../../src/utils/utils");
const os = require('os');
/** /**
* 局域网房间发现列表 * 服务器网络列表
* */
* @param {*} io socketio对象 let serverNetworkList = null;
* @param {*} socket 单个socket连接 (() => {
* @param {*} tables 数据表对象 if (!serverNetworkList) {
* @param {*} dbClient sequelize-orm对象 serverNetworkList = [];
* @param {*} data event参数 let ifaces = os.networkInterfaces();
for (let iface in ifaces) {
for (let i = 0, len = ifaces[iface].length; i < len; ++i) {
const item = ifaces[iface][i];
if (item.family === 'IPv4') {
serverNetworkList.push(ifaces[iface][i])
}
}
}
}
})()
console.log(serverNetworkList)
/**
* 通过ip获取子网掩码
* @param {*} ip
* @returns * @returns
*/ */
async function localNetRoom(io, socket, tables, dbClient, data){ function getNetMaskByIp(ip) {
try{ if (!serverNetworkList) {
const { toCurrentSocket = false, toAll = false } = data; return "255.255.255.255";
let { ip, address } = utils.getSocketClientInfo(socket);
let roomList = [];
let rooms = io.sockets.adapter.rooms;
for(let roomId in rooms){
if(roomId.length > 15){
continue;
}
//最多返回10个房间
if(roomList.length > 10){
break;
}
// 是否开启局域网房间
const localNetRoom = rooms[roomId].localNetRoom || false;
if(!localNetRoom){
continue;
}
// 房间ip
const roomIp = rooms[roomId].ip || "";
// 房间address/ip
const roomAddress = rooms[roomId].address || "";
if(roomIp){
// 本地请求
if(
(roomIp.indexOf("127.0.0.1") > -1 && ip.indexOf("127.0.0.1") > -1)
||
(roomIp.indexOf("localhost") > -1 && ip.indexOf("localhost") > -1)
){
roomList = addFilterRoomListData(roomList, {
room : roomId,
type : 'file',
ips : [roomIp],
count : rooms[roomId].length
})
}else{
// 在同一个网段
if(utils.isSameSubnet(roomIp, ip, "255.255.255.255")){
roomList = addFilterRoomListData(roomList, {
room : roomId,
type : 'file',
ips : [roomIp],
count : rooms[roomId].length
})
}
}
}
if(roomAddress){
// 本地请求
if(
(roomAddress.indexOf("127.0.0.1") > -1 && address.indexOf("127.0.0.1") > -1)
||
(roomAddress.indexOf("localhost") > -1 && address.indexOf("localhost") > -1)
){
roomList = addFilterRoomListData(roomList, {
room : roomId,
type : 'file',
ips : [roomAddress],
count : rooms[roomId].length
})
}else{
// 在同一个网段
if(utils.isSameSubnet(roomAddress, address, "255.255.255.255")){
roomList = addFilterRoomListData(roomList, {
room : roomId,
type : 'file',
ips : [roomAddress],
count : rooms[roomId].length
})
}
}
}
}
roomList.map(item=>{
item.room = item.room.toString().substring(0,1) + "***";
})
// 通知当前用户
if(toCurrentSocket){
socket.emit(rtcClientEvent.localNetRoom, {
list : roomList
})
}
// 通知全部用户
if(toAll){
io.sockets.emit(rtcClientEvent.localNetRoom, {
list : roomList
});
}
}catch(e){
utils.tlConsole(e)
bussinessNotify.sendSystemErrorMsg({
title: "socket-localNetRoom",
data: JSON.stringify(data),
room: "",
from : socket.id,
msg : JSON.stringify({
message: e.message,
fileName: e.fileName,
lineNumber: e.lineNumber,
stack: e.stack,
name: e.name
}, null, '\t')
})
} }
const filterList = serverNetworkList.filter(item => {
return item.address === ip;
})
if (!filterList || filterList.length === 0) {
return "255.255.255.255";
}
return filterList[0].netmask;
} }
@@ -138,15 +50,15 @@ async function localNetRoom(io, socket, tables, dbClient, data){
* @param {*} list * @param {*} list
* @returns * @returns
*/ */
function addFilterRoomListData(list, obj){ function addFilterRoomListData(list, obj) {
let exist = list.filter(item => item.room === obj.room).length > 0; let exist = list.filter(item => item.room === obj.room).length > 0;
if(!exist){ if (!exist) {
list.push(obj) list.push(obj)
return list return list
} }
for(let i = 0; i < list.length; i++){ for (let i = 0; i < list.length; i++) {
if(list[i].room === obj.room){ if (list[i].room === obj.room) {
let oldIps = list[i].ips; let oldIps = list[i].ips;
oldIps.push(obj.ips[0]) oldIps.push(obj.ips[0])
list[i].ips = oldIps; list[i].ips = oldIps;
@@ -156,6 +68,245 @@ function addFilterRoomListData(list, obj){
} }
/**
* 局域网房间发现列表
* 连接类型广播
*
* @param {*} io socketio对象
* @param {*} socket 单个socket连接
* @param {*} tables 数据表对象
* @param {*} dbClient sequelize-orm对象
* @param {*} data event参数
* @returns
*/
function localNetRoom(io, socket, tables, dbClient, data) {
const { ips : currentIps = [] } = data;
let filterRoomList = [];
//所有正常的房间列表ip统计
let rooms = io.sockets.adapter.rooms;
let roomIpsList = [];
for (let roomId in rooms) {
let roomIps = rooms[roomId].ips;
if (
roomId.length > 15 || // 非法房间号
!rooms[roomId] || // 房间不存在
!roomIps || // 房间没有上报ip
roomIps.length === 0 || // 房间没有上报ip
rooms[roomId].length === 0 || // 房间没有人
!rooms[roomId].localNetRoom // 房间没有开启局域网
) {
continue;
}
//最多处理返回10个局域网房间
if (roomIpsList.length > 10) {
break;
}
roomIpsList.push(...roomIps.map(item => {
item.room = roomId;
item.count = rooms[roomId] ? Object.keys(rooms[roomId].sockets).length : 0,
item.owner = rooms[roomId].owner;
item.roomType = rooms[roomId].type;
return item;
}))
}
//根据当前socket连接的ip信息筛选出和ip在同一个局域网的房间列表
currentIps.forEach(currentIpInfo => {
const { ipType: currentIpType, address: currentAddress } = currentIpInfo;
roomIpsList.forEach(otherIpInfo => {
const { ipType: otherIpType, address: otherAddress, room, count, owner, roomType } = otherIpInfo;
if (otherIpType === "srflx" && currentIpType === 'srflx') { //公网ip
if (utils.isSameSubnet(currentAddress, otherAddress, getNetMaskByIp(currentAddress))) {
filterRoomList = addFilterRoomListData(filterRoomList, {
room, roomType, count, owner, ips: [otherAddress]
})
}
} else if (otherIpType === 'host' && currentIpType === 'host') { //内网ip
if (utils.isSameSubnet(currentAddress, otherAddress, getNetMaskByIp(currentAddress))) {
filterRoomList = addFilterRoomListData(filterRoomList, {
room, roomType, count, owner, ips: [otherAddress]
})
}
}
})
});
// filterRoomList.map(item => {
// item.room = item.room.toString().substring(0, 1) + "***";
// })
return filterRoomList;
}
/**
* 局域网房间发现列表
* socket用户连接之后广播
* @param {*} io socketio对象
* @param {*} socket 单个socket连接
* @param {*} tables 数据表对象
* @param {*} dbClient sequelize-orm对象
* @param {*} data event参数
* @returns
*/
function localNetRoomForConnect(io, socket, tables, dbClient, data) {
try {
let filterRoomList = localNetRoom(io, socket, tables, dbClient, data);
socket.emit(rtcClientEvent.localNetRoom, {
list: filterRoomList,
mode : 'connect'
});
} catch (e) {
utils.tlConsole(e)
bussinessNotify.sendSystemErrorMsg({
title: "socket-localNetRoomForConnect",
data: JSON.stringify(data),
room: "",
from: socket.id,
msg: JSON.stringify({
message: e.message,
fileName: e.fileName,
lineNumber: e.lineNumber,
stack: e.stack,
name: e.name
}, null, '\t')
})
}
}
/**
* 局域网房间发现列表
* socket用户加入房间之后广播
* @param {*} io socketio对象
* @param {*} socket 单个socket连接
* @param {*} tables 数据表对象
* @param {*} dbClient sequelize-orm对象
* @param {*} data event参数
* @returns
*/
function localNetRoomForJoin(io, socket, tables, dbClient, data) {
try {
const { room } = data;
const socketRoomInfo = io.sockets.adapter.rooms[room];
const ips = socketRoomInfo ? socketRoomInfo.ips : [];
const owner = socketRoomInfo ? socketRoomInfo.owner : socket.id;
const count = socketRoomInfo ? Object.keys(socketRoomInfo.sockets).length : 0;
const roomType = socketRoomInfo ? socketRoomInfo.type : "file";
io.sockets.emit(rtcClientEvent.localNetRoom, {
list : [{ room, roomType, count, owner, ips : ips.map(item => item.address) }],
mode : 'join'
});
} catch (e) {
utils.tlConsole(e)
bussinessNotify.sendSystemErrorMsg({
title: "socket-localNetRoomForJoin",
data: JSON.stringify(data),
room: "",
from: socket.id,
msg: JSON.stringify({
message: e.message,
fileName: e.fileName,
lineNumber: e.lineNumber,
stack: e.stack,
name: e.name
}, null, '\t')
})
}
}
/**
* 局域网房间发现列表
* socket用户退出房间之后广播
* @param {*} io socketio对象
* @param {*} socket 单个socket连接
* @param {*} tables 数据表对象
* @param {*} dbClient sequelize-orm对象
* @param {*} data event参数
* @returns
*/
function localNetRoomForExit(io, socket, tables, dbClient, data) {
try {
const { room } = data;
const socketRoomInfo = io.sockets.adapter.rooms[room];
const ips = socketRoomInfo ? socketRoomInfo.ips : [];
const owner = socketRoomInfo ? socketRoomInfo.owner : socket.id;
const count = socketRoomInfo ? Object.keys(socketRoomInfo.sockets).length : 0;
const roomType = socketRoomInfo ? socketRoomInfo.type : "file";
io.sockets.emit(rtcClientEvent.localNetRoom, {
list : [{ room, roomType, count, owner, ips: ips.map(item => item.address) }],
mode : 'exit'
});
} catch (e) {
utils.tlConsole(e)
bussinessNotify.sendSystemErrorMsg({
title: "socket-localNetRoomForExit",
data: JSON.stringify(data),
room: "",
from: socket.id,
msg: JSON.stringify({
message: e.message,
fileName: e.fileName,
lineNumber: e.lineNumber,
stack: e.stack,
name: e.name
}, null, '\t')
})
}
}
/**
* 局域网房间发现列表
* socket用户断开连接之后广播
* @param {*} io socketio对象
* @param {*} socket 单个socket连接
* @param {*} tables 数据表对象
* @param {*} dbClient sequelize-orm对象
* @param {*} data event参数
* @returns
*/
function localNetRoomForDisconnect(io, socket, tables, dbClient, data) {
try {
io.sockets.emit(rtcClientEvent.localNetRoom, {
list : [{ socketId : socket.id }],
mode : 'disconnect'
});
} catch (e) {
utils.tlConsole(e)
bussinessNotify.sendSystemErrorMsg({
title: "socket-localNetRoomForDisconnect",
data: JSON.stringify(data),
room: "",
from: socket.id,
msg: JSON.stringify({
message: e.message,
fileName: e.fileName,
lineNumber: e.lineNumber,
stack: e.stack,
name: e.name
}, null, '\t')
})
}
}
module.exports = { module.exports = {
localNetRoom localNetRoomForConnect, localNetRoomForJoin,
localNetRoomForExit, localNetRoomForDisconnect
} }

View File

@@ -0,0 +1,57 @@
const utils = require("./../../utils/utils");
const daoDog = require("./../../dao/dog/dog")
const daoUser = require("./../../dao/user/user")
const rtcConstant = require("../rtcConstant");
const rtcClientEvent = rtcConstant.rtcClientEvent
const daoRelation = require("../../dao/relation/relation");
/**
* 订阅网站通知
* @param {*} io socketio对象
* @param {*} socket 单个socket连接
* @param {*} tables 数据表对象
* @param {*} dbClient sequelize-orm对象
* @param {*} data event参数
* @returns
*/
async function subscribeNofity(io, socket, tables, dbClient, data){
let { roomId = '', email = '' } = data;
let { handshake, userAgent, ip } = utils.getSocketClientInfo(socket);
socket.emit(rtcClientEvent.subscribeNofity, data);
//控制操作事件入库
let recoderId = await daoDog.addDogData({
name: "订阅网站通知",
roomId: roomId,
socketId: socket.id,
device: userAgent,
flag: 0,
content: JSON.stringify(data),
handshake: JSON.stringify(handshake),
ip: ip
}, tables, dbClient);
//更新用户订阅标识
const { userId, flag = 0 } = socket.userInfo;
if(userId){
await daoUser.updateUserFlag({
id : userId,
flag : utils.setBit(flag, tables.UserOther.Flag.IS_SUBSCRIBE_WEBSITE_NOTIFY)
}, tables, dbClient);
}
//添加用户-操作关联记录
if(socket.userId){
daoRelation.addUserDogRelation({
dogId : recoderId,
userId : socket.userId,
}, tables, dbClient);
}
}
module.exports = {
subscribeNofity
}

View File

@@ -29,7 +29,7 @@ async function token(io, socket, tables, dbClient, data){
"content-type": "application/json", "content-type": "application/json",
}, },
qs: { qs: {
token, key : "iamtsm-socket" token, key : cfg.login.token.key
}, },
}, (err, res, body) => { }, (err, res, body) => {
if(err){ if(err){
@@ -42,9 +42,9 @@ async function token(io, socket, tables, dbClient, data){
return; return;
} }
socket.userId = body.userId; socket.userInfo = body.userInfo;
utils.tlConsole("同步token信息成功 : ", token, body.userId) utils.tlConsole("同步token信息成功 : ", token, body.userInfo)
}); });
} }

View File

@@ -1,6 +1,11 @@
// user // user
module.exports = (sequelize, DataTypes) => { module.exports = (sequelize, DataTypes) => {
return { return {
UserOther : {
Flag : {
IS_SUBSCRIBE_WEBSITE_NOTIFY : 0x1, //是否已订阅网站通知
}
},
User: sequelize.define('user', { User: sequelize.define('user', {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
@@ -36,6 +41,11 @@ module.exports = (sequelize, DataTypes) => {
role: { role: {
type: DataTypes.STRING(15), type: DataTypes.STRING(15),
comment: '用户身份' comment: '用户身份'
},
flag: {
type: DataTypes.INTEGER,
comment: '标志位',
defaultValue: 0,
} }
}, { }, {
timestamps: true, timestamps: true,

View File

@@ -49,7 +49,7 @@ function getLocalIP() {
function isSameSubnet(ip1, ip2, subnetMask) { function isSameSubnet(ip1, ip2, subnetMask) {
// 将IPv4或IPv6地址和子网掩码转换为数字形式 // 将IPv4或IPv6地址和子网掩码转换为数字形式
function ipToNumber(ip) { function ipToNumber(ip) {
if (ip.includes(':')) { // IPv6 if (ip.indexOf(':') > -1) { // IPv6
const parts = ip.split(':'); const parts = ip.split(':');
return parts.map(part => parseInt(part, 16)).join(''); return parts.map(part => parseInt(part, 16)).join('');
} else { // IPv4 } else { // IPv4
@@ -374,6 +374,15 @@ function checkBit(flag, bit){
return (flag & bit) === bit; return (flag & bit) === bit;
} }
/**
* 根据flag和bit设置对应的值
* @param {*} flag
* @param {*} bit
*/
function setBit(flag, bit){
return flag | bit;
}
module.exports = { module.exports = {
@@ -392,5 +401,6 @@ module.exports = {
unescapeStr, unescapeStr,
escapeStr, escapeStr,
isSameSubnet, isSameSubnet,
checkBit checkBit,
setBit
} }

View File

@@ -54,6 +54,24 @@
<div class="content unicode" style="display: block;"> <div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe635;</span>
<div class="name">通知</div>
<div class="code-name">&amp;#xe635;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe702;</span>
<div class="name">群蜂操作记录</div>
<div class="code-name">&amp;#xe702;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6af;</span>
<div class="name">订阅</div>
<div class="code-name">&amp;#xe6af;</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe604;</span> <span class="icon iconfont">&#xe604;</span>
<div class="name">置顶</div> <div class="name">置顶</div>
@@ -738,9 +756,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1698150656017') format('woff2'), src: url('iconfont.woff2?t=1698825191464') format('woff2'),
url('iconfont.woff?t=1698150656017') format('woff'), url('iconfont.woff?t=1698825191464') format('woff'),
url('iconfont.ttf?t=1698150656017') format('truetype'); url('iconfont.ttf?t=1698825191464') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -766,6 +784,33 @@
<div class="content font-class"> <div class="content font-class">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-rtc-file-tongzhi"></span>
<div class="name">
通知
</div>
<div class="code-name">.icon-rtc-file-tongzhi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-rtc-file-qunfengcaozuojilu"></span>
<div class="name">
群蜂操作记录
</div>
<div class="code-name">.icon-rtc-file-qunfengcaozuojilu
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-rtc-file-dingyue"></span>
<div class="name">
订阅
</div>
<div class="code-name">.icon-rtc-file-dingyue
</div>
</li>
<li class="dib"> <li class="dib">
<span class="icon iconfont icon-rtc-file-zhiding"></span> <span class="icon iconfont icon-rtc-file-zhiding"></span>
<div class="name"> <div class="name">
@@ -1792,6 +1837,30 @@
<div class="content symbol"> <div class="content symbol">
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-rtc-file-tongzhi"></use>
</svg>
<div class="name">通知</div>
<div class="code-name">#icon-rtc-file-tongzhi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-rtc-file-qunfengcaozuojilu"></use>
</svg>
<div class="name">群蜂操作记录</div>
<div class="code-name">#icon-rtc-file-qunfengcaozuojilu</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-rtc-file-dingyue"></use>
</svg>
<div class="name">订阅</div>
<div class="code-name">#icon-rtc-file-dingyue</div>
</li>
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-rtc-file-zhiding"></use> <use xlink:href="#icon-rtc-file-zhiding"></use>

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4147343 */ font-family: "iconfont"; /* Project id 4147343 */
src: url('iconfont.woff2?t=1698150656017') format('woff2'), src: url('iconfont.woff2?t=1698825191464') format('woff2'),
url('iconfont.woff?t=1698150656017') format('woff'), url('iconfont.woff?t=1698825191464') format('woff'),
url('iconfont.ttf?t=1698150656017') format('truetype'); url('iconfont.ttf?t=1698825191464') format('truetype');
} }
.iconfont { .iconfont {
@@ -13,6 +13,18 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-rtc-file-tongzhi:before {
content: "\e635";
}
.icon-rtc-file-qunfengcaozuojilu:before {
content: "\e702";
}
.icon-rtc-file-dingyue:before {
content: "\e6af";
}
.icon-rtc-file-zhiding:before { .icon-rtc-file-zhiding:before {
content: "\e604"; content: "\e604";
} }

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,27 @@
"css_prefix_text": "icon-rtc-file-", "css_prefix_text": "icon-rtc-file-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "10906513",
"name": "通知",
"font_class": "tongzhi",
"unicode": "e635",
"unicode_decimal": 58933
},
{
"icon_id": "423509",
"name": "群蜂操作记录",
"font_class": "qunfengcaozuojilu",
"unicode": "e702",
"unicode_decimal": 59138
},
{
"icon_id": "28108444",
"name": "订阅",
"font_class": "dingyue",
"unicode": "e6af",
"unicode_decimal": 59055
},
{ {
"icon_id": "8224818", "icon_id": "8224818",
"name": "置顶", "name": "置顶",

View File

@@ -213,7 +213,7 @@ body {
border-radius: 15px; border-radius: 15px;
color: white; color: white;
background: #7187e685; background: #7187e685;
transition: font-size 0.3s; transition: all .4s;
} }
.tl-rtc-file-tool-list .swiper-slide { .tl-rtc-file-tool-list .swiper-slide {
@@ -1054,18 +1054,11 @@ body {
margin-bottom: 10px; margin-bottom: 10px;
} }
.tl-rtc-file-login-user{ .tl-rtc-file-login-user, .tl-rtc-file-login-user-info{
margin-top: 20px; margin: 10px;
margin-bottom: 20px; text-align: center;
width: 80%; max-height: 250px;
margin-left: 10%; overflow: hidden;
}
.tl-rtc-file-login-user-info{
margin-top: 20px;
margin-bottom: 20px;
width: 80%;
margin-left: 10%;
} }
.tl-rtc-file-login-user-info-avatar{ .tl-rtc-file-login-user-info-avatar{
@@ -1075,8 +1068,10 @@ body {
} }
.tl-rtc-file-login-user-info-avatar img{ .tl-rtc-file-login-user-info-avatar img{
width: 100%; width: 50%;
border-radius: 50%; border-radius: 50%;
box-shadow: #c2b6b63b 0 3px 10px 0px;
cursor: pointer;
} }
#tl-rtc-file-user-help{ #tl-rtc-file-user-help{
@@ -1096,16 +1091,36 @@ body {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
.tl-rtc-file-logout{ .tl-rtc-file-login-user-btn{
width: 60%; width: 80%;
margin-left: 10%;
bottom: 20px;
position: absolute; position: absolute;
margin-left: 8%;
} }
.tl-rtc-file-logout button{ .tl-rtc-file-logout button{
width: 100%; width: 100%;
margin-bottom: 10px; border-radius: 8px;
background: #79b0e8;
}
.tl-rtc-file-user-oper{
display: inline-flex;
align-items: center;
margin-top: 20px;
margin-bottom: 20px;
}
.tl-rtc-file-user-oper svg{
font-size: 32px;
margin: 5px;
cursor: pointer;
border-radius: 50%;
padding: 5px;
transition: all .3s;
}
.tl-rtc-file-user-oper svg:hover{
background: #f1f1f1;
} }
.isMediaing{ .isMediaing{

View File

@@ -71,11 +71,6 @@
<use xlink:href="#icon-rtc-file-gongzhonghao"></use> <use xlink:href="#icon-rtc-file-gongzhonghao"></use>
</svg> </svg>
</a> </a>
<a :title="lang.relay_on" id="useTurn" v-show="switchData.openUseTurnIcon && useTurn" @click="useTurnMsg">
<svg class="icon" aria-hidden="true" style="width: 20px;height: 20px;margin-right: 10px;">
<use xlink:href="#icon-rtc-file-yunfuwuqi"></use>
</svg>
</a>
<a :title="lang.other_language" id="language"> <a :title="lang.other_language" id="language">
<svg class="icon" aria-hidden="true" style="width: 18px;height: 18px;margin-right: 10px;"> <svg class="icon" aria-hidden="true" style="width: 18px;height: 18px;margin-right: 10px;">
<use xlink:href="#icon-rtc-file-duoyuyan"></use> <use xlink:href="#icon-rtc-file-duoyuyan"></use>
@@ -1082,7 +1077,7 @@
<div class="layui-col-sm2" style="width: 100%;"> <div class="layui-col-sm2" style="width: 100%;">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header"> <div class="layui-card-header">
{{lang.log}} <b v-show="isCloseLogs" style="color: red;">{{lang.off}}</b> - {{lang.total}}:{{filterLogs.length}} {{lang.log}} <b v-show="!useLogOutput" style="color: red;">{{lang.off}}</b> - {{lang.total}}:{{filterLogs.length}}
<i @click="clickLogs" class="layui-icon layui-icon-close" <i @click="clickLogs" class="layui-icon layui-icon-close"
style="cursor: pointer; right: 10px;position: absolute;"></i> style="cursor: pointer; right: 10px;position: absolute;"></i>
</div> </div>

View File

@@ -48,6 +48,9 @@ window.tlrtcfile = {
containSymbol: function (str) { containSymbol: function (str) {
return new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>《》/?~@#¥……&*()——|{}【】‘;:”“'。,、?]").test(str) return new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>《》/?~@#¥……&*()——|{}【】‘;:”“'。,、?]").test(str)
}, },
isEmail : function(str){
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
},
genNickNameRandom: function () { genNickNameRandom: function () {
// 获取指定范围内的随机数 // 获取指定范围内的随机数
function randomAccess(min, max) { function randomAccess(min, max) {
@@ -435,15 +438,13 @@ window.tlrtcfile = {
return await getRTCStats(peerConnection); return await getRTCStats(peerConnection);
}, },
copyTxt: function (id, content) { copyTxt: function (id, content, callback) {
let that = this; let that = this;
document.querySelector("#" + id).setAttribute("data-clipboard-text", content); document.querySelector("#" + id).setAttribute("data-clipboard-text", content);
let clipboard = new ClipboardJS('#' + id); let clipboard = new ClipboardJS('#' + id);
clipboard.on('success', function (e) { clipboard.on('success', function (e) {
e.clearSelection(); e.clearSelection();
if (window.layer) { callback && callback();
layer.msg("复制内容成功!")
}
}); });
}, },
getQrCode: function (id, content) { getQrCode: function (id, content) {
@@ -483,23 +484,23 @@ window.tlrtcfile = {
callback("keyup", event) callback("keyup", event)
}) })
}, },
getRoomTypeZh: function (type){ getRoomType: function (type){
if(type === 'file'){ if(type === 'file'){
return "文件房间" return "file_room_type"
}else if(type === 'live'){ }else if(type === 'live'){
return "直播房间" return "live_room_type"
}else if(type === 'video'){ }else if(type === 'video'){
return "音视频房间" return "video_room_type"
}else if(type === 'screen'){ }else if(type === 'screen'){
return "屏幕共享房间" return "screen_room_type"
}else if(type === 'password'){ }else if(type === 'password'){
return "密码房间" return "password_room_type"
}else if(type === 'audio'){ }else if(type === 'audio'){
return "语音连麦房间" return "audio_room_type"
}else if(type === 'system'){ }else if(type === 'system'){
return "系统房间" return "system_room_type"
}else{ }else{
return "未知类型房间" return "unknown_room_type"
} }
}, },
scrollToBottom: function (dom, duration, timeout) { scrollToBottom: function (dom, duration, timeout) {
@@ -551,8 +552,8 @@ window.tlrtcfile = {
animateMargin() animateMargin()
}, timeout); }, timeout);
}, },
genNickName: function () { genNickName: function (language) {
let { adjectives, nouns } = this.nameDatabase() let { adjectives, nouns } = language === 'zh' ? this.nameDatabase() : this.nameDatabaseEn()
let adjectiveIndex = Math.floor(Math.random() * adjectives.length); let adjectiveIndex = Math.floor(Math.random() * adjectives.length);
let nounIndex = Math.floor(Math.random() * nouns.length); let nounIndex = Math.floor(Math.random() * nouns.length);
let adjective = adjectives[adjectiveIndex]; let adjective = adjectives[adjectiveIndex];
@@ -618,6 +619,62 @@ window.tlrtcfile = {
] ]
return { adjectives, nouns } return { adjectives, nouns }
}, },
nameDatabaseEn: function () {
const adjectives = [
"Humorous", "Funny", "Crazy", "Strange", "Quirky", "Boring", "Mysterious", "Magical", "Witty", "Playful",
"Clever", "Beautiful", "Cute", "Charming", "Cool", "Adorable", "Stylish", "Majestic", "Fierce", "Radiant",
"Clever", "Mischievous", "Tiny", "Delicate", "Tender", "Soft", "Friendly", "Humble", "Reserved", "Proud",
"Narcissistic", "Romantic", "Innocent", "Passionate", "Persistent", "Cold", "Spoiled", "Naive", "Passionate", "Mature",
"Melancholic", "Neurotic", "Lonely", "Nostalgic", "Fresh", "Elegant", "Elegant", "Aloof", "Sassy", "Rebellious",
"Irritable", "Violent", "Alluring", "Crafty", "Confident", "Insecure", "Pessimistic", "Optimistic", "Brave", "Timid", "Joyful",
"Painful", "Kind", "Evil", "Profound", "Sacred", "Plump", "Slender", "Obese", "Slender", "Handsome", "Ugly",
"Fragrant", "Stinky", "Passionate", "Indifferent", "Vibrant", "Clean", "Dirty", "Carefree", "Moody",
"Ordinary", "Extraordinary", "Shy", "Warm-hearted", "Witty", "Agile", "Dull", "Intelligent", "Ignorant", "Sincere", "Hypocritical",
"Frank", "Cautious", "Bold", "Humble", "Arrogant", "Serious", "Relaxed", "Anxious", "Hardworking", "Lazy", "Punctual",
"Late", "Strong", "Weak", "Intelligent", "Stupid", "Smart", "Clever", "Mischievous", "Naughty", "Lively", "Silent",
"Healthy", "Unhealthy", "Tall", "Short", "Long", "Short", "Fat", "Thin", "Happy", "Unhappy", "Sweet", "Bitter",
"Astute", "Foolish", "Intelligent", "High IQ", "Resourceful", "Clumsy", "Calm", "Impulsive", "Steady", "Frivolous",
"Gentle", "Rough", "Learner", "Hates Learning", "Eater", "Picky Eater", "Patient", "Impatient", "Friendly", "Aloof", "Tolerant",
"Stubborn", "Cautious", "Kind", "Malicious", "Calm", "Hysterical", "Opportunistic", "Pessimistic", "Optimistic", "Open-minded", "Narrow-minded",
"Loyal", "Untrustworthy", "Charming", "Boring", "Thoughtful", "Boring", "Strategic", "Shortsighted", "Understanding", "Selfish", "Frank",
"Curious", "Insensitive", "Social", "Reclusive", "Talkative", "Quiet", "Thoughtful", "Quick-witted", "Emotionally Rich", "Kind-hearted", "Confident",
"Innocent", "Pursuing Perfection", "Energetic", "Adventurous", "Creative", "Calm", "Goal-oriented", "Gentle", "Helpful",
"Smart and Quick-witted", "Loyal", "Quick-witted", "Generous", "Graceful and Multifaceted", "Fashionable", "Easy-going", "Elegant and Graceful",
"Resilient", "Independent", "Outgoing", "Introverted", "Passionate and Focused", "Energetic", "Humerous", "Thoughtful and Kind", "Sacrificing",
"Decisive", "Curious", "Warm-hearted", "Enthusiastic", "Lonely and Sad", "Romantic and Passionate", "Smiling", "Unrestrained", "Silly", "Carefree",
"Lazy", "Boring", "Low-key", "Sensitive", "Cold", "Focused", "Scornful", "Passionate", "Loyal", "Mysterious", "Proud", "Free", "Artistic",
"Fashionable", "Generous", "Talented", "Elegant", "Sunny", "Witty", "Naive and Romantic", "Cheerful", "Reserved and Calm", "Diligent", "Lazy",
"Responsible", "Desiring Freedom", "Emotional", "Rational", "Insecure", "Seeking Security", "Emotional", "Optimistic", "Pessimistic", "Realistic", "Idealistic",
"Approachable", "Arrogant", "Valuing Family", "Valuing Friendship", "Valuing Love", "Compassionate", "Sense of Justice", "Compassionate", "Childlike", "Confident", "Timid",
"Talkative", "Reserved", "Outgoing", "Introverted", "Curious", "Not Understanding Others", "Sociable", "Loves Being Alone", "Self-aware", "Loves Music", "Loves Reading",
"Loves Traveling", "Loves Food", "Loves Sports", "Loves Photography", "Loves Collecting", "Loves Shopping", "Hates Going Out", "Picky", "Self-reflective", "Doesn't Judge Others",
"Judges Others", "Tasteful", "Unhygienic", "Hygienic", "Loves Cleanliness", "Loves Chaos", "Loves Organization", "Loves Casualness", "Loves Tidiness"
];
const nouns = [
'Puppy', 'Kitten', 'Fawn', 'Bear Cub', 'Bunny', 'Lamb', 'Piglet', 'Foal', 'Little Lion', 'Little Tiger',
'Little Monkey', 'Little Fish', 'Little Turtle', 'Little Bird', 'Little Ant', 'Little Bee', 'Little Butterfly', 'Little Dragonfly', 'Little Crab', 'Little Octopus',
'Little Dolphin', 'Little Shark', 'Little Whale', 'Little Crocodile', 'Little Duck', 'Snowman', 'Little Ball', 'Little Basketball', 'Little Soccer', 'Little Volleyball',
'Little Baseball', 'Little Skateboard', 'Little Ice Cream', 'Little Umbrella', 'Little Glove', 'Little Movie', 'Little Blue Sky', 'Little Princess', 'Little Prince', 'Little Toy',
'Little Candy', 'Little Chocolate', 'Little Ice Cream', 'Little Cake', 'Little Pizza', 'Little Burger', 'Little Fried Chicken', 'Little Roast Duck', 'Little Fish Ball', 'Little Hot Pot',
'Little Skewer', 'Little Pancake', 'Little Deep-Fried Dough Stick', 'Little Rice Porridge', 'Little Yogurt', 'Little Tofu', 'Little Dumpling', 'Little Bun', 'Little Wonton',
'Little Noodles', 'Little Beef Noodles', 'Little Glutinous Rice Chicken', 'Little Steamed Dumpling', 'Little Fried Noodles', 'Little Steamed Bun', 'Little Roast Meat', 'Little Skewer', 'Little Peanut', 'Little Sun',
'Little Moon', 'Little Star', 'Little Rainbow', 'Little Windmill', 'Little Balloon', 'Little Piano', 'Little Guitar', 'Little Speaker', 'Little Microphone', 'Little Actor',
'Little Painter', 'Little Engineer', 'Little Doctor', 'Little Policeman', 'Little Firefighter', 'Little Driver', 'Little Farmer', 'Little Diver', 'Little Pilot', 'Little Basketball',
'Little Swimming Champion', 'Little Running Champion', 'Little Martial Arts Expert', 'Little Ballet Dancer', 'Little Sand Painter', 'Little Calligrapher', 'Little Jigsaw Expert', 'Little Toy Collector',
'Little Movie Producer', 'Little Space Traveler', 'Superhero', 'Invincible Demon King', 'Ultimate Overlord', 'Supreme Emperor', 'Giant from Heaven', 'Peerless Genius', 'Mythical Gate',
'Terrifying Monster', 'Wizard', 'Mysterious Swordsman', 'Immortal Legend', 'Cosmic Tyrant', 'Volcano of Hell', 'Endless Darkness', 'Shining Star', 'Radiant Light', 'Golden Knight',
'Doomsday Annihilator', 'Invincible', 'Crushing Everything', 'Peerless Master', 'Extraordinary', 'King of All', 'Dark Knight', 'War God', 'Center of Attention', 'Shocking the World',
'Domineering', 'Never Wavering', 'Empire Ruler', 'Unyielding', 'Ruthless King', 'Beyond Limits', 'Infinite Power', 'Shining Brightly', 'Endless Pursuit', 'Dance of the Blade',
'Solo World', 'Consuming Everything', 'Eternal Realm', 'Doomsday War God', 'Vast Wealth', 'Mythical Legend', 'Unrivaled', 'Master of a Thousand Swords', 'Bloodthirsty Demon', 'King of the Deep Sea',
'Fantasy City', 'Chosen One', 'Immortal Swordsman', 'Eternal Legend', 'Cosmic Overlord', 'Fire Volcano', 'Boundless Darkness', 'Shining Star', 'Infinite Quest', 'Dance of the Blade',
'Swallower of All Things', 'Eternal War God', 'Massive Fortune', 'Mythical Legend', 'Only One', 'Myriad Swords Return to the Origin', 'Bloodthirsty Madman', 'King of the Deep Sea', 'Fantasy City', 'Chosen One',
'Immortal Swordsman', 'Eternal Legend', 'Cosmic Overlord', 'Fire Volcano', 'Boundless Darkness', 'Shining Star', 'Infinite Quest', 'Dance of the Blade', 'Swallower of All Things', 'Eternal War God',
'Massive Fortune', 'Mythical Legend', 'Only One', 'Myriad Swords Return to the Origin', 'Bloodthirsty Madman', 'King of the Deep Sea', 'Fantasy City', 'Chosen One'
];
return { adjectives, nouns }
},
previewCodeFile: function (options) { previewCodeFile: function (options) {
let { file, max, callback } = options; let { file, max, callback } = options;

View File

@@ -18,15 +18,18 @@ let useIndexedDb = (window.localStorage.getItem("tl-rtc-file-receive-file-use-in
let useFixedRoom = window.localStorage.getItem("tl-rtc-file-use-fixed-room") || ""; let useFixedRoom = window.localStorage.getItem("tl-rtc-file-use-fixed-room") || "";
// 是否开启局域网房间被发现 // 是否开启局域网房间被发现
let useLocalNetworkRoomShare = (window.localStorage.getItem("tl-rtc-file-use-local-network-room-share") || "true") === 'true'; let useLocalNetworkRoomShare = (window.localStorage.getItem("tl-rtc-file-use-local-network-room-share") || "true") === 'true';
// 是否关闭消息红点 // 是否开启消息红点
let useMessageDot = (window.localStorage.getItem("tl-rtc-file-use-message-dot") || "true") === 'true'; let useMessageDot = (window.localStorage.getItem("tl-rtc-file-use-message-dot") || "true") === 'true';
// 是否开启浏览器系统消息通知
let useWebMsgNotify = (window.localStorage.getItem("tl-rtc-file-use-web-msg-notify") || "true") === 'true';
axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => { axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
let { data : { let { data : {
code, login, code, login,
token : userToken, token : userToken,
avatar, avatar,
username username,
subscribeNotify
} } = await axios.get("/api/login/state"); } } = await axios.get("/api/login/state");
let resData = initData.data; let resData = initData.data;
@@ -88,9 +91,10 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
isCameraEnabled : true, //音视频场景下自己的摄像头是否开启 isCameraEnabled : true, //音视频场景下自己的摄像头是否开启
isAudioEnabled : true, //音视频场景下自己的麦克风是否开启 isAudioEnabled : true, //音视频场景下自己的麦克风是否开启
isLoudspeakerEnabled : true, //音视频场景下自己的扬声器是否开启 isLoudspeakerEnabled : true, //音视频场景下自己的扬声器是否开启
isCloseLogs : false, //是否关闭日志, 默认开启日志 useLogOutput : true, //是否输出日志, 默认输出日志
chatCommFilterGood : false, // 是否展示公共聊天频道的精选消息 chatCommFilterGood : false, // 是否展示公共聊天频道的精选消息
chatCommFilterTop : false, // 是否展示公共聊天频道的置顶消息 chatCommFilterTop : false, // 是否展示公共聊天频道的置顶消息
useWebMsgNotify: useWebMsgNotify, //是否开启网页消息通知
useMessageDot : useMessageDot, //是否关闭消息提示红点, 默认开启 useMessageDot : useMessageDot, //是否关闭消息提示红点, 默认开启
useFixedRoom: useFixedRoom, //是否使用自定义房间号,持久化,后续自动进入房间 useFixedRoom: useFixedRoom, //是否使用自定义房间号,持久化,后续自动进入房间
useIndexedDb : useIndexedDb, // 是否需要将文件保存到indexedDb useIndexedDb : useIndexedDb, // 是否需要将文件保存到indexedDb
@@ -126,7 +130,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
nickName: "", //本人名称 nickName: "", //本人名称
socketId: 0, //本人的id socketId: 0, //本人的id
roomId: "10086", //房间号 roomId: "10086", //房间号
roomType : "file", //房间类型 video, live, audio ,file roomType : "file", //房间类型 video, live, audio ,file, password
liveShareMode : "video", //直播类型 video, screen liveShareMode : "video", //直播类型 video, screen
liveShareRole : "owner", //直播身份 owner: 主播, viwer:观众 liveShareRole : "owner", //直播身份 owner: 主播, viwer:观众
codeId: "", //取件码 codeId: "", //取件码
@@ -135,8 +139,9 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
remoteMap: {}, //远程连接map remoteMap: {}, //远程连接map
switchData: {}, //配置开关数据 switchData: {}, //配置开关数据
chatRoomSingleSocketId : "", //私聊对方的socketId chatRoomSingleSocketId : "", //私聊对方的socketId
avatar : avatar, //用户登录头像 avatar : avatar || "/image/44826979.png", //用户登录头像
username : username, //用户登录昵称 username : username || " -- ", //用户登录昵称
subscribeNotify : subscribeNotify || false, //是否已经订阅过网站
chunkSize: 16 * 1024, // 一块16kb 最大应该可以设置到64kb chunkSize: 16 * 1024, // 一块16kb 最大应该可以设置到64kb
currentSendAllSize: 0, // 统计发送文件总大小 (流量统计) currentSendAllSize: 0, // 统计发送文件总大小 (流量统计)
@@ -167,7 +172,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
popUpList: [], //消息数据 popUpList: [], //消息数据
localNetRoomList : [], //局域网房间列表 localNetRoomList : [], //局域网房间列表
preMouseMove : {}, //上一次鼠标移动的事件 preMouseMove : {}, //上一次鼠标移动的事件
ips: [], // 记录ip列表检测是否支持p2p ips: [], // 记录ip列表
popUpMsgDom : [], // 消息弹窗dom popUpMsgDom : [], // 消息弹窗dom
videoDeviceList : [], //摄像头设备列表 videoDeviceList : [], //摄像头设备列表
audioDeviceList : [], //麦克风设备列表 audioDeviceList : [], //麦克风设备列表
@@ -249,7 +254,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
} }
}, },
roomTypeName: function(){ roomTypeName: function(){
return window.tlrtcfile.getRoomTypeZh(this.roomType) return this.lang[window.tlrtcfile.getRoomType(this.roomType)]
}, },
canSaveToIndexedDb: function(){ canSaveToIndexedDb: function(){
return localforage.supports(localforage.INDEXEDDB) return localforage.supports(localforage.INDEXEDDB)
@@ -330,6 +335,38 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}, 500); }, 500);
} }
}); });
document.querySelector("#tl-rtc-file-user-log").addEventListener('click', async () => {
layer.msg(that.lang.load_history_oper_log_succ)
});
document.querySelector("#tl-rtc-file-user-subscribe").addEventListener('click', async () => {
if(that.subscribeNotify){
layer.msg(that.lang.alreay_subscribe)
return
}
layer.prompt({
formType: 0,
title: that.lang.email_subscribe_website_notify,
btn : [that.lang.confirm, that.lang.cancel],
value: "",
maxlength : 100,
}, function (value, index, elem) {
if(!tlrtcfile.isEmail(value)){
layer.msg(that.lang.email_format_error)
return
}
that.socket.emit("subscribeNofity", {
room: that.roomId,
email : value
})
layer.close(index);
return false
});
});
}, },
content: ` content: `
<div class="tl-rtc-file-login-user"> <div class="tl-rtc-file-login-user">
@@ -338,14 +375,26 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
<img src="${that.avatar}" alt="头像"> <img src="${that.avatar}" alt="头像">
</div> </div>
<div class="tl-rtc-file-login-user-info-name"> <div class="tl-rtc-file-login-user-info-name">
微信昵称: ${that.username} ${that.lang.wchat_nickname}: ${that.username}
</div> </div>
<div class="tl-rtc-file-login-user-info-name"> <div class="tl-rtc-file-login-user-info-name">
个人昵称: ${that.nickName} ${that.lang.website_nickname}: ${that.nickName}
</div>
<div style="text-align: center;">
<div class="tl-rtc-file-user-oper">
<svg class="icon" aria-hidden="true" id="tl-rtc-file-user-log">
<use xlink:href="#icon-rtc-file-qunfengcaozuojilu"></use>
</svg>
<svg class="icon" aria-hidden="true" id="tl-rtc-file-user-subscribe">
<use xlink:href="#icon-rtc-file-dingyue"></use>
</svg>
</div>
</div> </div>
</div> </div>
<div class="tl-rtc-file-logout"> <div class="tl-rtc-file-login-user-btn">
<button id="tl-rtc-file-logout-btn" type="button" class="layui-btn">退出登录</button> <div class="tl-rtc-file-logout">
<button id="tl-rtc-file-logout-btn" type="button" class="layui-btn">${that.lang.logout}</button>
</div>
</div> </div>
</div> </div>
` `
@@ -450,6 +499,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
layer.prompt({ layer.prompt({
formType: 0, formType: 0,
title: that.lang.changeNickName, title: that.lang.changeNickName,
btn : [that.lang.confirm, that.lang.cancel],
value: "", value: "",
maxlength : 10, maxlength : 10,
}, function (value, index, elem) { }, function (value, index, elem) {
@@ -828,6 +878,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
layer.prompt({ layer.prompt({
formType: 0, formType: 0,
title: this.lang.please_enter_code, title: this.lang.please_enter_code,
btn : [that.lang.confirm, that.lang.cancel],
value: this.codeId, value: this.codeId,
}, function (value, index, elem) { }, function (value, index, elem) {
if(value.length < 30 || tlrtcfile.containSymbol(value) || tlrtcfile.containChinese(value)){ if(value.length < 30 || tlrtcfile.containSymbol(value) || tlrtcfile.containChinese(value)){
@@ -893,6 +944,21 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
that.sendChatingRoomSingle(); that.sendChatingRoomSingle();
}) })
let remoteRtc = that.getRemoteInfo(that.chatRoomSingleSocketId);
let receiveChatRoomSingleList = [];
if(remoteRtc && remoteRtc.receiveChatRoomSingleList){
receiveChatRoomSingleList = remoteRtc.receiveChatRoomSingleList;
}
receiveChatRoomSingleList.forEach((item, index) => {
const id = "tl-rtc-file-content-copy" + index;
if(!document.getElementById(id)) return;
document.getElementById(id).addEventListener('click', function () {
tlrtcfile.copyTxt(id, item.content, function () {
layer.msg(that.lang.copy_success)
});
that.addUserLogs(that.lang.copy_success);
});
})
}, },
cancel: function (index, layero) { cancel: function (index, layero) {
this.chatRoomSingleSocketId = ""; this.chatRoomSingleSocketId = "";
@@ -910,6 +976,9 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
<small>${this.lang.user}: <b>{{info.nickName}}</b></small> - <small>${this.lang.user}: <b>{{info.nickName}}</b></small> -
<small>id: <b>{{info.socketId}}</b></small> - <small>id: <b>{{info.socketId}}</b></small> -
<small>${this.lang.time}: <b>{{info.timeAgo}}</b></small> <small>${this.lang.time}: <b>{{info.timeAgo}}</b></small>
<svg class="icon" aria-hidden="true" style="margin-left: 5px;cursor: pointer;" id="tl-rtc-file-content-copy{{index}}">
<use xlink:href="#icon-rtc-file-fuzhi"></use>
</svg>
</div> </div>
<div style="margin-top: 5px;word-break: break-all;width: 90%;"> <div style="margin-top: 5px;word-break: break-all;width: 90%;">
<b style="font-weight: bold; font-size: large;">{{- info.content }}</b> <b style="font-weight: bold; font-size: large;">{{- info.content }}</b>
@@ -1053,8 +1122,8 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
2 : 1800, // 队列只有两个弹窗排队时, 弹窗悬停时间1800ms 2 : 1800, // 队列只有两个弹窗排队时, 弹窗悬停时间1800ms
5 : 1600, 5 : 1600,
8 : 1300, 8 : 1300,
10 : 900, 10 : 500,
20 : 700 20 : 200
}; };
//轮训是否有弹窗排队中 //轮训是否有弹窗排队中
if(!data){ if(!data){
@@ -1245,7 +1314,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
// 设置昵称 // 设置昵称
setNickName: function(){ setNickName: function(){
if(window.tlrtcfile.genNickName){ if(window.tlrtcfile.genNickName){
this.nickName = window.tlrtcfile.genNickName(); this.nickName = window.tlrtcfile.genNickName(this.langMode);
} }
}, },
// 打开公告 // 打开公告
@@ -1496,15 +1565,18 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
let that = this; let that = this;
layer.prompt({ layer.prompt({
formType: 0, formType: 0,
title: this.lang.please_enter_password title: this.lang.please_enter_password_room_num,
btn : [that.lang.confirm, that.lang.cancel],
}, function (value, index, elem) { }, function (value, index, elem) {
that.roomId = value; that.roomId = value;
layer.close(index); layer.close(index);
that.isPasswordRoom = !that.isPasswordRoom; that.isPasswordRoom = !that.isPasswordRoom;
that.roomType = "password";
layer.prompt({ layer.prompt({
formType: 1, formType: 1,
title: that.lang.please_enter_password title: that.lang.please_enter_password,
btn : [that.lang.confirm, that.lang.cancel],
}, function (value, index, elem) { }, function (value, index, elem) {
that.createPasswordRoom(value); that.createPasswordRoom(value);
layer.close(index); layer.close(index);
@@ -1560,6 +1632,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}else{ }else{
layer.prompt({ layer.prompt({
formType: 0, formType: 0,
btn : [that.lang.confirm, that.lang.cancel],
title: that.lang.please_enter_video_call_room_num title: that.lang.please_enter_video_call_room_num
}, function (value, index, elem) { }, function (value, index, elem) {
that.roomId = value; that.roomId = value;
@@ -1624,6 +1697,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}else{ }else{
layer.prompt({ layer.prompt({
formType: 0, formType: 0,
btn : [that.lang.confirm, that.lang.cancel],
title: this.lang.please_enter_screen_sharing_room_num, title: this.lang.please_enter_screen_sharing_room_num,
}, function (value, index, elem) { }, function (value, index, elem) {
that.roomId = value; that.roomId = value;
@@ -1848,6 +1922,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
layer.prompt({ layer.prompt({
formType: 0, formType: 0,
title: this.lang.please_enter_audio_sharing_room_num, title: this.lang.please_enter_audio_sharing_room_num,
btn : [that.lang.confirm, that.lang.cancel],
}, function (value, index, elem) { }, function (value, index, elem) {
that.roomId = value; that.roomId = value;
that.createMediaRoom("audio"); that.createMediaRoom("audio");
@@ -2040,6 +2115,17 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
document.getElementById("tl-sendChatingComm").addEventListener('click',function(){ document.getElementById("tl-sendChatingComm").addEventListener('click',function(){
that.sendChatingComm(); that.sendChatingComm();
}) })
that.receiveChatCommList.forEach((item, index) => {
const id = "tl-rtc-file-content-copy" + index;
if(!document.getElementById(id)) return;
document.getElementById(id).addEventListener('click', function () {
tlrtcfile.copyTxt(id, item.msg, function () {
layer.msg(that.lang.copy_success)
});
that.addUserLogs(that.lang.copy_success);
});
})
}, },
content: ` content: `
<div class="layui-col-sm12" style="padding: 15px;"> <div class="layui-col-sm12" style="padding: 15px;">
@@ -2058,7 +2144,10 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
{{# } }} {{# } }}
<small>${this.lang.room}: <b>{{info.room}}</b></small> - <small>${this.lang.room}: <b>{{info.room}}</b></small> -
<small>${this.lang.user}: <b>{{info.socketId}}</b></small> - <small>${this.lang.user}: <b>{{info.socketId}}</b></small> -
<small>${this.lang.time}: <b>{{info.timeAgo}}</b></small> <small>${this.lang.time}: <b>{{info.timeAgo}}</b></small>
<svg class="icon" aria-hidden="true" style="margin-left: 5px;cursor: pointer;" id="tl-rtc-file-content-copy{{index}}">
<use xlink:href="#icon-rtc-file-fuzhi"></use>
</svg>
{{# if(info.admin) { }} {{# if(info.admin) { }}
<svg class="icon" aria-hidden="true" style="width: 24px;height: 24px;color:#1e9fff;"> <svg class="icon" aria-hidden="true" style="width: 24px;height: 24px;color:#1e9fff;">
<use xlink:href="#icon-rtc-file-zhuip"></use> <use xlink:href="#icon-rtc-file-zhuip"></use>
@@ -2260,6 +2349,17 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
document.getElementById("tl-sendChatingRoom").addEventListener("click",function(){ document.getElementById("tl-sendChatingRoom").addEventListener("click",function(){
that.sendChatingRoom(); that.sendChatingRoom();
}) })
that.receiveChatRoomList.forEach((item, index) => {
const id = "tl-rtc-file-content-copy" + index;
if(!document.getElementById(id)) return;
document.getElementById(id).addEventListener('click', function () {
tlrtcfile.copyTxt(id, item.content, function () {
layer.msg(that.lang.copy_success)
});
that.addUserLogs(that.lang.copy_success);
});
})
}, },
content: ` content: `
<div class="layui-col-sm12" style="padding: 15px;"> <div class="layui-col-sm12" style="padding: 15px;">
@@ -2283,6 +2383,9 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
{{# } }} {{# } }}
<small>id: <b>{{info.socketId}}</b></small> - <small>id: <b>{{info.socketId}}</b></small> -
<small>${this.lang.time}: <b>{{info.timeAgo}}</b></small> <small>${this.lang.time}: <b>{{info.timeAgo}}</b></small>
<svg class="icon" aria-hidden="true" style="margin-left: 5px;cursor: pointer;" id="tl-rtc-file-content-copy{{index}}">
<use xlink:href="#icon-rtc-file-fuzhi"></use>
</svg>
</div> </div>
<div style="margin-top: 5px;word-break: break-all;width: 90%;"> <div style="margin-top: 5px;word-break: break-all;width: 90%;">
<b style="font-weight: bold; font-size: large;"> {{- info.content}} </b> <b style="font-weight: bold; font-size: large;"> {{- info.content}} </b>
@@ -2454,7 +2557,8 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
langMode : this.langMode, langMode : this.langMode,
ua: this.isMobile ? 'mobile' : 'pc', ua: this.isMobile ? 'mobile' : 'pc',
network : this.network, network : this.network,
localNetRoom : this.useLocalNetworkRoomShare localNetRoom : this.useLocalNetworkRoomShare,
ips : this.ips,
}); });
this.isJoined = true; this.isJoined = true;
this.addPopup({ this.addPopup({
@@ -2486,7 +2590,8 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
ua: this.isMobile ? 'mobile' : 'pc', ua: this.isMobile ? 'mobile' : 'pc',
network : this.network, network : this.network,
liveShareRole : this.liveShareRole, liveShareRole : this.liveShareRole,
localNetRoom : this.useLocalNetworkRoomShare localNetRoom : this.useLocalNetworkRoomShare,
ips : this.ips,
}); });
this.isJoined = true; this.isJoined = true;
this.roomType = type; this.roomType = type;
@@ -2524,7 +2629,8 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
langMode : this.langMode, langMode : this.langMode,
ua: this.isMobile ? 'mobile' : 'pc', ua: this.isMobile ? 'mobile' : 'pc',
network : this.network, network : this.network,
localNetRoom : this.useLocalNetworkRoomShare localNetRoom : this.useLocalNetworkRoomShare,
ips : this.ips,
}); });
this.isJoined = true; this.isJoined = true;
this.addPopup({ this.addPopup({
@@ -3365,14 +3471,6 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
sdp: event.candidate.candidate sdp: event.candidate.candidate
}; };
this.socket.emit('candidate', message); this.socket.emit('candidate', message);
let ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/;
let match = ipRegex.exec(event.candidate.candidate);
let ipAddress = match && Array.isArray(match) && match.length > 0 ? match[1] : "unknow";
if (ipAddress !== 'unknow') {
this.ips.push(ipAddress);
}
this.addSysLogs("IP: " + ipAddress);
} }
}, },
// offer // offer
@@ -3418,7 +3516,22 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
let that = this; let that = this;
this.socket.on("localNetRoom", data => { this.socket.on("localNetRoom", data => {
that.localNetRoomList = data.list || []; const { mode, list } = data;
if(mode === 'connect'){
that.localNetRoomList = data.list || [];
}else if(mode === 'join'){
let newList = that.localNetRoomList.filter(item => { return item.owner !== list[0].owner });
newList.push(list[0]);
that.localNetRoomList = newList;
}else if(mode === 'exit'){
let newList = that.localNetRoomList.filter(item => { return item.owner !== list[0].owner });
if(list[0].count === 0){ //退出后房间没人了,清理
that.localNetRoomList = newList;
}else{ // 退出后房间还有人,更新
newList.push(list[0]);
that.localNetRoomList = newList;
}
}
if(that.localNetRoomList.length === 0 && that.showLocalNetRoom){ if(that.localNetRoomList.length === 0 && that.showLocalNetRoom){
that.clickLocalNetRooms(true); that.clickLocalNetRooms(true);
} }
@@ -4032,6 +4145,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
layer.prompt({ layer.prompt({
formType: 1, formType: 1,
title: that.lang.please_enter, title: that.lang.please_enter,
btn : [that.lang.confirm, that.lang.cancel],
}, function (value, index, elem) { }, function (value, index, elem) {
that.socket.emit('manageConfirm', { that.socket.emit('manageConfirm', {
room: that.roomId, room: that.roomId,
@@ -4041,6 +4155,11 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}); });
}); });
//关闭音视频
this.socket.on('subscribeNofity', function (data) {
layer.msg(that.lang.subscribe_website_notify_succ)
});
this.socket.on('manage', function (data) { this.socket.on('manage', function (data) {
if (data.socketId !== that.socketId) { if (data.socketId !== that.socketId) {
layer.msg(that.lang.illegal_event) layer.msg(that.lang.illegal_event)
@@ -4168,8 +4287,8 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}) })
}) })
document.getElementById("closeLogs").addEventListener('click', function(){ document.getElementById("logOutput").addEventListener('click', function(){
that.closeLogs(); that.logOutput();
}) })
document.getElementById("coffee").addEventListener('click', function(){ document.getElementById("coffee").addEventListener('click', function(){
@@ -4199,6 +4318,10 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
document.getElementById("fileTransferSettingHelp").addEventListener('click', function(){ document.getElementById("fileTransferSettingHelp").addEventListener('click', function(){
that.settingHelp(); that.settingHelp();
}) })
document.getElementById("webMsgNotify").addEventListener('click', function(){
that.webMsgNotify();
})
}, },
content: ` content: `
<div class="setting-main layui-carousel" id="tl-rtc-file-setting-info"> <div class="setting-main layui-carousel" id="tl-rtc-file-setting-info">
@@ -4340,13 +4463,13 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
</li> </li>
<li class="layui-col-xs4"> <li class="layui-col-xs4">
<a title="${this.lang.log}"> <a title="${this.lang.log}">
<svg class="icon" aria-hidden="true" id="closeLogs"> <svg class="icon" aria-hidden="true" id="logOutput">
<use xlink:href="#icon-rtc-file-rizhiguanli"></use> <use xlink:href="#icon-rtc-file-rizhiguanli"></use>
</svg> </svg>
<svg id="closeLogsOpen" class="icon settingOpenIcon" aria-hidden="true" style="${this.isCloseLogs ? 'display:none;' : ''}"> <svg id="logOutputOpen" class="icon settingOpenIcon" aria-hidden="true" style="${this.useLogOutput ? '' : 'display:none;'}">
<use xlink:href="#icon-rtc-file-zhengque"></use> <use xlink:href="#icon-rtc-file-zhengque"></use>
</svg> </svg>
<svg id="closeLogsClose" class="icon settingCloseIcon" aria-hidden="true" style="${!this.isCloseLogs ? 'display:none;' : ''}"> <svg id="logOutputClose" class="icon settingCloseIcon" aria-hidden="true" style="${!this.useLogOutput ? '' : 'display:none;'}">
<use xlink:href="#icon-rtc-file-cuowu"></use> <use xlink:href="#icon-rtc-file-cuowu"></use>
</svg> </svg>
<cite>${this.lang.log}</cite> <cite>${this.lang.log}</cite>
@@ -4394,6 +4517,20 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
<cite>${this.lang.local_network_room_share}</cite> <cite>${this.lang.local_network_room_share}</cite>
</a> </a>
</li> </li>
<li class="layui-col-xs4">
<a title="${this.lang.web_msg_notify}">
<svg class="icon" aria-hidden="true" id="webMsgNotify">
<use xlink:href="#icon-rtc-file-tongzhi"></use>
</svg>
<svg id="webMsgNotifyOpen" class="icon settingOpenIcon" aria-hidden="true" style="${this.useWebMsgNotify ? '' : 'display:none;'}">
<use xlink:href="#icon-rtc-file-zhengque"></use>
</svg>
<svg id="webMsgNotifyClose" class="icon settingCloseIcon" aria-hidden="true" style="${!this.useWebMsgNotify ? '' : 'display:none;'}">
<use xlink:href="#icon-rtc-file-cuowu"></use>
</svg>
<cite>${this.lang.web_msg_notify}</cite>
</a>
</li>
</ul> </ul>
</div> </div>
@@ -4466,24 +4603,23 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
layer.msg(this.lang.auto_join_fixed_room + ": " + this.useFixedRoom) layer.msg(this.lang.auto_join_fixed_room + ": " + this.useFixedRoom)
}, },
// 是否关闭日志输出 // 是否关闭日志输出
closeLogs: function(){ logOutput: function(){
this.isCloseLogs = !this.isCloseLogs; this.useLogOutput = !this.useLogOutput;
if (this.isCloseLogs) { if (this.useLogOutput) {
layer.msg(`${this.lang.logs_switch}${this.lang.on}`) $("#logOutputOpen").css("display", "inline");
$("#closeLogsOpen").css("display", "inline"); $("#logOutputClose").css("display", "none");
$("#closeLogsClose").css("display", "none");
} else { } else {
layer.msg(`${this.lang.logs_switch}${this.lang.off}`) $("#logOutputOpen").css("display", "none");
$("#closeLogsOpen").css("display", "none"); $("#logOutputClose").css("display", "inline");
$("#closeLogsClose").css("display", "inline");
} }
$("#closeLogs").removeClass("layui-anim-rotate") layer.msg(`${this.lang.logs_switch}${this.useLogOutput ? this.lang.on : this.lang.off}`)
$("#logOutput").removeClass("layui-anim-rotate")
setTimeout(() => { setTimeout(() => {
$("#closeLogs").addClass("layui-anim-rotate") $("#logOutput").addClass("layui-anim-rotate")
}, 50) }, 50)
}, },
// ai对话上下文开关 // ai对话上下文开关
@@ -4507,43 +4643,64 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
$("#aiContext").addClass("layui-anim-rotate") $("#aiContext").addClass("layui-anim-rotate")
}, 50) }, 50)
}, },
// 是否关闭消息红点提示 // 是否开启消息红点提示
messageDot : function(){ messageDot : function(){
this.useMessageDot = !this.useMessageDot;
if (this.useMessageDot) { if (this.useMessageDot) {
window.localStorage.setItem("tl-rtc-file-use-message-dot", false)
layer.msg(`${this.lang.messgae_dot_switch}${this.lang.off}`)
$("#messageDotOpen").css("display", "none");
$("#messageDotClose").css("display", "inline");
} else {
window.localStorage.setItem("tl-rtc-file-use-message-dot", true) window.localStorage.setItem("tl-rtc-file-use-message-dot", true)
layer.msg(`${this.lang.messgae_dot_switch}${this.lang.on}`)
$("#messageDotOpen").css("display", "inline"); $("#messageDotOpen").css("display", "inline");
$("#messageDotClose").css("display", "none"); $("#messageDotClose").css("display", "none");
} else {
window.localStorage.setItem("tl-rtc-file-use-message-dot", false)
$("#messageDotOpen").css("display", "none");
$("#messageDotClose").css("display", "inline");
} }
this.useMessageDot = !this.useMessageDot; layer.msg(`${this.lang.messgae_dot_switch}${this.useMessageDot ? this.lang.on : this.lang.off}`)
$("#messageDot").removeClass("layui-anim-rotate") $("#messageDot").removeClass("layui-anim-rotate")
setTimeout(() => { setTimeout(() => {
$("#messageDot").addClass("layui-anim-rotate") $("#messageDot").addClass("layui-anim-rotate")
}, 50) }, 50)
}, },
// 是否开启局域网房间分享 // 开启系统消息提示弹窗
localNetworkRoomShare : function(){ webMsgNotify: function(){
if(this.useLocalNetworkRoomShare){ this.useWebMsgNotify = !this.useWebMsgNotify;
window.localStorage.setItem("tl-rtc-file-use-local-network-room-share", false)
layer.msg(`${this.lang.local_network_room_share}${this.lang.off}`) if (this.useWebMsgNotify) {
$("#localNetworkRoomShareOpen").css("display", "none"); window.localStorage.setItem("tl-rtc-file-use-web-message-notify", true)
$("#localNetworkRoomShareClose").css("display", "inline"); $("#webMsgNotifyOpen").css("display", "inline");
}else{ $("#webMsgNotifyClose").css("display", "none");
window.localStorage.setItem("tl-rtc-file-use-local-network-room-share", true) } else {
layer.msg(`${this.lang.local_network_room_share}${this.lang.on}`) window.localStorage.setItem("tl-rtc-file-use-web-message-notify", false)
$("#localNetworkRoomShareOpen").css("display", "inline"); $("#webMsgNotifyOpen").css("display", "none");
$("#localNetworkRoomShareClose").css("display", "none"); $("#webMsgNotifyClose").css("display", "inline");
} }
layer.msg(`${this.lang.web_msg_notify}${this.useWebMsgNotify ? this.lang.on : this.lang.off}`)
$("#webMsgNotify").removeClass("layui-anim-rotate")
setTimeout(() => {
$("#webMsgNotify").addClass("layui-anim-rotate")
}, 50)
},
// 是否开启局域网房间分享
localNetworkRoomShare : function(){
this.useLocalNetworkRoomShare = !this.useLocalNetworkRoomShare; this.useLocalNetworkRoomShare = !this.useLocalNetworkRoomShare;
if(this.useLocalNetworkRoomShare){
window.localStorage.setItem("tl-rtc-file-use-local-network-room-share", true)
$("#localNetworkRoomShareOpen").css("display", "inline");
$("#localNetworkRoomShareClose").css("display", "none");
}else{
window.localStorage.setItem("tl-rtc-file-use-local-network-room-share", false)
$("#localNetworkRoomShareOpen").css("display", "none");
$("#localNetworkRoomShareClose").css("display", "inline");
}
layer.msg(`${this.lang.local_network_room_share}${this.useLocalNetworkRoomShare ? this.lang.on : this.lang.off}`)
$("#localNetworkRoomShare").removeClass("layui-anim-rotate") $("#localNetworkRoomShare").removeClass("layui-anim-rotate")
setTimeout(() => { setTimeout(() => {
$("#localNetworkRoomShare").addClass("layui-anim-rotate") $("#localNetworkRoomShare").addClass("layui-anim-rotate")
@@ -4567,6 +4724,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
formType: 0, formType: 0,
value: '', value: '',
title: that.lang.fixed_room, title: that.lang.fixed_room,
btn : [that.lang.confirm, that.lang.cancel],
}, function (value, index, elem) { }, function (value, index, elem) {
if (!that.switchData.allowChinese && window.tlrtcfile.containChinese(value)) { if (!that.switchData.allowChinese && window.tlrtcfile.containChinese(value)) {
layer.msg(that.lang.room_num_no_zh) layer.msg(that.lang.room_num_no_zh)
@@ -4642,6 +4800,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
formType: 0, formType: 0,
value: 'wss://', value: 'wss://',
title: that.lang.input_custom_ws_url, title: that.lang.input_custom_ws_url,
btn : [that.lang.confirm, that.lang.cancel],
}, function (value, index, elem) { }, function (value, index, elem) {
if(!/^wss?:\/\/[^\s/$.?#].[^\s]*$/.test(value)){ if(!/^wss?:\/\/[^\s/$.?#].[^\s]*$/.test(value)){
layer.msg(that.lang.ws_url_error) layer.msg(that.lang.ws_url_error)
@@ -4685,11 +4844,6 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
window.location.reload() window.location.reload()
}, 300); }, 300);
}, },
// 中继信息提示
useTurnMsg: function () {
layer.msg(this.lang.relay_on)
this.addUserLogs(this.lang.relay_on)
},
// 当前网络状态 // 当前网络状态
networkMsg: function () { networkMsg: function () {
layer.msg(this.lang.current_network + (this.network !== 'wifi' ? this.lang.mobile_data : this.network)) layer.msg(this.lang.current_network + (this.network !== 'wifi' ? this.lang.mobile_data : this.network))
@@ -4712,7 +4866,7 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}, },
// 记录日志 // 记录日志
addLogs: function (msg, type) { addLogs: function (msg, type) {
if(this.isCloseLogs){ if(!this.useLogOutput){
return return
} }
if (this.logs.length > this.maxLogCount) { if (this.logs.length > this.maxLogCount) {
@@ -4792,13 +4946,8 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
tlrtcfile.getQrCode("tl-rtc-file-room-share-image", content) tlrtcfile.getQrCode("tl-rtc-file-room-share-image", content)
} }
document.querySelector("#shareUrl").setAttribute("data-clipboard-text", content); tlrtcfile.copyTxt("shareUrl", content, function () {
let clipboard = new ClipboardJS('#shareUrl'); layer.msg(that.lang.copy_room_link)
clipboard.on('success', function (e) {
e.clearSelection();
setTimeout(() => {
layer.msg(that.lang.copy_room_link)
}, 500);
}); });
that.addUserLogs(that.lang.copy_room_link); that.addUserLogs(that.lang.copy_room_link);
}, },
@@ -5274,6 +5423,37 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
}, 50) }, 50)
} }
}, },
// 局域网房间功能开启进行的的ip上报
localNetRoomIpReport: async function () {
let that = this;
await new Promise((resolve, reject) => {
const pc = new RTCPeerConnection(that.config);
pc.createDataChannel('report');
pc.createOffer().then(offer => pc.setLocalDescription(offer)).catch(reject);
pc.addEventListener("icegatheringstatechange", (ev) => {
if(pc.iceGatheringState === 'complete'){
resolve(true)
}
});
pc.onicecandidate = (e) => {
if (e.candidate) {
if(e.candidate.type !== 'relay'){
let alreadyHas = that.ips.filter(item=>{
return item.address === e.candidate.address;
}).length > 0;
if(!alreadyHas){
that.ips.push({
ipType : e.candidate.type,
address : e.candidate.address,
protocol : e.candidate.protocol,
})
}
}
}
};
});
this.socket.emit("localNetRoom", { ips : this.ips })
},
// 自动监听窗口变化更新css // 自动监听窗口变化更新css
reCaculateWindowSize: function () { reCaculateWindowSize: function () {
this.clientWidth = document.body.clientWidth; this.clientWidth = document.body.clientWidth;
@@ -5614,6 +5794,10 @@ axios.get("/api/comm/initData?turn="+useTurn, {}).then(async (initData) => {
this.loadVConsoleJs(); this.loadVConsoleJs();
this.addSysLogs(this.lang.debug_init_done); this.addSysLogs(this.lang.debug_init_done);
this.addSysLogs(this.lang.local_network_room_report_init);
this.localNetRoomIpReport();
this.addSysLogs(this.lang.local_network_room_report_init_done);
this.addSysLogs(this.lang.current_relay_status + (this.useTurn ? this.lang.on : this.lang.off)) this.addSysLogs(this.lang.current_relay_status + (this.useTurn ? this.lang.on : this.lang.off))
} }
}); });

View File

@@ -413,8 +413,51 @@ const local_lang = {
"webrtc_ice_state" : "webrtc state", "webrtc_ice_state" : "webrtc state",
"ip" : "IP", "ip" : "IP",
"online_count" : "Online count", "online_count" : "Online count",
"load_history_oper_log_succ" : "Load histroy oper log list successfully",
"subscribe_website_notify_succ" : "Subscribe website notify successfully",
"wchat_nickname" : "Wxchat nickname",
"website_nickname" : "Website nickname",
"logout" : "Logout",
"email_subscribe" : "Email subscribe",
"email_format_error" : "Email format error",
"email_subscribe_website_notify" : "Email subscribe website notify",
"alreay_subscribe" : "Alreay subscribe website notify",
"copy_success" : "Copy success",
"web_msg_notify" : "Web msg notify",
"please_enter_password_room_num" : "Please enter the password room number",
"file_room_type" : "File room type",
"live_room_type" : "Live room type",
"video_room_type" : "Video room type",
"screen_room_type" : "Screen room type",
"password_room_type" : "Password room type",
"audio_room_type" : "Audio room type",
"system_room_type" : "System room type",
"unknown_room_type" : "Unknown room type",
"local_network_room_report_init" : "Local network room report init",
"local_network_room_report_init_done" : "Local network room report init done",
}, },
"zh": { "zh": {
"local_network_room_report_init" : "局域网房间上报初始化",
"local_network_room_report_init_done" : "局域网房间上报初始化完成",
"file_room_type" : "文件房间",
"live_room_type" : "直播房间",
"video_room_type" : "音视频房间",
"screen_room_type" : "屏幕共享房间",
"password_room_type" : "密码房间",
"audio_room_type" : "语音连麦房间",
"system_room_type" : "系统房间",
"unknown_room_type" : "未知类型房间",
"web_msg_notify" : "系统通知",
"copy_success" : "复制成功",
"alreay_subscribe" : "您已订阅网站通知",
"email_subscribe_website_notify" : "邮件订阅网站通知",
"email_format_error" : "邮箱格式错误",
"email_subscribe" : "邮件订阅",
"logout" : "退出登录",
"website_nickname" : "网站昵称",
"wchat_nickname" : "微信昵称",
"subscribe_website_notify_succ" : "订阅网站通知成功",
"load_history_oper_log_succ" : "即将支持加载历史记录",
"question_answer" : "问答/建议反馈列表", "question_answer" : "问答/建议反馈列表",
"ip" : "IP", "ip" : "IP",
"online_count" : "在线人数", "online_count" : "在线人数",
@@ -680,6 +723,7 @@ const local_lang = {
"please_enter_code": "请输入取件码", "please_enter_code": "请输入取件码",
"please_enter_content": "请输入文本内容", "please_enter_content": "请输入文本内容",
"please_enter_live_room_num": "请输入直播房间号", "please_enter_live_room_num": "请输入直播房间号",
"please_enter_password_room_num" : "请输入密码房间号",
"please_enter_password": "请输入密码房间密码", "please_enter_password": "请输入密码房间密码",
"please_enter_right_code": "请输入正确的取件码", "please_enter_right_code": "请输入正确的取件码",
"please_enter_room_num": "请先填写房间号", "please_enter_room_num": "请先填写房间号",