Merge pull request 'yangjie' (#28) from yangjie into master
Reviewed-on: #28
This commit is contained in:
commit
d3fb9068c5
256
main.js
256
main.js
|
|
@ -14,6 +14,7 @@ const path = require('node:path')
|
|||
const fs = require('fs');
|
||||
const Registry = require('winreg');
|
||||
const { autoUpdater, CancellationToken } = require('electron-updater');
|
||||
const signalR = require('@microsoft/signalr');
|
||||
const cancellationToken = new CancellationToken()
|
||||
app.allowRendererProcessReuse = false;
|
||||
let mainWindow = null;
|
||||
|
|
@ -21,6 +22,7 @@ let childWindow = {}
|
|||
let isMaximized = false;
|
||||
let env;
|
||||
let regKey;
|
||||
let connection = null;
|
||||
|
||||
class AppWindow extends BrowserWindow {
|
||||
constructor(config) {
|
||||
|
|
@ -142,6 +144,220 @@ app.on('ready', () => {
|
|||
isMaximized = true;
|
||||
}
|
||||
});
|
||||
// socket
|
||||
ipcMain.handle('startSignalr', (event, user) => {
|
||||
startSignalr(user)
|
||||
});
|
||||
ipcMain.handle('offSignalr', (event) => {
|
||||
if (connection) {
|
||||
connection.off('ReceiveMessage');
|
||||
connection.off('Operation');
|
||||
connection.off('ForceExitRoom');
|
||||
connection.off('AllLeave');
|
||||
connection.off('ShowUser');
|
||||
connection.off('RefreshView');
|
||||
connection.off('UserJoined');
|
||||
connection.off('UserLeave');
|
||||
connection.off('OperAllMicr');
|
||||
connection.off('OperMicr');
|
||||
connection.off('OperCamera');
|
||||
connection.off('ManagerRefresh');
|
||||
connection.off('ApplyToSpeak');
|
||||
connection.off('Watch');
|
||||
connection.off('DriverList');
|
||||
connection.off('SetDriver');
|
||||
connection.off('ShowDriverList');
|
||||
}
|
||||
});
|
||||
ipcMain.handle('onStop', (event) => {
|
||||
if (connection) {
|
||||
mainWindow.webContents.send('changeLocalStorage', {
|
||||
isSignalr: false,
|
||||
});
|
||||
connection.off('Invitation');
|
||||
connection.off('ForceLogout');
|
||||
connection.stop()
|
||||
connection = ""
|
||||
}
|
||||
});
|
||||
ipcMain.handle('onInvoke', async (event, str, data) => {
|
||||
switch (str) {
|
||||
case 'sendChannelMsg':
|
||||
await connection.invoke(str, data.roomNum, data.msg)
|
||||
break;
|
||||
case 'sendOper':
|
||||
// 4:屏幕共享
|
||||
await connection.invoke(str, data.roomNum, data.type)
|
||||
break;
|
||||
case 'getDrivers':
|
||||
// 获取某个人的设备列表
|
||||
await connection.invoke(str, data.uid)
|
||||
break;
|
||||
case 'sendDrivers':
|
||||
// 发送设备列表给某个人
|
||||
await connection.invoke(str, data.uid, data.driversJsonString)
|
||||
break;
|
||||
case 'setDrivers':
|
||||
// 设置某个人的设备列表
|
||||
await connection.invoke(str, data.uid, data.driversJsonString)
|
||||
break;
|
||||
case 'joinChannel':
|
||||
// 设置某个人的设备列表
|
||||
await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera)
|
||||
break;
|
||||
case 'levelChannel':
|
||||
// 设置某个人的设备列表
|
||||
await connection.invoke(str, data.roomNum)
|
||||
break;
|
||||
}
|
||||
});
|
||||
ipcMain.handle('onOtherSignalr', (event) => {
|
||||
if (connection) {
|
||||
// 邀请
|
||||
connection.on("Invitation", (roomNum, roomName, InviterName) => {
|
||||
mainWindow.webContents.send('onOtherSignalr', {
|
||||
key: 'Invitation',
|
||||
roomNum, roomName, InviterName
|
||||
});
|
||||
});
|
||||
// 退出
|
||||
connection.on("ForceLogout", (msg) => {
|
||||
mainWindow.webContents.send('onOtherSignalr', {
|
||||
key: 'ForceLogout',
|
||||
msg
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
ipcMain.handle('onSignalr', (event) => {
|
||||
if (connection) {
|
||||
// 聊天
|
||||
connection.on("ReceiveMessage", (uid, userName, message, timestamp) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'ReceiveMessage',
|
||||
uid, message, userName, timestamp
|
||||
})
|
||||
});
|
||||
// 扩展操作
|
||||
connection.on("Operation", (type) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'Operation',
|
||||
type
|
||||
})
|
||||
});
|
||||
// 移出会议
|
||||
connection.on("ForceExitRoom", () => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'ForceExitRoom',
|
||||
})
|
||||
});
|
||||
// 全员离开房间
|
||||
connection.on("AllLeave", () => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'AllLeave',
|
||||
})
|
||||
});
|
||||
// 全员看他
|
||||
connection.on("ShowUser", (uid, uname, operUid, operUserName) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'ShowUser',
|
||||
uid,
|
||||
uname,
|
||||
operUid,
|
||||
operUserName,
|
||||
})
|
||||
});
|
||||
// 更新视图模式
|
||||
connection.on("RefreshView", (type) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'RefreshView',
|
||||
type
|
||||
})
|
||||
});
|
||||
// 用户加入频道回调
|
||||
connection.on("UserJoined", (user) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'UserJoined',
|
||||
user,
|
||||
})
|
||||
});
|
||||
// 用户退出频道回调
|
||||
connection.on("UserLeave", (uid) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'UserLeave',
|
||||
uid,
|
||||
})
|
||||
});
|
||||
// 所有用户开闭麦
|
||||
connection.on("OperAllMicr", (enableMicr, uid) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'OperAllMicr',
|
||||
enableMicr,
|
||||
uid
|
||||
})
|
||||
});
|
||||
// 用户关闭开启麦克风
|
||||
connection.on("OperMicr", (user, operUid) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'OperMicr',
|
||||
user,
|
||||
operUid
|
||||
})
|
||||
});
|
||||
// 用户开启关闭摄像头
|
||||
connection.on("OperCamera", (user, operUid) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'OperCamera',
|
||||
user,
|
||||
operUid
|
||||
})
|
||||
});
|
||||
// 发言人用户信息刷新
|
||||
connection.on("ManagerRefresh", (user, uid) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'ManagerRefresh',
|
||||
user,
|
||||
uid
|
||||
})
|
||||
});
|
||||
// 申请发言
|
||||
connection.on("ApplyToSpeak", (uid, uname) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'ApplyToSpeak',
|
||||
uid,
|
||||
uname
|
||||
})
|
||||
});
|
||||
// 管理员查看随机用户
|
||||
connection.on("Watch", (watchUids) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'Watch',
|
||||
watchUids
|
||||
})
|
||||
});
|
||||
// 设备列表
|
||||
connection.on("DriverList", (callerUid) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'DriverList',
|
||||
callerUid
|
||||
})
|
||||
});
|
||||
// 设置设备
|
||||
connection.on("SaveDriver", (driver) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'SaveDriver',
|
||||
driver
|
||||
})
|
||||
});
|
||||
// 显示设备列表
|
||||
connection.on("ShowDriverList", (driversJsonString) => {
|
||||
mainWindow.webContents.send('onSignalr', {
|
||||
key: 'ShowDriverList',
|
||||
driversJsonString
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
// 放大缩小退出窗口
|
||||
ipcMain.handle('setViewStatus', async (event, status) => {
|
||||
switch (status) {
|
||||
|
|
@ -170,6 +386,10 @@ app.on('ready', () => {
|
|||
ipcMain.handle('getIsMaximized', () => {
|
||||
return mainWindow.isMaximized();
|
||||
});
|
||||
// 获取app路径
|
||||
ipcMain.handle('getAppPath', () => {
|
||||
return app.getAppPath();
|
||||
});
|
||||
// 获取版本号
|
||||
ipcMain.handle('getVersion', () => {
|
||||
return app.getVersion();
|
||||
|
|
@ -490,3 +710,39 @@ function mainWindowCenter() {
|
|||
function mainWindowHide() {
|
||||
mainWindow.setPosition(-999999, -999999);
|
||||
}
|
||||
|
||||
const startSignalr = async (user) => {
|
||||
connection = new signalR.HubConnectionBuilder().withAutomaticReconnect()
|
||||
.withUrl(`${env === 'development' ? 'http://192.168.2.9:5192' : 'https://meeting-api.23544.com/pc'}/session-manage`, {
|
||||
skipNegotiation: true,
|
||||
transport: signalR.HttpTransportType.WebSockets,
|
||||
accessTokenFactory: () => user.token
|
||||
})
|
||||
.build();
|
||||
onStart()
|
||||
mainWindow.webContents.send('changeLocalStorage', {
|
||||
isSignalr: true,
|
||||
reconnect: true,
|
||||
});
|
||||
connection.onreconnected(async () => {
|
||||
mainWindow.webContents.send('changeLocalStorage', {
|
||||
reconnect: true,
|
||||
});
|
||||
});
|
||||
connection.onreconnecting(async () => {
|
||||
onStart()
|
||||
mainWindow.webContents.send('changeLocalStorage', {
|
||||
reconnect: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const onStart = async () => {
|
||||
if (connection) {
|
||||
if (connection.state !== signalR.HubConnectionState.Connected) {
|
||||
connection.start();
|
||||
} else {
|
||||
setTimeout(onStart, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
package.json
10
package.json
|
|
@ -91,7 +91,15 @@
|
|||
"directories": {
|
||||
"output": "electron"
|
||||
},
|
||||
"extraResources": [],
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "src/assets/virtualBackground",
|
||||
"to": "images",
|
||||
"filter": [
|
||||
"**/*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"installerIcon": "build/install.ico",
|
||||
|
|
|
|||
30
preload.js
30
preload.js
|
|
@ -1,6 +1,32 @@
|
|||
// // 在 preload 脚本中。
|
||||
const { ipcRenderer } = require('electron')
|
||||
window.electron = {
|
||||
// socket
|
||||
startSignalr: (user) => {
|
||||
ipcRenderer.invoke('startSignalr', user)
|
||||
},
|
||||
offSignalr: () => {
|
||||
ipcRenderer.invoke('offSignalr')
|
||||
},
|
||||
onStop: () => {
|
||||
ipcRenderer.invoke('onStop')
|
||||
},
|
||||
onInvoke: (str, data) => {
|
||||
ipcRenderer.invoke('onInvoke', str, data)
|
||||
},
|
||||
changeLocalStorage: (callback) => {
|
||||
ipcRenderer.on('changeLocalStorage', callback)
|
||||
},
|
||||
onOtherSignalr: (callback) => {
|
||||
ipcRenderer.invoke('onOtherSignalr')
|
||||
ipcRenderer.removeAllListeners('onOtherSignalr')
|
||||
ipcRenderer.on('onOtherSignalr', callback)
|
||||
},
|
||||
onSignalr: (callback) => {
|
||||
ipcRenderer.invoke('onSignalr')
|
||||
ipcRenderer.removeAllListeners('onSignalr')
|
||||
ipcRenderer.on('onSignalr', callback)
|
||||
},
|
||||
// 设置窗口大小
|
||||
setMainWindowSize: (config) => {
|
||||
ipcRenderer.invoke('setMainWindowSize', { ...config })
|
||||
|
|
@ -17,6 +43,10 @@ window.electron = {
|
|||
getIsMaximized: () => {
|
||||
return ipcRenderer.invoke('getIsMaximized')
|
||||
},
|
||||
// 获取app路径
|
||||
getAppPath: () => {
|
||||
return ipcRenderer.invoke('getAppPath')
|
||||
},
|
||||
// 获取版本号
|
||||
getVersion: () => {
|
||||
return ipcRenderer.invoke('getVersion')
|
||||
|
|
|
|||
30
src/App.tsx
30
src/App.tsx
|
|
@ -9,7 +9,6 @@ import Meeting from '@/page/Meeting/index'
|
|||
import NotFound from '@/page/NotFound/index'
|
||||
import { storage } from '@/utils'
|
||||
import { message, Spin } from "antd";
|
||||
import { onOtherSignalr, onStop, startSignalr } from "@/utils/package/signalr";
|
||||
import JoinMeetingModal from "@/components/JoinMeetingModal";
|
||||
import UpdateModal from "@/components/UpdateModal";
|
||||
import * as CryptoJS from 'crypto-js';
|
||||
|
|
@ -24,7 +23,7 @@ import ChatSmallWindow from "@/page/Meeting/ChatSmallWindow";
|
|||
import ChatBigWindow from "@/page/Meeting/ChatBigWindow";
|
||||
import CurrentSpeakUserWindow from "@/page/Meeting/CurrentSpeakUserWindow";
|
||||
import NoticeWindow from "@/page/Meeting/NoticeWindow";
|
||||
import { getKeyOpenChildWindow, setKeyOpenChildWindow } from "./utils/package/public";
|
||||
import { getKeyOpenChildWindow, setKeyOpenChildWindow, storageSeeting } from "./utils/package/public";
|
||||
const fs = require('fs').promises;
|
||||
const { exec } = require('child_process');
|
||||
const App: React.FC = () => {
|
||||
|
|
@ -54,7 +53,7 @@ const App: React.FC = () => {
|
|||
storage.setItem('user', JSON.stringify(res.data))
|
||||
storage.setItem('userLogin', true)
|
||||
toSrc('/home')
|
||||
await startSignalr()
|
||||
await window.electron.startSignalr(res.data)
|
||||
} else {
|
||||
toSrc('/login')
|
||||
}
|
||||
|
|
@ -121,6 +120,11 @@ const App: React.FC = () => {
|
|||
}
|
||||
}
|
||||
})
|
||||
window.electron.changeLocalStorage(async (_e: any, data: any) => {
|
||||
for (const key in data) {
|
||||
storage.setItem(key, data[key])
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
window.electron.onUpdate((_e: any, data: any) => {
|
||||
|
|
@ -129,21 +133,7 @@ const App: React.FC = () => {
|
|||
}
|
||||
})
|
||||
if (!storage.getItem('setting')) {
|
||||
storage.setItem('setting', JSON.stringify({
|
||||
videoDeviceId: '', //摄像头id
|
||||
ecordingDeviceId: "", //输入设备id
|
||||
playBackDeviceId: "", //输出设备id
|
||||
ecordingVolume: '', //输入音量
|
||||
playBackVolume: '', //输出音量
|
||||
autoEcordingVolume: true, //是否自动调整麦克风音量
|
||||
recordingFilesPath: path.resolve(__dirname, '../../Downloads') + '\\', //本地录制保存路径
|
||||
shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径
|
||||
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
||||
closeSetting: 'hide', //关闭按钮设置
|
||||
isAINoiseReduction: true, //是否开启ai降噪
|
||||
aINoiseReduction: 1, // 降噪模式
|
||||
isRecordingTips: true, //是否开启录制提示
|
||||
}))
|
||||
storage.setItem('setting', JSON.stringify(storageSeeting))
|
||||
}
|
||||
if (!storage.getItem('openChildWindow')) {
|
||||
storage.setItem('openChildWindow', JSON.stringify({}))
|
||||
|
|
@ -173,7 +163,7 @@ const App: React.FC = () => {
|
|||
}, [state])
|
||||
useEffect(() => {
|
||||
if (location.href.indexOf('/login') !== -1) {
|
||||
onStop()
|
||||
window.electron.onStop()
|
||||
}
|
||||
}, [navigate])
|
||||
}
|
||||
|
|
@ -196,7 +186,7 @@ const App: React.FC = () => {
|
|||
};
|
||||
|
||||
const onEventSignalr = (): void => {
|
||||
onOtherSignalr(async (item: any) => {
|
||||
window.electron.onOtherSignalr(async (_e: any, item: any) => {
|
||||
switch (item.key) {
|
||||
case 'Invitation':
|
||||
window.electron.joinNotification({
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 712 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 838 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 600 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 921 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
|
|
@ -1,6 +1,5 @@
|
|||
import styles from '@/components/EquipmentManagement/index.module.scss'
|
||||
import { getKeyOpenChildWindow } from '@/utils/package/public';
|
||||
import { onInvoke } from '@/utils/package/signalr';
|
||||
import { Button, Modal, Select, Slider, message } from 'antd';
|
||||
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||
const EquipmentManagement = forwardRef((props: any, ref: any) => {
|
||||
|
|
@ -12,7 +11,7 @@ const EquipmentManagement = forwardRef((props: any, ref: any) => {
|
|||
if (isOpen) {
|
||||
props.getDriver?.(uid)
|
||||
} else {
|
||||
await onInvoke('getDrivers', {
|
||||
await window.electron.onInvoke('getDrivers', {
|
||||
uid
|
||||
})
|
||||
}
|
||||
|
|
@ -99,7 +98,7 @@ const EquipmentManagement = forwardRef((props: any, ref: any) => {
|
|||
driversJsonString: JSON.stringify(deviceInfo)
|
||||
})
|
||||
} else {
|
||||
await onInvoke('setDrivers', {
|
||||
await window.electron.onInvoke('setDrivers', {
|
||||
uid: callerUid,
|
||||
driversJsonString: JSON.stringify(deviceInfo)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// 设置向导
|
||||
.stupWizard {
|
||||
height: 70vh;
|
||||
height: 90vh;
|
||||
display: flex;
|
||||
|
||||
.stupWizardLeft {
|
||||
|
|
@ -68,6 +68,10 @@
|
|||
}
|
||||
|
||||
.videoComponents {
|
||||
>div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
>div:nth-child(1) {
|
||||
width: 100%;
|
||||
height: 296px;
|
||||
|
|
@ -88,7 +92,6 @@
|
|||
|
||||
>div:nth-child(2) {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
|
|
@ -96,6 +99,82 @@
|
|||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
>div:nth-child(3) {}
|
||||
|
||||
.beautyEffect {
|
||||
>span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
>div {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
>div {
|
||||
border: 1px transparent solid;
|
||||
width: calc(100% /6);
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
|
||||
>label {
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
>input {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
>img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
border: 1px white solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.otherVideoSeeting {
|
||||
>div {
|
||||
margin-bottom: 20px;
|
||||
|
||||
>span {
|
||||
color: white;
|
||||
}
|
||||
|
||||
>div {
|
||||
margin-left: 40px;
|
||||
flex-grow: 1;
|
||||
|
||||
>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
>span {
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
>div {
|
||||
flex-grow: 1;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.audioComponents {
|
||||
|
|
|
|||
|
|
@ -6,12 +6,15 @@ import { agora } from '@/utils/package/agora'
|
|||
import { CloseOutlined, LoadingOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { storage } from '@/utils';
|
||||
import path from 'path';
|
||||
|
||||
import { role } from '@/config/role';
|
||||
import { storageSeeting } from '@/utils/package/public';
|
||||
let meetingUserInfo = '' as any;
|
||||
const fs = require('fs').promises;
|
||||
const { exec } = require('child_process');
|
||||
const StupWizard = forwardRef((props: any, ref: any) => {
|
||||
const StupWizard = forwardRef((_props: any, ref: any) => {
|
||||
useImperativeHandle(ref, () => ({
|
||||
changeModal: (index: number = 0) => {
|
||||
changeModal: (index: number = 0, data: any) => {
|
||||
meetingUserInfo = data;
|
||||
if (location.hash.indexOf('/meeting') === -1) {
|
||||
agora.init()
|
||||
}
|
||||
|
|
@ -23,47 +26,9 @@ const StupWizard = forwardRef((props: any, ref: any) => {
|
|||
return res
|
||||
})
|
||||
const setting = JSON.parse(storage.getItem('setting') as string)
|
||||
const obj: any = {
|
||||
videoDeviceId: '', //摄像头id
|
||||
ecordingDeviceId: "", //输入设备id
|
||||
playBackDeviceId: "", //输出设备id
|
||||
ecordingVolume: '', //输入音量
|
||||
playBackVolume: '', //输出音量
|
||||
autoEcordingVolume: true, //是否自动调整麦克风音量
|
||||
recordingFilesPath: path.resolve(__dirname, '../../Downloads') + '\\', //本地录制保存路径
|
||||
shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径
|
||||
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
||||
closeSetting: 'hide', //关闭按钮设置
|
||||
isAINoiseReduction: true, //是否开启ai降噪
|
||||
aINoiseReduction: 1, // 降噪模式
|
||||
isRecordingTips: true, //是否开启录制提示
|
||||
beautyEffect: { //美颜效果
|
||||
isBeautyEffect: false, //是否打开美颜
|
||||
lighteningContrastLevel: 1, //对比度
|
||||
lighteningLevel: 0, //美白程度
|
||||
smoothnessLevel: 0, //磨皮程度
|
||||
rednessLevel: 0, //红润度
|
||||
sharpnessLevel: 0, //锐化程度
|
||||
},
|
||||
colorEnhancement: { //色彩增强
|
||||
isColorEnhancement: false, //是否打开色彩增强
|
||||
strengthLevel: 0.5, //色彩增强程度
|
||||
skinProtectLevel: 1, //肤色保护程度
|
||||
},
|
||||
darkLightEnhancement: { //暗光增强
|
||||
isDarkLightEnhancement: false, //是否打开暗光增强
|
||||
level: 0, //暗光增强等级
|
||||
mode: 0, //暗光增强模式
|
||||
},
|
||||
virtualBackground: { //虚拟背景
|
||||
isVirtualBackground: false, //是否打开虚拟背景
|
||||
color: '0xFFFFFF', // 纯色
|
||||
sourceIndex: '', // 背景图下标
|
||||
},
|
||||
}
|
||||
for (const key in obj) {
|
||||
for (const key in storageSeeting) {
|
||||
if (setting[key] === undefined) {
|
||||
setting[key] = obj[key]
|
||||
setting[key] = storageSeeting[key]
|
||||
}
|
||||
}
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
|
|
@ -192,10 +157,81 @@ const VideoComponents = () => {
|
|||
list: [],
|
||||
item: null,
|
||||
});
|
||||
const [videoKey, setVideoKey] = useState('beautyEffect');
|
||||
const [virtualBackgroundImg] = useState([
|
||||
ImageUrl.virtualBackground1,
|
||||
ImageUrl.virtualBackground2,
|
||||
ImageUrl.virtualBackground3,
|
||||
ImageUrl.virtualBackground4,
|
||||
ImageUrl.virtualBackground5,
|
||||
ImageUrl.virtualBackground6,
|
||||
]);
|
||||
const [beautyEffect, setBeautyEffect] = useState<any>({
|
||||
isBeautyEffect: false, //是否打开美颜
|
||||
lighteningContrastLevel: 1, //对比度
|
||||
lighteningLevel: 0, //美白程度
|
||||
smoothnessLevel: 0, //磨皮程度
|
||||
rednessLevel: 0, //红润度
|
||||
sharpnessLevel: 0, //锐化程度
|
||||
});
|
||||
const [colorEnhancement, setColorEnhancement] = useState<any>({
|
||||
isColorEnhancement: false, //是否打开色彩增强
|
||||
strengthLevel: 0.5, //色彩增强程度
|
||||
skinProtectLevel: 1, //肤色保护程度
|
||||
});
|
||||
const [darkLightEnhancement, setDarkLightEnhancement] = useState<any>({
|
||||
isDarkLightEnhancement: false, //是否打开暗光增强
|
||||
level: 0, //暗光增强等级
|
||||
mode: 0, //暗光增强模式
|
||||
});
|
||||
const [virtualBackground, setVirtualBackground] = useState<any>({
|
||||
isVirtualBackground: false, //是否打开虚拟背景
|
||||
color: '0xFFFFFF', // 纯色
|
||||
sourceIndex: '', // 背景图下标
|
||||
});
|
||||
const setting = JSON.parse(storage.getItem('setting') as string)
|
||||
useEffect(() => {
|
||||
setBeautyEffect(setting.beautyEffect)
|
||||
setColorEnhancement(setting.colorEnhancement)
|
||||
setDarkLightEnhancement(setting.darkLightEnhancement)
|
||||
setVirtualBackground(setting.virtualBackground)
|
||||
getVideoDeviceList()
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
agora.setBeautyEffectOptions(beautyEffect.isBeautyEffect, beautyEffect)
|
||||
}, [beautyEffect]);
|
||||
useEffect(() => {
|
||||
agora.setColorEnhanceOptions(colorEnhancement.isColorEnhancement, colorEnhancement)
|
||||
}, [colorEnhancement]);
|
||||
useEffect(() => {
|
||||
agora.setLowlightEnhanceOptions(darkLightEnhancement.isDarkLightEnhancement, darkLightEnhancement)
|
||||
}, [darkLightEnhancement]);
|
||||
useEffect(() => {
|
||||
if (typeof virtualBackground.sourceIndex === 'number') {
|
||||
if (import.meta.env.VITE_ENV === 'development') {
|
||||
window.electron.getAppPath().then((res: string) => {
|
||||
const imagePath = path.join(res, 'src', 'assets', 'virtualBackground', `${virtualBackground.sourceIndex + 1}.png`);
|
||||
agora.enableVirtualBackground(virtualBackground.isVirtualBackground, {
|
||||
source: imagePath,
|
||||
background_source_type: 2,
|
||||
color: Number(virtualBackground.color),
|
||||
})
|
||||
})
|
||||
} else {
|
||||
const imagePath = path.join((process as any).resourcesPath, 'images', `${virtualBackground.sourceIndex + 1}.png`);
|
||||
agora.enableVirtualBackground(virtualBackground.isVirtualBackground, {
|
||||
source: imagePath,
|
||||
background_source_type: 2,
|
||||
color: Number(virtualBackground.color),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
agora.enableVirtualBackground(virtualBackground.isVirtualBackground, {
|
||||
background_source_type: 1,
|
||||
color: Number(virtualBackground.color),
|
||||
})
|
||||
}
|
||||
}, [virtualBackground]);
|
||||
const getVideoDeviceList = async (): Promise<void> => {
|
||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
||||
agora.getVideoDeviceManager().then(async (res) => {
|
||||
|
|
@ -261,17 +297,267 @@ const VideoComponents = () => {
|
|||
<Select
|
||||
placeholder={videoDeviceManager.list.length ? '请选择设备' : '未检测到摄像头'}
|
||||
options={videoDeviceManager.list} style={{ flexGrow: 1, marginRight: '10px' }}
|
||||
value={videoDeviceManager.item} onChange={async (e) => {
|
||||
setting.videoDeviceId = e;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
value={videoDeviceManager.item || null} onChange={async (e) => {
|
||||
setVideoDeviceManager({
|
||||
...videoDeviceManager,
|
||||
item: e
|
||||
})
|
||||
agora.setVideoDeviceManager(e)
|
||||
if (!setting.videoDeviceId) {
|
||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
||||
await agora.startPreview('videoPreview', Number(userInfo.screenShareId))
|
||||
}
|
||||
setting.videoDeviceId = e;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
}} />
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<Radio.Group buttonStyle="solid" value={videoKey} onChange={(e) => {
|
||||
setVideoKey(e.target.value)
|
||||
}}>
|
||||
<Radio.Button value="beautyEffect">虚拟背景</Radio.Button>
|
||||
<Radio.Button value="colorEnhancement">美颜效果</Radio.Button>
|
||||
<Radio.Button value="darkLightEnhancement">色彩增强</Radio.Button>
|
||||
<Radio.Button value="virtualBackground">暗光增强</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
{videoKey === 'beautyEffect' ? <div className={styles.beautyEffect}>
|
||||
<span>
|
||||
<Checkbox style={{ marginRight: '10px' }} checked={virtualBackground.isVirtualBackground} onChange={(e) => {
|
||||
setting.virtualBackground.isVirtualBackground = e.target.checked;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setVirtualBackground({
|
||||
...virtualBackground,
|
||||
isVirtualBackground: e.target.checked
|
||||
})
|
||||
}}>
|
||||
</Checkbox>
|
||||
虚拟背景
|
||||
</span>
|
||||
<div>
|
||||
<div className={virtualBackground.sourceIndex === '' ? styles.active : ''}>
|
||||
<div style={{ backgroundColor: '#' + Number(virtualBackground.color)?.toString(16).padStart(6, '0') }} onClick={() => {
|
||||
setting.virtualBackground.sourceIndex = '';
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setVirtualBackground({
|
||||
...virtualBackground,
|
||||
sourceIndex: ''
|
||||
})
|
||||
}}>
|
||||
<input type="color" name="" id="color-select" onChange={(e) => {
|
||||
let hexInt = parseInt('0x' + e.target.value.split('#')[1], 16)
|
||||
setting.virtualBackground.color = hexInt
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setVirtualBackground({
|
||||
...virtualBackground,
|
||||
color: hexInt
|
||||
})
|
||||
}} />
|
||||
<label htmlFor='color-select'>(纯色)更改颜色</label>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
virtualBackgroundImg.map((item, index) => {
|
||||
return (
|
||||
<div key={index} className={virtualBackground.sourceIndex === index ? styles.active : ''} onClick={() => {
|
||||
setting.virtualBackground.sourceIndex = index;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setVirtualBackground({
|
||||
...virtualBackground,
|
||||
sourceIndex: index
|
||||
})
|
||||
}}>
|
||||
<img src={item} alt="" />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div> : null}
|
||||
<div className={styles.otherVideoSeeting}>
|
||||
{videoKey === 'colorEnhancement' ? <div>
|
||||
<span>
|
||||
<Checkbox style={{ marginRight: '10px' }} checked={beautyEffect.isBeautyEffect} onChange={(e) => {
|
||||
setting.beautyEffect.isBeautyEffect = e.target.checked;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setBeautyEffect({
|
||||
...beautyEffect,
|
||||
isBeautyEffect: e.target.checked
|
||||
})
|
||||
}}>
|
||||
</Checkbox>
|
||||
美颜效果
|
||||
</span>
|
||||
<div>
|
||||
<div>
|
||||
<span>对比度</span>
|
||||
<div>
|
||||
<Radio.Group disabled={!beautyEffect.isBeautyEffect} onChange={(e: any) => {
|
||||
setting.beautyEffect.lighteningContrastLevel = e.target.value;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setBeautyEffect({
|
||||
...beautyEffect,
|
||||
lighteningContrastLevel: e.target.value
|
||||
})
|
||||
}} style={{ flexShrink: 0, margin: '10px 0' }} value={beautyEffect.lighteningContrastLevel}>
|
||||
<Radio value={0}>低对比度</Radio>
|
||||
<Radio value={1}>正常对比度</Radio>
|
||||
<Radio value={2}>高对比度</Radio>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>美白程度</span>
|
||||
<div>
|
||||
<Slider value={beautyEffect.lighteningLevel} step={0.1} style={{ width: '100%' }} max={1}
|
||||
onChange={async (e) => {
|
||||
setting.beautyEffect.lighteningLevel = e
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setBeautyEffect({
|
||||
...beautyEffect,
|
||||
lighteningLevel: e
|
||||
})
|
||||
}} disabled={!beautyEffect.isBeautyEffect} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>磨皮程度</span>
|
||||
<div>
|
||||
<Slider value={beautyEffect.smoothnessLevel} step={0.1} style={{ width: '100%' }} max={1}
|
||||
onChange={async (e) => {
|
||||
setting.beautyEffect.smoothnessLevel = e
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setBeautyEffect({
|
||||
...beautyEffect,
|
||||
smoothnessLevel: e
|
||||
})
|
||||
}} disabled={!beautyEffect.isBeautyEffect} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>红润度</span>
|
||||
<div>
|
||||
<Slider value={beautyEffect.rednessLevel} step={0.1} style={{ width: '100%' }} max={1}
|
||||
onChange={async (e) => {
|
||||
setting.beautyEffect.rednessLevel = e
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setBeautyEffect({
|
||||
...beautyEffect,
|
||||
rednessLevel: e
|
||||
})
|
||||
}} disabled={!beautyEffect.isBeautyEffect} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>锐化程度</span>
|
||||
<div>
|
||||
<Slider value={beautyEffect.sharpnessLevel} step={0.1} style={{ width: '100%' }} max={1}
|
||||
onChange={async (e) => {
|
||||
setting.beautyEffect.sharpnessLevel = e
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setBeautyEffect({
|
||||
...beautyEffect,
|
||||
sharpnessLevel: e
|
||||
})
|
||||
}} disabled={!beautyEffect.isBeautyEffect} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> : null}
|
||||
{videoKey === 'darkLightEnhancement' ? <div>
|
||||
<span>
|
||||
<Checkbox style={{ marginRight: '10px' }} checked={colorEnhancement.isColorEnhancement} onChange={(e) => {
|
||||
setting.colorEnhancement.isColorEnhancement = e.target.checked;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setColorEnhancement({
|
||||
...colorEnhancement,
|
||||
isColorEnhancement: e.target.checked
|
||||
})
|
||||
}}>
|
||||
</Checkbox>
|
||||
色彩增强
|
||||
</span>
|
||||
<div>
|
||||
<div>
|
||||
<span>色彩增强程度</span>
|
||||
<div>
|
||||
<Slider value={colorEnhancement.strengthLevel} step={0.1} style={{ width: '100%' }} max={1}
|
||||
onChange={async (e) => {
|
||||
setting.colorEnhancement.strengthLevel = e
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setColorEnhancement({
|
||||
...colorEnhancement,
|
||||
strengthLevel: e
|
||||
})
|
||||
}} disabled={!colorEnhancement.isColorEnhancement} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>肤色保护程度</span>
|
||||
<div>
|
||||
<Slider value={colorEnhancement.skinProtectLevel} step={0.1} style={{ width: '100%' }} max={1}
|
||||
onChange={async (e) => {
|
||||
setting.colorEnhancement.skinProtectLevel = e
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setColorEnhancement({
|
||||
...colorEnhancement,
|
||||
skinProtectLevel: e
|
||||
})
|
||||
}} disabled={!colorEnhancement.isColorEnhancement} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> : null}
|
||||
{videoKey === 'virtualBackground' ? <div>
|
||||
<span>
|
||||
<Checkbox style={{ marginRight: '10px' }} checked={darkLightEnhancement.isDarkLightEnhancement} onChange={(e) => {
|
||||
setting.darkLightEnhancement.isDarkLightEnhancement = e.target.checked;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setDarkLightEnhancement({
|
||||
...darkLightEnhancement,
|
||||
isDarkLightEnhancement: e.target.checked
|
||||
})
|
||||
}}>
|
||||
</Checkbox>
|
||||
暗光增强
|
||||
</span>
|
||||
<div>
|
||||
<div>
|
||||
<span>暗光增强等级</span>
|
||||
<div>
|
||||
<Radio.Group disabled={!darkLightEnhancement.isDarkLightEnhancement} onChange={(e: any) => {
|
||||
setting.darkLightEnhancement.level = e.target.value;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setDarkLightEnhancement({
|
||||
...darkLightEnhancement,
|
||||
level: e.target.value
|
||||
})
|
||||
}} style={{ flexShrink: 0, margin: '10px 0' }} value={darkLightEnhancement.level}>
|
||||
<Radio value={0}>(默认)优先画质的暗光增强,会处理视频图像的亮度、细节、噪声,消耗的性能适中,处理速度适中,综合画质最优。</Radio>
|
||||
<Radio value={1}>优先性能的暗光增强,会处理视频图像的亮度、细节,消耗的性能较少,处理速度较快。</Radio>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span>暗光增强模式</span>
|
||||
<div>
|
||||
<Radio.Group disabled={!darkLightEnhancement.isDarkLightEnhancement} onChange={(e: any) => {
|
||||
setting.darkLightEnhancement.mode = e.target.value;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setDarkLightEnhancement({
|
||||
...darkLightEnhancement,
|
||||
mode: e.target.value
|
||||
})
|
||||
}} style={{ flexShrink: 0, margin: '10px 0' }} value={darkLightEnhancement.mode}>
|
||||
<Radio value={0}>(默认)自动模式。SDK 会根据环境光亮度自动开启或关闭暗光增强功能,以适时补光和防止过曝。</Radio>
|
||||
<Radio value={1}>手动模式。用户需手动开启或关闭暗光增强功能。</Radio>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
@ -296,12 +582,15 @@ const AudioComponents = () => {
|
|||
getAudioMediaList()
|
||||
agora.registerEventHandler({
|
||||
onAudioVolumeIndication: (speakers: any) => {
|
||||
const totalVolume = speakers.length ? speakers[0].volume : 0
|
||||
const percentage = (totalVolume / 255) * 100
|
||||
const dom = document.getElementById('deviceTest') as any;
|
||||
if (dom) {
|
||||
dom.style.width = `${percentage}%`
|
||||
}
|
||||
speakers.forEach((item: any) => {
|
||||
if (item.uid === 0 || item.uid === 1) {
|
||||
const percentage = (item.volume / 255) * 100
|
||||
const dom = document.getElementById('deviceTest') as any;
|
||||
if (dom) {
|
||||
dom.style.width = `${percentage}%`
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}, []);
|
||||
|
|
@ -351,7 +640,7 @@ const AudioComponents = () => {
|
|||
<Select
|
||||
placeholder={audioDeviceManager.ecordingList.length ? '请选择设备' : '未检测到麦克风'}
|
||||
options={audioDeviceManager.ecordingList} style={{ flexGrow: 1 }}
|
||||
value={audioDeviceManager.ecordingItem} onChange={async (e) => {
|
||||
value={audioDeviceManager.ecordingItem || null} onChange={async (e) => {
|
||||
setting.ecordingDeviceId = e;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setAudioDeviceManager({
|
||||
|
|
@ -360,22 +649,26 @@ const AudioComponents = () => {
|
|||
})
|
||||
agora.setRecordingDevice(e)
|
||||
}} />;
|
||||
{audioDeviceManager.ecordingActive ? <div onClick={() => {
|
||||
agora.stopRecordingDeviceTest()
|
||||
setAudioDeviceManager({
|
||||
...audioDeviceManager,
|
||||
playBackActive: false,
|
||||
ecordingActive: false,
|
||||
})
|
||||
}}>结束</div> : <div onClick={() => {
|
||||
agora.stopPlaybackDeviceTest()
|
||||
agora.startRecordingDeviceTest(100)
|
||||
setAudioDeviceManager({
|
||||
...audioDeviceManager,
|
||||
playBackActive: false,
|
||||
ecordingActive: true,
|
||||
})
|
||||
}}>测试</div>}
|
||||
{(meetingUserInfo &&
|
||||
(role.ID.includes(meetingUserInfo.roleId) || meetingUserInfo.isRoomManager) &&
|
||||
meetingUserInfo.enableMicr) ||
|
||||
location.hash.indexOf('/meeting') === -1
|
||||
? audioDeviceManager.ecordingActive ? <div onClick={() => {
|
||||
agora.stopRecordingDeviceTest()
|
||||
setAudioDeviceManager({
|
||||
...audioDeviceManager,
|
||||
playBackActive: false,
|
||||
ecordingActive: false,
|
||||
})
|
||||
}}>结束</div> : <div onClick={() => {
|
||||
agora.stopPlaybackDeviceTest()
|
||||
agora.startRecordingDeviceTest(100)
|
||||
setAudioDeviceManager({
|
||||
...audioDeviceManager,
|
||||
playBackActive: false,
|
||||
ecordingActive: true,
|
||||
})
|
||||
}}>测试</div> : null}
|
||||
</div>
|
||||
{audioDeviceManager.ecordingActive ? <div className={styles.audioComponentsVolume}>
|
||||
<img src={ImageUrl.icon36} alt="" />
|
||||
|
|
@ -448,7 +741,7 @@ const AudioComponents = () => {
|
|||
<Select
|
||||
placeholder={audioDeviceManager.playBackList.length ? '请选择设备' : '未检测到麦克风'}
|
||||
options={audioDeviceManager.playBackList} style={{ flexGrow: 1 }}
|
||||
value={audioDeviceManager.playBackItem} onChange={async (e) => {
|
||||
value={audioDeviceManager.playBackItem || null} onChange={async (e) => {
|
||||
setting.playBackDeviceId = e;
|
||||
storage.setItem('setting', JSON.stringify(setting))
|
||||
setAudioDeviceManager({
|
||||
|
|
|
|||
|
|
@ -169,3 +169,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1154px) {
|
||||
.indexContentListItem {
|
||||
width: calc(98% / 2) !important;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@ import { storage } from '@/utils'
|
|||
import { GetCheckUser, PostAnonLogin, PostLogin } from '@/api/Login'
|
||||
import * as CryptoJS from 'crypto-js';
|
||||
import ImageUrl from '@/utils/package/imageUrl'
|
||||
import { startSignalr } from '@/utils/package/signalr';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { GetCheckoutRoomNum, GetRoomInfo, GetRoomRtcToken } from '@/api/Home/Index';
|
||||
const Login: React.FC = () => {
|
||||
|
|
@ -164,7 +163,7 @@ const Login: React.FC = () => {
|
|||
height: Math.ceil(res.height / 1.3),
|
||||
})
|
||||
})
|
||||
startSignalr()
|
||||
window.electron.startSignalr(res.data)
|
||||
navigate('/home')
|
||||
}
|
||||
})
|
||||
|
|
@ -321,7 +320,7 @@ const Login: React.FC = () => {
|
|||
if (res.code == 200) {
|
||||
storage.setItem('user', JSON.stringify(res.data))
|
||||
storage.setItem('userLogin', true)
|
||||
await startSignalr()
|
||||
await window.electron.startSignalr(res.data)
|
||||
getRoomRtcToken(anonInfo.roomNum, (options: any) => {
|
||||
if (options) {
|
||||
GetRoomInfo(anonInfo.roomNum).then(async (res) => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import { storage } from '@/utils';
|
|||
import { GetRoomUser, PostOpenMicr, PostOpenCamera, GetLeaveAll, PostRoomManager, DeleteRoomManager, GetRoomKickout, GetShowUser, PostShowUser, PostMuteAll, GetRoomUserItem, GetApplySpeak } from '@/api/Meeting';
|
||||
import ImageUrl from '@/utils/package/imageUrl'
|
||||
import { agora } from '@/utils/package/agora'
|
||||
import { onInvoke, onSignalr, offSignalr } from '@/utils/package/signalr';
|
||||
import dayjs from 'dayjs';
|
||||
import durationPlugin from 'dayjs/plugin/duration';
|
||||
import { AudioVolumeInfo, ConnectionChangedReasonType, ConnectionStateType, LocalVideoStreamReason, LocalVideoStreamState, QualityType, RtcConnection, RtcStats, UserOfflineReasonType, VideoSourceType, VideoStreamType } from 'agora-electron-sdk';
|
||||
|
|
@ -276,12 +275,12 @@ const Meeting: React.FC = () => {
|
|||
})
|
||||
break;
|
||||
case 'userListWindowEquipmentManagement':
|
||||
await onInvoke('getDrivers', {
|
||||
await window.electron.onInvoke('getDrivers', {
|
||||
uid: userListWindowEquipmentManagement.uid,
|
||||
})
|
||||
break;
|
||||
case 'userListWindowSetEquipmentManagement':
|
||||
await onInvoke('setDrivers', {
|
||||
await window.electron.onInvoke('setDrivers', {
|
||||
uid: userListWindowSetEquipmentManagement.uid,
|
||||
driversJsonString: userListWindowSetEquipmentManagement.driversJsonString
|
||||
})
|
||||
|
|
@ -410,7 +409,6 @@ const Meeting: React.FC = () => {
|
|||
firstFooterList[0][0].active = !state.enableMicr
|
||||
firstFooterList[0][1].title = state.enableCamera ? '关闭视频' : '开启视频'
|
||||
firstFooterList[0][1].active = !state.enableCamera
|
||||
agora.muteLocalVideoStream(userInfo, state.enableMicr, state.enableCamera)
|
||||
setFooterList(firstFooterList)
|
||||
setTimeout(async () => {
|
||||
const setting = await JSON.parse(storage.getItem('setting') as string);
|
||||
|
|
@ -534,7 +532,7 @@ const Meeting: React.FC = () => {
|
|||
}, [currentVideoId, isShare]);
|
||||
|
||||
useEffect(() => {
|
||||
onSignalr(async (item: any) => {
|
||||
window.electron.onSignalr(async (_e: any, item: any) => {
|
||||
const setting = JSON.parse(storage.getItem('setting') as string)
|
||||
switch (item.key) {
|
||||
// 聊天
|
||||
|
|
@ -573,7 +571,7 @@ const Meeting: React.FC = () => {
|
|||
setIsShare((res: any) => {
|
||||
if (userInfo.screenShareId === String(res)) {
|
||||
changeStatusList({
|
||||
title: '停止共享'
|
||||
title: '共享冲突停止共享',
|
||||
}, 1, 0)
|
||||
}
|
||||
return res
|
||||
|
|
@ -789,7 +787,7 @@ const Meeting: React.FC = () => {
|
|||
playBackDeviceId: res[1].ecordingList.find((row: any) => row.deviceId === setting.playBackDeviceId) ? setting.playBackDeviceId : res[1].playBackList.length ? res[1].playBackList[0].deviceId : null,
|
||||
ecordingVolume: res[1].ecordingVolume
|
||||
}
|
||||
onInvoke('sendDrivers', {
|
||||
window.electron.onInvoke('sendDrivers', {
|
||||
uid: item.callerUid,
|
||||
driversJsonString: JSON.stringify(data)
|
||||
})
|
||||
|
|
@ -825,7 +823,7 @@ const Meeting: React.FC = () => {
|
|||
}
|
||||
})
|
||||
return () => {
|
||||
offSignalr()
|
||||
window.electron.offSignalr()
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
|
@ -930,6 +928,7 @@ const Meeting: React.FC = () => {
|
|||
// 声网初始化
|
||||
const agoraInit = async () => {
|
||||
await agora.init(true)
|
||||
await agora.muteLocalVideoStream(userInfo, state.enableMicr, state.enableCamera)
|
||||
await getJoin(state.enableMicr, state.enableCamera)
|
||||
agora.registerEventHandler({
|
||||
onJoinChannelSuccess: async (connection: RtcConnection, _elapsed: number) => {
|
||||
|
|
@ -963,6 +962,7 @@ const Meeting: React.FC = () => {
|
|||
}
|
||||
},
|
||||
onUserOffline: async (connection: RtcConnection, remoteUid: number, _reason: UserOfflineReasonType) => {
|
||||
await agora.destroyRendererByConfig(Number(remoteUid), connection.channelId)
|
||||
if (connection.channelId === state.channelId) {
|
||||
if (String(remoteUid).length === 9) {
|
||||
setIsShare(null)
|
||||
|
|
@ -1380,6 +1380,7 @@ const Meeting: React.FC = () => {
|
|||
})
|
||||
break;
|
||||
case '停止共享':
|
||||
case '共享冲突停止共享':
|
||||
await getUserRoomInfo().then(async (res) => {
|
||||
if (res) {
|
||||
await stopScreenCapture()
|
||||
|
|
@ -1387,7 +1388,9 @@ const Meeting: React.FC = () => {
|
|||
message.error(msgTips)
|
||||
}
|
||||
})
|
||||
await allUserLook(userInfo.uid, userInfo.userName)
|
||||
if (row.title === '停止共享') {
|
||||
await allUserLook(userInfo.uid, userInfo.userName)
|
||||
}
|
||||
break;
|
||||
case '静音':
|
||||
await postOpenMicr(false, userInfo.uid)
|
||||
|
|
@ -1424,7 +1427,10 @@ const Meeting: React.FC = () => {
|
|||
})
|
||||
break;
|
||||
case '设置':
|
||||
stupWizardRef.current.changeModal()
|
||||
await getUserRoomInfo().then(async (res) => {
|
||||
stupWizardRef.current.changeModal(0, res)
|
||||
})
|
||||
|
||||
break;
|
||||
case '邀请人员':
|
||||
await getUserRoomInfo().then(async (res) => {
|
||||
|
|
@ -1550,11 +1556,8 @@ const Meeting: React.FC = () => {
|
|||
// 退出房间
|
||||
const leaveChannel = async (bool: boolean = true): Promise<void> => {
|
||||
await stopRecorderMedia()
|
||||
try {
|
||||
if (bool) {
|
||||
await getLeave()
|
||||
}
|
||||
} catch (error) {
|
||||
if (bool) {
|
||||
await getLeave()
|
||||
}
|
||||
await stopScreenCapture()
|
||||
await agora.leaveChannel()
|
||||
|
|
@ -1715,7 +1718,7 @@ const Meeting: React.FC = () => {
|
|||
break;
|
||||
case 'reconnect':
|
||||
if (e.value == true) {
|
||||
await onInvoke('joinChannel', {
|
||||
await window.electron.onInvoke('joinChannel', {
|
||||
roomNum: state.channelId,
|
||||
enableMicr: !footerList[0][0].active,
|
||||
enableCamera: !footerList[0][1].active
|
||||
|
|
@ -1747,7 +1750,7 @@ const Meeting: React.FC = () => {
|
|||
const sendMsg = (text?: string): void => {
|
||||
let msg = text ? text : textMsg;
|
||||
if (msg) {
|
||||
onInvoke('sendChannelMsg', {
|
||||
window.electron.onInvoke('sendChannelMsg', {
|
||||
roomNum: state.channelId,
|
||||
msg: msg,
|
||||
})
|
||||
|
|
@ -1991,7 +1994,7 @@ const Meeting: React.FC = () => {
|
|||
// enableMicr,
|
||||
// enableCamera
|
||||
// })
|
||||
await onInvoke('joinChannel', {
|
||||
await window.electron.onInvoke('joinChannel', {
|
||||
roomNum: state.channelId,
|
||||
enableMicr,
|
||||
enableCamera
|
||||
|
|
@ -2003,7 +2006,7 @@ const Meeting: React.FC = () => {
|
|||
// await GetLeave({
|
||||
// roomNum: state.channelId,
|
||||
// })
|
||||
await onInvoke('levelChannel', {
|
||||
await window.electron.onInvoke('levelChannel', {
|
||||
roomNum: state.channelId
|
||||
})
|
||||
}
|
||||
|
|
@ -2786,13 +2789,13 @@ const Meeting: React.FC = () => {
|
|||
setIsSharePopConfirm(false)
|
||||
setIsSharedScreenModal(false)
|
||||
}} style={{ backgroundColor: '#31353A', marginRight: '14px' }}>取消</Button>
|
||||
{isShare ? <Popconfirm
|
||||
{isShare && sharedScreenItem ? <Popconfirm
|
||||
title="提示"
|
||||
description={`这将停止[${isShareUser?.userName}]的共享,是否继续?`}
|
||||
open={isSharePopConfirm}
|
||||
onConfirm={async () => {
|
||||
setIsSharePopConfirm(false)
|
||||
await onInvoke('sendOper', {
|
||||
await window.electron.onInvoke('sendOper', {
|
||||
roomNum: state.channelId,
|
||||
type: 4,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
// electron-env.d.ts
|
||||
export interface IElectronAPI {
|
||||
startSignalr: (user: any) => Promise<void>;
|
||||
offSignalr: () => Promise<void>;
|
||||
onStop: () => Promise<void>;
|
||||
onInvoke: (str: string, data: any) => Promise<void>;
|
||||
changeLocalStorage: (callBack: Function) => void;
|
||||
onOtherSignalr: (callBack: Function) => void;
|
||||
onSignalr: (callBack: Function) => void;
|
||||
setMainWindowSize: (config: any) => void;
|
||||
getWindowSize: () => any;
|
||||
setViewStatus: (status: 'quit' | 'maximize' | 'minimize' | 'unmaximize' | 'hide' | 'show') => void;
|
||||
getIsMaximized: () => Promise<boolean>;
|
||||
getAppPath: () => Promise<string>;
|
||||
setWriteText: (text: string) => void;
|
||||
onQuit: (callBack: Function) => void;
|
||||
onUpdate: (callBack: Function) => void;
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@ import {
|
|||
ConnectionStateType,
|
||||
ConnectionChangedReasonType,
|
||||
LocalVideoStreamReason,
|
||||
LocalVideoStreamState
|
||||
LocalVideoStreamState,
|
||||
BeautyOptions,
|
||||
ColorEnhanceOptions,
|
||||
LowlightEnhanceOptions,
|
||||
VirtualBackgroundSource
|
||||
} from "agora-electron-sdk";
|
||||
import { GetRoomRtcToken, GetAgoraConf } from "@/api/Home/Index";
|
||||
import { storage } from '@/utils';
|
||||
import { role } from "@/config/role";
|
||||
import path from "path";
|
||||
const option: any = {
|
||||
appId: '',
|
||||
token: '',
|
||||
|
|
@ -64,8 +69,11 @@ export const agora = {
|
|||
}
|
||||
})
|
||||
} else {
|
||||
await agora.setVideoDeviceManager(await rtcEngine.getVideoDeviceManager().getDevice())
|
||||
setting.videoDeviceId = await rtcEngine.getVideoDeviceManager().getDevice()
|
||||
try {
|
||||
await agora.setVideoDeviceManager(await rtcEngine.getVideoDeviceManager().getDevice())
|
||||
setting.videoDeviceId = await rtcEngine.getVideoDeviceManager().getDevice()
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 播放设备
|
||||
|
|
@ -110,6 +118,35 @@ export const agora = {
|
|||
if (settingData.ecordingDeviceId) agora.setRecordingDevice(settingData.ecordingDeviceId) // 设置音频采集设备
|
||||
if (settingData.ecordingVolume) agora.setRecordingDeviceVolume(settingData.ecordingVolume) // 设置音频设备音量
|
||||
if (settingData.isAINoiseReduction) agora.setAINSMode(settingData.isAINoiseReduction, settingData.aINoiseReduction) // 设置ai降噪
|
||||
if (settingData.beautyEffect) agora.setBeautyEffectOptions(settingData.beautyEffect.isBeautyEffect, settingData.beautyEffect)
|
||||
if (settingData.colorEnhancement) agora.setColorEnhanceOptions(settingData.colorEnhancement.isColorEnhancement, settingData.colorEnhancement)
|
||||
if (settingData.darkLightEnhancement) agora.setLowlightEnhanceOptions(settingData.darkLightEnhancement.isDarkLightEnhancement, settingData.darkLightEnhancement)
|
||||
if (settingData.virtualBackground) {
|
||||
if (typeof settingData.virtualBackground.sourceIndex === 'number') {
|
||||
if (import.meta.env.VITE_ENV === 'development') {
|
||||
window.electron.getAppPath().then((res: string) => {
|
||||
const imagePath = path.join(res, 'src', 'assets', 'virtualBackground', `${settingData.virtualBackground.sourceIndex + 1}.png`);
|
||||
agora.enableVirtualBackground(settingData.virtualBackground.isVirtualBackground, {
|
||||
source: imagePath,
|
||||
background_source_type: 2,
|
||||
color: Number(settingData.virtualBackground.color),
|
||||
})
|
||||
})
|
||||
} else {
|
||||
const imagePath = path.join((process as any).resourcesPath, 'images', `${settingData.virtualBackground.sourceIndex + 1}.png`);
|
||||
agora.enableVirtualBackground(settingData.virtualBackground.isVirtualBackground, {
|
||||
source: imagePath,
|
||||
background_source_type: 2,
|
||||
color: Number(settingData.virtualBackground.color),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
agora.enableVirtualBackground(settingData.virtualBackground.isVirtualBackground, {
|
||||
background_source_type: 1,
|
||||
color: Number(settingData.virtualBackground.color),
|
||||
})
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
// 事件回调
|
||||
|
|
@ -329,7 +366,7 @@ export const agora = {
|
|||
rtcEngine.muteRemoteVideoStream(uid, mute)
|
||||
},
|
||||
// 销毁视频渲染dom
|
||||
destroyRendererByConfig: async (uid: number, channelId: string) => {
|
||||
destroyRendererByConfig: async (uid: number, channelId?: string) => {
|
||||
await rtcEngine.destroyRendererByConfig(VideoSourceType.VideoSourceRemote, channelId, uid);
|
||||
},
|
||||
// ai降噪
|
||||
|
|
@ -512,5 +549,22 @@ export const agora = {
|
|||
stopRecordingDeviceTest: async () => {
|
||||
await rtcEngine.getAudioDeviceManager().stopRecordingDeviceTest()
|
||||
},
|
||||
|
||||
// 设置美颜效果
|
||||
setBeautyEffectOptions: async (enabled: boolean, options: BeautyOptions) => {
|
||||
await rtcEngine.setBeautyEffectOptions(enabled, options)
|
||||
},
|
||||
// 设置色彩增强
|
||||
setColorEnhanceOptions: async (enabled: boolean, options: ColorEnhanceOptions) => {
|
||||
await rtcEngine.setColorEnhanceOptions(enabled, options)
|
||||
},
|
||||
// 设置暗光增强
|
||||
setLowlightEnhanceOptions: async (enabled: boolean, options: LowlightEnhanceOptions) => {
|
||||
await rtcEngine.setLowlightEnhanceOptions(enabled, options)
|
||||
},
|
||||
// 开启/关闭虚拟背景。
|
||||
enableVirtualBackground: async (enabled: boolean, backgroundSource: VirtualBackgroundSource) => {
|
||||
await rtcEngine.enableVirtualBackground(enabled, backgroundSource, {
|
||||
greenCapacity: 1
|
||||
})
|
||||
},
|
||||
}
|
||||
|
|
@ -73,6 +73,12 @@ import icon48Select from '@/assets/icon48-select.png'
|
|||
import icon49 from '@/assets/icon49.png'
|
||||
import icon50 from '@/assets/icon50.png'
|
||||
import icon51 from '@/assets/icon51.png'
|
||||
import virtualBackground1 from '@/assets/virtualBackground/1.png'
|
||||
import virtualBackground2 from '@/assets/virtualBackground/2.png'
|
||||
import virtualBackground3 from '@/assets/virtualBackground/3.png'
|
||||
import virtualBackground4 from '@/assets/virtualBackground/4.png'
|
||||
import virtualBackground5 from '@/assets/virtualBackground/5.png'
|
||||
import virtualBackground6 from '@/assets/virtualBackground/6.png'
|
||||
export default {
|
||||
loading,
|
||||
icon,
|
||||
|
|
@ -149,4 +155,10 @@ export default {
|
|||
icon49,
|
||||
icon50,
|
||||
icon51,
|
||||
virtualBackground1,
|
||||
virtualBackground2,
|
||||
virtualBackground3,
|
||||
virtualBackground4,
|
||||
virtualBackground5,
|
||||
virtualBackground6,
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import path from "path";
|
||||
import storage from "./storage";
|
||||
export const setKeyOpenChildWindow = async (key: string, bool: boolean) => {
|
||||
const openChildWindow = await JSON.parse(storage.getItem('openChildWindow') as string)
|
||||
|
|
@ -13,3 +14,43 @@ export const getKeyOpenChildWindow = async (key: string): Promise<boolean> => {
|
|||
const openChildWindow = await JSON.parse(storage.getItem('openChildWindow') as string)
|
||||
return openChildWindow[key]
|
||||
};
|
||||
|
||||
|
||||
export const storageSeeting: any = {
|
||||
videoDeviceId: '', //摄像头id
|
||||
ecordingDeviceId: "", //输入设备id
|
||||
playBackDeviceId: "", //输出设备id
|
||||
ecordingVolume: '', //输入音量
|
||||
playBackVolume: '', //输出音量
|
||||
autoEcordingVolume: true, //是否自动调整麦克风音量
|
||||
recordingFilesPath: path.resolve(__dirname, '../../Downloads') + '\\', //本地录制保存路径
|
||||
shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径
|
||||
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
||||
closeSetting: 'hide', //关闭按钮设置
|
||||
isAINoiseReduction: true, //是否开启ai降噪
|
||||
aINoiseReduction: 1, // 降噪模式
|
||||
isRecordingTips: true, //是否开启录制提示
|
||||
beautyEffect: { //美颜效果
|
||||
isBeautyEffect: false, //是否打开美颜
|
||||
lighteningContrastLevel: 1, //对比度
|
||||
lighteningLevel: 0, //美白程度
|
||||
smoothnessLevel: 0, //磨皮程度
|
||||
rednessLevel: 0, //红润度
|
||||
sharpnessLevel: 0, //锐化程度
|
||||
},
|
||||
colorEnhancement: { //色彩增强
|
||||
isColorEnhancement: false, //是否打开色彩增强
|
||||
strengthLevel: 0.5, //色彩增强程度
|
||||
skinProtectLevel: 1, //肤色保护程度
|
||||
},
|
||||
darkLightEnhancement: { //暗光增强
|
||||
isDarkLightEnhancement: false, //是否打开暗光增强
|
||||
level: 0, //暗光增强等级
|
||||
mode: 0, //暗光增强模式
|
||||
},
|
||||
virtualBackground: { //虚拟背景
|
||||
isVirtualBackground: false, //是否打开虚拟背景
|
||||
color: '0xFFFFFF', // 纯色
|
||||
sourceIndex: '', // 背景图下标
|
||||
},
|
||||
}
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
import * as signalR from '@microsoft/signalr';
|
||||
import storage from './storage';
|
||||
let connection = '' as any;
|
||||
export const startSignalr = async () => {
|
||||
const user = await JSON.parse(storage.getItem('user') as string);
|
||||
connection = new signalR.HubConnectionBuilder().withAutomaticReconnect()
|
||||
.withUrl(`${import.meta.env.VITE_BASE_URL_API}/session-manage`, {
|
||||
skipNegotiation: true,
|
||||
transport: signalR.HttpTransportType.WebSockets,
|
||||
accessTokenFactory: () => user.token
|
||||
})
|
||||
.build();
|
||||
onStart()
|
||||
storage.setItem('isSignalr', true)
|
||||
storage.setItem('reconnect', true)
|
||||
connection.onreconnected(async () => {
|
||||
storage.setItem('reconnect', true)
|
||||
});
|
||||
connection.onreconnecting(async () => {
|
||||
onStart()
|
||||
storage.setItem('reconnect', false)
|
||||
});
|
||||
}
|
||||
|
||||
export const onStart = async () => {
|
||||
if (connection) {
|
||||
if (connection.state !== signalR.HubConnectionState.Connected) {
|
||||
connection.start();
|
||||
} else {
|
||||
setTimeout(onStart, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
export const onOtherSignalr = (callBack: Function) => {
|
||||
if (connection) {
|
||||
// 邀请
|
||||
connection.on("Invitation", (roomNum: string, roomName: string, InviterName: string) => {
|
||||
callBack({
|
||||
key: 'Invitation',
|
||||
roomNum, roomName, InviterName
|
||||
})
|
||||
});
|
||||
// 退出
|
||||
connection.on("ForceLogout", (msg: string) => {
|
||||
callBack({
|
||||
key: 'ForceLogout',
|
||||
msg
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
export const onSignalr = (callBack: Function) => {
|
||||
if (connection) {
|
||||
// 聊天
|
||||
connection.on("ReceiveMessage", (uid: string, userName: string, message: string, timestamp: string) => {
|
||||
callBack({
|
||||
key: 'ReceiveMessage',
|
||||
uid, message, userName, timestamp
|
||||
})
|
||||
});
|
||||
// 扩展操作
|
||||
connection.on("Operation", (type: number) => {
|
||||
callBack({
|
||||
key: 'Operation',
|
||||
type
|
||||
})
|
||||
});
|
||||
// 移出会议
|
||||
connection.on("ForceExitRoom", () => {
|
||||
callBack({
|
||||
key: 'ForceExitRoom',
|
||||
})
|
||||
});
|
||||
// 全员离开房间
|
||||
connection.on("AllLeave", () => {
|
||||
callBack({
|
||||
key: 'AllLeave',
|
||||
})
|
||||
});
|
||||
// 全员看他
|
||||
connection.on("ShowUser", (uid: string, uname: string, operUid: string, operUserName: string) => {
|
||||
callBack({
|
||||
key: 'ShowUser',
|
||||
uid,
|
||||
uname,
|
||||
operUid,
|
||||
operUserName,
|
||||
})
|
||||
});
|
||||
// 更新视图模式
|
||||
connection.on("RefreshView", (type: string) => {
|
||||
callBack({
|
||||
key: 'RefreshView',
|
||||
type
|
||||
})
|
||||
});
|
||||
// 用户加入频道回调
|
||||
connection.on("UserJoined", (user: any) => {
|
||||
callBack({
|
||||
key: 'UserJoined',
|
||||
user,
|
||||
})
|
||||
});
|
||||
// 用户退出频道回调
|
||||
connection.on("UserLeave", (uid: string,) => {
|
||||
callBack({
|
||||
key: 'UserLeave',
|
||||
uid,
|
||||
})
|
||||
});
|
||||
// 所有用户开闭麦
|
||||
connection.on("OperAllMicr", (enableMicr: boolean, uid: string) => {
|
||||
callBack({
|
||||
key: 'OperAllMicr',
|
||||
enableMicr,
|
||||
uid
|
||||
})
|
||||
});
|
||||
// 用户关闭开启麦克风
|
||||
connection.on("OperMicr", (user: any, operUid: string) => {
|
||||
callBack({
|
||||
key: 'OperMicr',
|
||||
user,
|
||||
operUid
|
||||
})
|
||||
});
|
||||
// 用户开启关闭摄像头
|
||||
connection.on("OperCamera", (user: any, operUid: string) => {
|
||||
callBack({
|
||||
key: 'OperCamera',
|
||||
user,
|
||||
operUid
|
||||
})
|
||||
});
|
||||
// 发言人用户信息刷新
|
||||
connection.on("ManagerRefresh", (user: any, uid: string) => {
|
||||
callBack({
|
||||
key: 'ManagerRefresh',
|
||||
user,
|
||||
uid
|
||||
})
|
||||
});
|
||||
// 申请发言
|
||||
connection.on("ApplyToSpeak", (uid: string, uname: string) => {
|
||||
callBack({
|
||||
key: 'ApplyToSpeak',
|
||||
uid,
|
||||
uname
|
||||
})
|
||||
});
|
||||
// 管理员查看随机用户
|
||||
connection.on("Watch", (watchUids: string[]) => {
|
||||
callBack({
|
||||
key: 'Watch',
|
||||
watchUids
|
||||
})
|
||||
});
|
||||
// 设备列表
|
||||
connection.on("DriverList", (callerUid: string) => {
|
||||
callBack({
|
||||
key: 'DriverList',
|
||||
callerUid
|
||||
})
|
||||
});
|
||||
// 设置设备
|
||||
connection.on("SaveDriver", (driver: string) => {
|
||||
callBack({
|
||||
key: 'SaveDriver',
|
||||
driver
|
||||
})
|
||||
});
|
||||
// 显示设备列表
|
||||
connection.on("ShowDriverList", (driversJsonString: string) => {
|
||||
callBack({
|
||||
key: 'ShowDriverList',
|
||||
driversJsonString
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
export const offSignalr = () => {
|
||||
if (connection) {
|
||||
connection.off('ReceiveMessage');
|
||||
connection.off('Operation');
|
||||
connection.off('ForceExitRoom');
|
||||
connection.off('AllLeave');
|
||||
connection.off('ShowUser');
|
||||
connection.off('RefreshView');
|
||||
connection.off('UserJoined');
|
||||
connection.off('UserLeave');
|
||||
connection.off('OperAllMicr');
|
||||
connection.off('OperMicr');
|
||||
connection.off('OperCamera');
|
||||
connection.off('ManagerRefresh');
|
||||
connection.off('ApplyToSpeak');
|
||||
connection.off('Watch');
|
||||
connection.off('DriverList');
|
||||
connection.off('SetDriver');
|
||||
connection.off('ShowDriverList');
|
||||
}
|
||||
}
|
||||
export const onInvoke = async (str: string, data: any) => {
|
||||
switch (str) {
|
||||
case 'sendChannelMsg':
|
||||
await connection.invoke(str, data.roomNum, data.msg)
|
||||
break;
|
||||
case 'sendOper':
|
||||
// 4:屏幕共享
|
||||
await connection.invoke(str, data.roomNum, data.type)
|
||||
break;
|
||||
case 'getDrivers':
|
||||
// 获取某个人的设备列表
|
||||
await connection.invoke(str, data.uid)
|
||||
break;
|
||||
case 'sendDrivers':
|
||||
// 发送设备列表给某个人
|
||||
await connection.invoke(str, data.uid, data.driversJsonString)
|
||||
break;
|
||||
case 'setDrivers':
|
||||
// 设置某个人的设备列表
|
||||
await connection.invoke(str, data.uid, data.driversJsonString)
|
||||
break;
|
||||
case 'joinChannel':
|
||||
// 设置某个人的设备列表
|
||||
await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera)
|
||||
break;
|
||||
case 'levelChannel':
|
||||
// 设置某个人的设备列表
|
||||
await connection.invoke(str, data.roomNum)
|
||||
break;
|
||||
}
|
||||
}
|
||||
export const onStop = async () => {
|
||||
if (connection) {
|
||||
storage.setItem('isSignalr', false)
|
||||
connection.off('Invitation');
|
||||
connection.off('ForceLogout');
|
||||
connection.stop()
|
||||
connection = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +350,7 @@ $pagination-hover-background-color: #5575F2;
|
|||
|
||||
// ant-notification
|
||||
.ant-notification {
|
||||
-webkit-app-region: no-drag;
|
||||
.ant-notification-notice-wrapper {
|
||||
background-color: #1F2022;
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,11 @@ export default defineConfig({
|
|||
ConnectionStateType,
|
||||
ConnectionChangedReasonType,
|
||||
LocalVideoStreamState,
|
||||
LocalVideoStreamReason
|
||||
LocalVideoStreamReason,
|
||||
BeautyOptions,
|
||||
ColorEnhanceOptions,
|
||||
LowlightEnhanceOptions,
|
||||
VirtualBackgroundSource
|
||||
} = require("agora-electron-sdk")
|
||||
export {
|
||||
createAgoraRtcEngine,
|
||||
|
|
@ -93,7 +97,11 @@ export default defineConfig({
|
|||
ConnectionStateType,
|
||||
ConnectionChangedReasonType,
|
||||
LocalVideoStreamState,
|
||||
LocalVideoStreamReason
|
||||
LocalVideoStreamReason,
|
||||
BeautyOptions,
|
||||
ColorEnhanceOptions,
|
||||
LowlightEnhanceOptions,
|
||||
VirtualBackgroundSource
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue