Compare commits
No commits in common. "master" and "0.6.4" have entirely different histories.
|
|
@ -0,0 +1,6 @@
|
||||||
|
#基础API 绝对的
|
||||||
|
VITE_BASE_URL_API = 'http://192.168.2.9:5192'
|
||||||
|
#当前IP 相对的
|
||||||
|
VITE_BASE_CURRENT_API = '.'
|
||||||
|
#开发环境
|
||||||
|
VITE_ENV = 'development'
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#基础API 绝对的
|
||||||
|
VITE_BASE_URL_API = 'https://meeting-api.23544.com/pc'
|
||||||
|
#当前IP 相对的
|
||||||
|
VITE_BASE_CURRENT_API = '.'
|
||||||
|
#生产环境
|
||||||
|
VITE_ENV = 'production'
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#基础API 绝对的
|
||||||
|
VITE_BASE_URL_API = 'https://meeting-api.23544.com/pc'
|
||||||
|
#当前IP 相对的
|
||||||
|
VITE_BASE_CURRENT_API = '.'
|
||||||
|
#测试环境
|
||||||
|
VITE_ENV = 'xy'
|
||||||
|
After Width: | Height: | Size: 162 KiB |
|
|
@ -1,16 +0,0 @@
|
||||||
!macro customFinishPage
|
|
||||||
AutoCloseWindow true
|
|
||||||
Function StartApp
|
|
||||||
${if} ${isUpdated}
|
|
||||||
StrCpy $1 "--updated"
|
|
||||||
${else}
|
|
||||||
StrCpy $1 ""
|
|
||||||
${endif}
|
|
||||||
${StdUtils.ExecShellAsUser} $0 "$launchLink" "open" "$1"
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
Function .onInstSuccess
|
|
||||||
Call StartApp
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
!macroend
|
|
||||||
|
|
@ -42,16 +42,15 @@
|
||||||
],
|
],
|
||||||
"nsis": {
|
"nsis": {
|
||||||
"oneClick": false,
|
"oneClick": false,
|
||||||
"installerIcon": "build/start.ico",
|
"installerIcon": "build/install.ico",
|
||||||
"uninstallerIcon": "build/start.ico",
|
"uninstallerIcon": "build/install.ico",
|
||||||
"installerHeaderIcon": "build/start.ico",
|
"installerHeaderIcon": "build/install.ico",
|
||||||
"allowToChangeInstallationDirectory": true,
|
"allowToChangeInstallationDirectory": true,
|
||||||
"createDesktopShortcut": true,
|
"createDesktopShortcut": true,
|
||||||
"createStartMenuShortcut": true,
|
"createStartMenuShortcut": true,
|
||||||
"deleteAppDataOnUninstall": true,
|
"deleteAppDataOnUninstall": true,
|
||||||
"shortcutName": "智汇享",
|
"shortcutName": "智汇享",
|
||||||
"allowElevation": true,
|
"allowElevation": true,
|
||||||
"perMachine": true,
|
"perMachine": true
|
||||||
"include": "build/install.nsh"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"appId": "agora.io.ElectronApiExample",
|
|
||||||
"asar": true,
|
|
||||||
"asarUnpack": [
|
|
||||||
"node_modules/agora-electron-sdk"
|
|
||||||
],
|
|
||||||
"buildDependenciesFromSource": true,
|
|
||||||
"compression": "normal",
|
|
||||||
"productName": "智汇享",
|
|
||||||
"publish": [
|
|
||||||
{
|
|
||||||
"provider": "generic",
|
|
||||||
"url": "http://192.168.2.9:8827"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"files": [
|
|
||||||
"!*.log"
|
|
||||||
],
|
|
||||||
"win": {
|
|
||||||
"icon": "build/start.ico",
|
|
||||||
"requestedExecutionLevel": "highestAvailable",
|
|
||||||
"target": [
|
|
||||||
{
|
|
||||||
"target": "nsis",
|
|
||||||
"arch": [
|
|
||||||
"ia32"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"directories": {
|
|
||||||
"output": "electron"
|
|
||||||
},
|
|
||||||
"extraResources": [
|
|
||||||
{
|
|
||||||
"from": "src/assets/virtualBackground",
|
|
||||||
"to": "images",
|
|
||||||
"filter": [
|
|
||||||
"**/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nsis": {
|
|
||||||
"oneClick": false,
|
|
||||||
"installerIcon": "build/start.ico",
|
|
||||||
"uninstallerIcon": "build/start.ico",
|
|
||||||
"installerHeaderIcon": "build/start.ico",
|
|
||||||
"allowToChangeInstallationDirectory": true,
|
|
||||||
"createDesktopShortcut": true,
|
|
||||||
"createStartMenuShortcut": true,
|
|
||||||
"deleteAppDataOnUninstall": true,
|
|
||||||
"shortcutName": "智汇享",
|
|
||||||
"allowElevation": true,
|
|
||||||
"perMachine": true,
|
|
||||||
"include": "build/install.nsh"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
"deleteAppDataOnUninstall": true,
|
"deleteAppDataOnUninstall": true,
|
||||||
"shortcutName": "湖北襄阳四中教研平台",
|
"shortcutName": "湖北襄阳四中教研平台",
|
||||||
"allowElevation": true,
|
"allowElevation": true,
|
||||||
"perMachine": true,
|
"perMachine": true
|
||||||
"include": "build/install.nsh"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
231
main.js
|
|
@ -10,8 +10,6 @@ const {
|
||||||
dialog,
|
dialog,
|
||||||
crashReporter,
|
crashReporter,
|
||||||
desktopCapturer,
|
desktopCapturer,
|
||||||
powerSaveBlocker,
|
|
||||||
net
|
|
||||||
} = require('electron');
|
} = require('electron');
|
||||||
const path = require('node:path')
|
const path = require('node:path')
|
||||||
const updateJs = require('./src/utils/package/update')
|
const updateJs = require('./src/utils/package/update')
|
||||||
|
|
@ -19,20 +17,17 @@ const fs = require('fs');
|
||||||
const Registry = require('winreg');
|
const Registry = require('winreg');
|
||||||
const { autoUpdater, CancellationToken } = require('electron-updater');
|
const { autoUpdater, CancellationToken } = require('electron-updater');
|
||||||
const signalR = require('@microsoft/signalr');
|
const signalR = require('@microsoft/signalr');
|
||||||
const { setTimeout, setInterval } = require('timers');
|
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('timers');
|
||||||
const cancellationToken = new CancellationToken()
|
const cancellationToken = new CancellationToken()
|
||||||
app.allowRendererProcessReuse = false;
|
app.allowRendererProcessReuse = false;
|
||||||
let mainWindow = null;
|
let mainWindow = null;
|
||||||
let childWindow = {}
|
let childWindow = {}
|
||||||
let isMaximized = false;
|
let isMaximized = false;
|
||||||
let env = 'development'; //development production xy
|
let env;
|
||||||
let regKey;
|
let regKey;
|
||||||
let connection = null;
|
let connection = null;
|
||||||
|
let envStr;
|
||||||
let startNumber = 0;
|
let startNumber = 0;
|
||||||
let buildStatus = false; //true 打包开发版本 false 本地开发
|
|
||||||
powerSaveBlocker.start('prevent-display-sleep')
|
|
||||||
const id = powerSaveBlocker.start('prevent-display-sleep')
|
|
||||||
powerSaveBlocker.stop(id)
|
|
||||||
|
|
||||||
class AppWindow extends BrowserWindow {
|
class AppWindow extends BrowserWindow {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
|
|
@ -53,15 +48,12 @@ class AppWindow extends BrowserWindow {
|
||||||
const finalConfig = { ...basicConfig, ...config };
|
const finalConfig = { ...basicConfig, ...config };
|
||||||
super(finalConfig);
|
super(finalConfig);
|
||||||
if (env === 'development') {
|
if (env === 'development') {
|
||||||
if (buildStatus) {
|
// 开发
|
||||||
this.loadURL('http://192.168.2.9:8827/');
|
this.loadURL('http://localhost:3000');
|
||||||
} else {
|
|
||||||
this.loadURL('http://localhost:3000');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.loadURL('https://meeting-api.23544.com/')
|
// 测试 | 生产
|
||||||
|
this.loadFile(path.resolve(__dirname, './dist/index.html'));
|
||||||
}
|
}
|
||||||
// this.loadFile(path.resolve(__dirname, './dist/index.html'))
|
|
||||||
this.once('ready-to-show', () => {
|
this.once('ready-to-show', () => {
|
||||||
this.show();
|
this.show();
|
||||||
});
|
});
|
||||||
|
|
@ -70,21 +62,33 @@ class AppWindow extends BrowserWindow {
|
||||||
function quit() {
|
function quit() {
|
||||||
app.quit()
|
app.quit()
|
||||||
}
|
}
|
||||||
let tray;
|
|
||||||
// 检查网络状态
|
|
||||||
function checkNetworkStatus() {
|
|
||||||
if (!net.isOnline()) {
|
|
||||||
dialog.showErrorBox(`${env === 'xy' ? '湖北襄阳四中教研平台' : '智汇享'}-网络连接错误', '当前无网络连接,请检查您的网络设置。`);
|
|
||||||
app.quit();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
function createTray() {
|
function createTray() {
|
||||||
const iconPath = `${__dirname}/src/assets/${updateJs.getIcon(env)}.png`;
|
const iconPath = `${__dirname}/src/assets/${updateJs.getIcon(envStr)}.png`;
|
||||||
const trayIcon = nativeImage.createFromPath(iconPath);
|
const trayIcon = nativeImage.createFromPath(iconPath);
|
||||||
tray = new Tray(trayIcon);
|
const tray = new Tray(trayIcon);
|
||||||
tray.setToolTip(updateJs.getTitle(env));
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
|
{
|
||||||
|
label: '打开', click: () => {
|
||||||
|
mainWindow.webContents.send('isOpenWindows');
|
||||||
|
},
|
||||||
|
// icon: iconPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '最小化到系统托盘', click: () => {
|
||||||
|
mainWindow.hide();
|
||||||
|
},
|
||||||
|
// icon: iconPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '退出', click: async () => {
|
||||||
|
quit()
|
||||||
|
},
|
||||||
|
// icon: iconPath,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
tray.setToolTip(updateJs.getTitle(envStr));
|
||||||
|
tray.setContextMenu(contextMenu);
|
||||||
tray.on('click', () => {
|
tray.on('click', () => {
|
||||||
mainWindow.webContents.send('isOpenWindows');
|
mainWindow.webContents.send('isOpenWindows');
|
||||||
});
|
});
|
||||||
|
|
@ -93,21 +97,9 @@ function createTray() {
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
mainWindow = new AppWindow();
|
mainWindow = new AppWindow();
|
||||||
mainWindow.focus();
|
mainWindow.focus();
|
||||||
mainWindow.hookWindowMessage(278, function (e) {
|
|
||||||
mainWindow.setEnabled(false);//窗口禁用
|
|
||||||
setTimeout(() => {
|
|
||||||
mainWindow.setEnabled(true);//窗口启用
|
|
||||||
}, 100);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const additionalData = { myKey: 'myValue' }
|
const additionalData = { myKey: 'myValue' }
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
// 检查网络状态
|
|
||||||
if (!checkNetworkStatus()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// const gotTheLock = true
|
|
||||||
const gotTheLock = app.requestSingleInstanceLock(additionalData)
|
const gotTheLock = app.requestSingleInstanceLock(additionalData)
|
||||||
if (gotTheLock) {
|
if (gotTheLock) {
|
||||||
app.getPath('crashDumps')
|
app.getPath('crashDumps')
|
||||||
|
|
@ -115,14 +107,15 @@ app.on('ready', () => {
|
||||||
uploadToServer: false,
|
uploadToServer: false,
|
||||||
ignoreSystemCrashHandler: false
|
ignoreSystemCrashHandler: false
|
||||||
})
|
})
|
||||||
// if (!buildStatus) {
|
env = process.argv.find((arg) => arg.startsWith('--env='))?.split('=')[1];
|
||||||
// Object.defineProperty(app, 'isPackaged', {
|
if (env === 'development') {
|
||||||
// get() {
|
Object.defineProperty(app, 'isPackaged', {
|
||||||
// return true
|
get() {
|
||||||
// }
|
return true
|
||||||
// })
|
}
|
||||||
// autoUpdater.updateConfigPath = path.join('latest.yml')
|
})
|
||||||
// }
|
autoUpdater.updateConfigPath = path.join('latest.yml')
|
||||||
|
}
|
||||||
createWindow()
|
createWindow()
|
||||||
regKey = new Registry({
|
regKey = new Registry({
|
||||||
hive: Registry.HKCU,
|
hive: Registry.HKCU,
|
||||||
|
|
@ -143,12 +136,6 @@ app.on('ready', () => {
|
||||||
mainWindow.webContents.openDevTools()
|
mainWindow.webContents.openDevTools()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mainWindow.on('focus', () => {
|
|
||||||
mainWindow.show()
|
|
||||||
});
|
|
||||||
mainWindow.on('maximize', () => {
|
|
||||||
mainWindow.show()
|
|
||||||
});
|
|
||||||
// 监听移动
|
// 监听移动
|
||||||
mainWindow.on('move', () => {
|
mainWindow.on('move', () => {
|
||||||
// 如果是全屏自动恢复到上次窗口大小
|
// 如果是全屏自动恢复到上次窗口大小
|
||||||
|
|
@ -160,20 +147,17 @@ app.on('ready', () => {
|
||||||
isMaximized = true;
|
isMaximized = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ipcMain.handle('startLoad', (event) => {
|
ipcMain.handle('setEnv', (event, str) => {
|
||||||
|
envStr = str;
|
||||||
if (startNumber === 0) {
|
if (startNumber === 0) {
|
||||||
updateHandle() // 检查更新
|
updateHandle() // 检查更新
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
autoUpdater.checkForUpdates()
|
updateHandle() // 每一小时检查更新
|
||||||
}, 1000 * 60 * 60)
|
}, 1000 * 60 * 60)
|
||||||
createTray()
|
createTray()
|
||||||
startNumber++
|
startNumber++
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 更新
|
|
||||||
ipcMain.handle('updateHandle', () => {
|
|
||||||
autoUpdater.checkForUpdates()
|
|
||||||
});
|
|
||||||
// socket
|
// socket
|
||||||
ipcMain.handle('startSignalr', (event, user) => {
|
ipcMain.handle('startSignalr', (event, user) => {
|
||||||
startSignalr(user)
|
startSignalr(user)
|
||||||
|
|
@ -198,11 +182,6 @@ app.on('ready', () => {
|
||||||
connection.off('SetDriver');
|
connection.off('SetDriver');
|
||||||
connection.off('ShowDriverList');
|
connection.off('ShowDriverList');
|
||||||
connection.off('ModifyNickName');
|
connection.off('ModifyNickName');
|
||||||
connection.off('JoinChannelCallback');
|
|
||||||
connection.off('ExitSharedScreen');
|
|
||||||
connection.off('SetSpeaker');
|
|
||||||
connection.off('ReceivedOperation');
|
|
||||||
connection.off('StopedSharedScreen');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ipcMain.handle('onStop', (event) => {
|
ipcMain.handle('onStop', (event) => {
|
||||||
|
|
@ -222,7 +201,8 @@ app.on('ready', () => {
|
||||||
await connection.invoke(str, data.roomNum, data.msg)
|
await connection.invoke(str, data.roomNum, data.msg)
|
||||||
break;
|
break;
|
||||||
case 'sendOper':
|
case 'sendOper':
|
||||||
await connection.invoke(str, data.roomNum, data.contentString)
|
// 4:屏幕共享
|
||||||
|
await connection.invoke(str, data.roomNum, data.type)
|
||||||
break;
|
break;
|
||||||
case 'getDrivers':
|
case 'getDrivers':
|
||||||
// 获取某个人的设备列表
|
// 获取某个人的设备列表
|
||||||
|
|
@ -237,21 +217,13 @@ app.on('ready', () => {
|
||||||
await connection.invoke(str, data.uid, data.driversJsonString)
|
await connection.invoke(str, data.uid, data.driversJsonString)
|
||||||
break;
|
break;
|
||||||
case 'joinChannel':
|
case 'joinChannel':
|
||||||
// 加入房间
|
// 设置某个人的设备列表
|
||||||
await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera, data.isRoomManager || false)
|
await connection.invoke(str, data.roomNum, data.enableMicr, data.enableCamera, data.isRoomManager || false)
|
||||||
break;
|
break;
|
||||||
case 'levelChannel':
|
case 'levelChannel':
|
||||||
// 退出房间
|
// 设置某个人的设备列表
|
||||||
await connection.invoke(str, data.roomNum)
|
await connection.invoke(str, data.roomNum)
|
||||||
break;
|
break;
|
||||||
case 'SetSpeakerCallback':
|
|
||||||
// 发言人设置成功
|
|
||||||
await connection.invoke(str, data)
|
|
||||||
break;
|
|
||||||
case 'sendOper2User':
|
|
||||||
// 扩展参数
|
|
||||||
await connection.invoke(str, data.uid, data.contentString)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ipcMain.handle('onOtherSignalr', (event) => {
|
ipcMain.handle('onOtherSignalr', (event) => {
|
||||||
|
|
@ -282,10 +254,10 @@ app.on('ready', () => {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
// 扩展操作
|
// 扩展操作
|
||||||
connection.on("Operation", (contentString) => {
|
connection.on("Operation", (type) => {
|
||||||
mainWindow.webContents.send('onSignalr', {
|
mainWindow.webContents.send('onSignalr', {
|
||||||
key: 'Operation',
|
key: 'Operation',
|
||||||
contentString
|
type
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
// 移出会议
|
// 移出会议
|
||||||
|
|
@ -407,40 +379,6 @@ app.on('ready', () => {
|
||||||
nickName
|
nickName
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
// 加入房间回调
|
|
||||||
connection.on("JoinChannelCallback", (isSuccess) => {
|
|
||||||
mainWindow.webContents.send('onSignalr', {
|
|
||||||
key: 'JoinChannelCallback',
|
|
||||||
isSuccess,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
// 退出共享
|
|
||||||
connection.on("ExitSharedScreen", () => {
|
|
||||||
mainWindow.webContents.send('onSignalr', {
|
|
||||||
key: 'ExitSharedScreen'
|
|
||||||
})
|
|
||||||
});
|
|
||||||
// 设置发言人
|
|
||||||
connection.on("SetSpeaker", (RoomManagerInputDTO) => {
|
|
||||||
mainWindow.webContents.send('onSignalr', {
|
|
||||||
key: 'SetSpeaker',
|
|
||||||
RoomManagerInputDTO
|
|
||||||
})
|
|
||||||
});
|
|
||||||
// 扩展参数
|
|
||||||
connection.on("ReceivedOperation", (contentString) => {
|
|
||||||
mainWindow.webContents.send('onSignalr', {
|
|
||||||
key: 'ReceivedOperation',
|
|
||||||
contentString
|
|
||||||
})
|
|
||||||
});
|
|
||||||
// 共享人取消共享屏幕
|
|
||||||
connection.on("StopedSharedScreen", (ScreenShareId) => {
|
|
||||||
mainWindow.webContents.send('onSignalr', {
|
|
||||||
key: 'StopedSharedScreen',
|
|
||||||
ScreenShareId
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 放大缩小退出窗口
|
// 放大缩小退出窗口
|
||||||
|
|
@ -482,10 +420,6 @@ app.on('ready', () => {
|
||||||
ipcMain.handle('getVersion', () => {
|
ipcMain.handle('getVersion', () => {
|
||||||
return app.getVersion();
|
return app.getVersion();
|
||||||
});
|
});
|
||||||
// 获取环境
|
|
||||||
ipcMain.handle('getEnv', () => {
|
|
||||||
return env;
|
|
||||||
});
|
|
||||||
// 获取窗口是否显示
|
// 获取窗口是否显示
|
||||||
ipcMain.handle('isVisible', () => {
|
ipcMain.handle('isVisible', () => {
|
||||||
return mainWindow.isVisible();
|
return mainWindow.isVisible();
|
||||||
|
|
@ -521,11 +455,6 @@ app.on('ready', () => {
|
||||||
downloadUpdate()
|
downloadUpdate()
|
||||||
} else if (data === '2') { // 下载完成 点击安装
|
} else if (data === '2') { // 下载完成 点击安装
|
||||||
quitAndInstall()
|
quitAndInstall()
|
||||||
} else if (data === '3') { // 打开弹窗
|
|
||||||
let message = JSON.stringify({
|
|
||||||
type: '3',
|
|
||||||
})
|
|
||||||
sendUpdateMessage(message)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 选择文件夹
|
// 选择文件夹
|
||||||
|
|
@ -560,32 +489,9 @@ app.on('ready', () => {
|
||||||
// 设置桌面应用基础属性
|
// 设置桌面应用基础属性
|
||||||
ipcMain.handle('setMainWindowSize', (event, config) => {
|
ipcMain.handle('setMainWindowSize', (event, config) => {
|
||||||
if (config.width === 250) {
|
if (config.width === 250) {
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
|
||||||
{
|
|
||||||
label: '退出',
|
|
||||||
click: () => quit(),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
tray.setContextMenu(contextMenu);
|
|
||||||
mainWindow.setSkipTaskbar(true)
|
mainWindow.setSkipTaskbar(true)
|
||||||
mainWindow.setResizable(false)
|
mainWindow.setResizable(false)
|
||||||
mainWindow.setAlwaysOnTop(true, 'screen-saver')
|
mainWindow.setAlwaysOnTop(true, 'screen-saver')
|
||||||
} else {
|
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
|
||||||
{
|
|
||||||
label: '打开',
|
|
||||||
click: () => mainWindow.webContents.send('isOpenWindows'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '最小化到系统托盘',
|
|
||||||
click: () => mainWindow.hide(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '退出',
|
|
||||||
click: () => quit(),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
tray.setContextMenu(contextMenu);
|
|
||||||
}
|
}
|
||||||
// 设置最小窗口尺寸
|
// 设置最小窗口尺寸
|
||||||
mainWindow.setMinimumSize(config.width, config.height);
|
mainWindow.setMinimumSize(config.width, config.height);
|
||||||
|
|
@ -643,26 +549,13 @@ app.on('ready', () => {
|
||||||
width: config.width,
|
width: config.width,
|
||||||
height: config.height,
|
height: config.height,
|
||||||
})
|
})
|
||||||
if (env === 'development') {
|
if (envStr === 'development') {
|
||||||
// 开发
|
// 开发
|
||||||
if (buildStatus) {
|
child.loadURL(config.url)
|
||||||
child.loadURL(`http://192.168.2.9:8827/#/${config.key}`);
|
|
||||||
// child.loadURL(`file://${path.join(__dirname, './dist/index.html')}#/${config.key}`);
|
|
||||||
} else {
|
|
||||||
child.loadURL(config.url)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 测试 | 生产
|
// 测试 | 生产
|
||||||
child.loadURL(`https://meeting-api.23544.com/#/${config.key}`);
|
child.loadURL(`file://${path.join(__dirname, './dist/index.html')}#/${config.key}`);
|
||||||
// child.loadURL(`file://${path.join(__dirname, './dist/index.html')}#/${config.key}`);
|
|
||||||
}
|
}
|
||||||
child.hookWindowMessage(278, function (e) {
|
|
||||||
child.setEnabled(false);//窗口禁用
|
|
||||||
setTimeout(() => {
|
|
||||||
child.setEnabled(true);//窗口启用
|
|
||||||
}, 100);
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
childWindow[config.key] = child
|
childWindow[config.key] = child
|
||||||
child.once('ready-to-show', () => {
|
child.once('ready-to-show', () => {
|
||||||
if (config.show) {
|
if (config.show) {
|
||||||
|
|
@ -756,6 +649,7 @@ app.on('ready', () => {
|
||||||
});
|
});
|
||||||
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
||||||
function updateHandle() {
|
function updateHandle() {
|
||||||
|
autoUpdater.checkForUpdates()
|
||||||
// autoUpdater.checkForUpdatesAndNotify().catch();
|
// autoUpdater.checkForUpdatesAndNotify().catch();
|
||||||
const message = {
|
const message = {
|
||||||
error: '检查更新出错',
|
error: '检查更新出错',
|
||||||
|
|
@ -763,26 +657,23 @@ function updateHandle() {
|
||||||
updateAva: '检测到新版本,正在下载……',
|
updateAva: '检测到新版本,正在下载……',
|
||||||
updateNotAva: '已经是最新版本,不用更新'
|
updateNotAva: '已经是最新版本,不用更新'
|
||||||
}
|
}
|
||||||
autoUpdater.setFeedURL(updateJs.getUpdateUrl(env))
|
autoUpdater.setFeedURL(updateJs.getUpdateUrl(envStr))
|
||||||
autoUpdater.autoDownload = false // 不自动下载安装包
|
autoUpdater.autoDownload = false // 不自动下载安装包
|
||||||
autoUpdater.autoInstallOnAppQuit = false // 不自动安装
|
autoUpdater.autoInstallOnAppQuit = false // 不自动安装
|
||||||
autoUpdater.on('error', function (error) {
|
autoUpdater.on('error', function (error) {
|
||||||
sendUpdateMessage(error)
|
sendUpdateMessage(message.error)
|
||||||
})
|
})
|
||||||
autoUpdater.on('checking-for-update', function () {
|
autoUpdater.on('checking-for-update', function () {
|
||||||
sendUpdateMessage(message.checking)
|
sendUpdateMessage(message.checking)
|
||||||
})
|
})
|
||||||
autoUpdater.on('update-available', function (info) {
|
autoUpdater.on('update-available', function (info) {
|
||||||
let messageStr = JSON.stringify({ type: '0' })
|
let messageStr = JSON.stringify({ type: '0' })
|
||||||
sendUpdateMessage(messageStr)
|
setTimeout(() => {
|
||||||
mainWindow.webContents.send('changeLocalStorage', {
|
sendUpdateMessage(messageStr)
|
||||||
isUpdate: true,
|
}, 5000)
|
||||||
});
|
|
||||||
})
|
})
|
||||||
autoUpdater.on('update-not-available', function (info) {
|
autoUpdater.on('update-not-available', function (info) {
|
||||||
mainWindow.webContents.send('changeLocalStorage', {
|
|
||||||
isUpdate: false,
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
// 更新下载进度事件
|
// 更新下载进度事件
|
||||||
autoUpdater.on('download-progress', function (progressObj) {
|
autoUpdater.on('download-progress', function (progressObj) {
|
||||||
|
|
@ -855,7 +746,7 @@ function mainWindowCenter() {
|
||||||
|
|
||||||
const startSignalr = async (user) => {
|
const startSignalr = async (user) => {
|
||||||
connection = new signalR.HubConnectionBuilder()
|
connection = new signalR.HubConnectionBuilder()
|
||||||
.withUrl(`${env === 'development' ? 'http://192.168.2.9:5192' : 'https://meeting-api.23544.com/pc'}/session-manage`, {
|
.withUrl(`${envStr === 'development' ? 'http://192.168.2.9:5192' : 'https://meeting-api.23544.com/pc'}/session-manage`, {
|
||||||
skipNegotiation: true,
|
skipNegotiation: true,
|
||||||
transport: signalR.HttpTransportType.WebSockets,
|
transport: signalR.HttpTransportType.WebSockets,
|
||||||
accessTokenFactory: () => user.token
|
accessTokenFactory: () => user.token
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "WGShare.Metting",
|
"name": "WGShare.Metting",
|
||||||
"version": "0.7.1",
|
"version": "0.4.8",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "WGShare.Metting",
|
"name": "WGShare.Metting",
|
||||||
"version": "0.7.1",
|
"version": "0.4.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^5.3.7",
|
"@ant-design/icons": "^5.3.7",
|
||||||
"@microsoft/signalr": "^8.0.0",
|
"@microsoft/signalr": "^8.0.0",
|
||||||
"@types/node": "^20.14.9",
|
"@types/node": "^20.14.9",
|
||||||
"agora-electron-sdk": "4.4.0",
|
"agora-electron-sdk": "^4.4.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"antd": "^5.18.2",
|
"antd": "^5.18.2",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"electron-squirrel-startup": "^1.0.1",
|
"electron-squirrel-startup": "^1.0.1",
|
||||||
"electron-updater": "^6.2.1",
|
"electron-updater": "^6.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
|
||||||
"os": "^0.1.2",
|
"os": "^0.1.2",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
||||||
|
|
|
||||||
17
package.json
|
|
@ -1,17 +1,21 @@
|
||||||
{
|
{
|
||||||
"name": "WGShare.Metting",
|
"name": "WGShare.Metting",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.8.0",
|
"version": "0.6.3",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"authors": "yj",
|
"authors": "yj",
|
||||||
"description": "智汇享",
|
"description": "智汇享",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "concurrently \"electron .\" \"cross-env BROWSER=none vite\"",
|
"dev": "concurrently \"electron . --env=development\" \"cross-env BROWSER=none vite\"",
|
||||||
"build": "vite build",
|
"prod": "concurrently \"electron . --env=production\" \"cross-env BROWSER=none vite\"",
|
||||||
|
"xy": "concurrently \"electron . --env=xy\" \"cross-env BROWSER=none vite\"",
|
||||||
|
"build": "vite build --mode development",
|
||||||
|
"build:prod": "vite build --mode production",
|
||||||
|
"build:xy": "vite build --mode xy",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"build:dev": "vite build & electron-builder -w --config=./config/development.json",
|
"build:dev-win": "vite build --mode development & electron-builder -w --config=./config/build.json",
|
||||||
"build:prod": "vite build & electron-builder -w --config=./config/production.json",
|
"build:prod-win": "vite build --mode production & electron-builder -w --config=./config/build.json",
|
||||||
"build:xy": "vite build & electron-builder -w --config=./config/xy.json"
|
"build:prod-win-xy": "vite build --mode xy & electron-builder -w --config=./config/xy.json"
|
||||||
},
|
},
|
||||||
"agora_electron": {
|
"agora_electron": {
|
||||||
"platform": "win32",
|
"platform": "win32",
|
||||||
|
|
@ -30,7 +34,6 @@
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"electron-squirrel-startup": "^1.0.1",
|
"electron-squirrel-startup": "^1.0.1",
|
||||||
"electron-updater": "^6.2.1",
|
"electron-updater": "^6.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
|
||||||
"os": "^0.1.2",
|
"os": "^0.1.2",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
||||||
|
|
|
||||||
16
preload.js
|
|
@ -51,10 +51,6 @@ window.electron = {
|
||||||
getVersion: () => {
|
getVersion: () => {
|
||||||
return ipcRenderer.invoke('getVersion')
|
return ipcRenderer.invoke('getVersion')
|
||||||
},
|
},
|
||||||
// 获取环境
|
|
||||||
getEnv: () => {
|
|
||||||
return ipcRenderer.invoke('getEnv')
|
|
||||||
},
|
|
||||||
// 获取窗口是否显示
|
// 获取窗口是否显示
|
||||||
isVisible: () => {
|
isVisible: () => {
|
||||||
return ipcRenderer.invoke('isVisible')
|
return ipcRenderer.invoke('isVisible')
|
||||||
|
|
@ -91,13 +87,9 @@ window.electron = {
|
||||||
isOpenWindows: (callback) => {
|
isOpenWindows: (callback) => {
|
||||||
ipcRenderer.on('isOpenWindows', callback)
|
ipcRenderer.on('isOpenWindows', callback)
|
||||||
},
|
},
|
||||||
// 首次加载
|
// 设置环境变量
|
||||||
startLoad: () => {
|
setEnv: (str) => {
|
||||||
ipcRenderer.invoke('startLoad')
|
ipcRenderer.invoke('setEnv', str)
|
||||||
},
|
|
||||||
// 更新
|
|
||||||
updateHandle: () => {
|
|
||||||
ipcRenderer.invoke('updateHandle')
|
|
||||||
},
|
},
|
||||||
// 通知下载最新的包
|
// 通知下载最新的包
|
||||||
onDownload: (type) => {
|
onDownload: (type) => {
|
||||||
|
|
@ -138,7 +130,7 @@ window.electron = {
|
||||||
ipcRenderer.invoke('createChildWindow', {
|
ipcRenderer.invoke('createChildWindow', {
|
||||||
url: location.origin + `/#/noticeWindow`,
|
url: location.origin + `/#/noticeWindow`,
|
||||||
width: 388,
|
width: 388,
|
||||||
height: 180,
|
height: 150,
|
||||||
key: 'noticeWindow',
|
key: 'noticeWindow',
|
||||||
})
|
})
|
||||||
ipcRenderer.invoke('createChildWindow', {
|
ipcRenderer.invoke('createChildWindow', {
|
||||||
|
|
|
||||||
91
src/App.tsx
|
|
@ -8,21 +8,20 @@ import Login from '@/page/Login/index'
|
||||||
import Meeting from '@/page/Meeting/index'
|
import Meeting from '@/page/Meeting/index'
|
||||||
import NotFound from '@/page/NotFound/index'
|
import NotFound from '@/page/NotFound/index'
|
||||||
import { storage } from '@/utils'
|
import { storage } from '@/utils'
|
||||||
import { message, Modal, Spin } from "antd";
|
import { message, Spin } from "antd";
|
||||||
import JoinMeetingModal from "@/components/JoinMeetingModal";
|
import JoinMeetingModal from "@/components/JoinMeetingModal";
|
||||||
import UpdateModal from "@/components/UpdateModal";
|
import UpdateModal from "@/components/UpdateModal";
|
||||||
import * as CryptoJS from 'crypto-js';
|
import * as CryptoJS from 'crypto-js';
|
||||||
import { GetCheckOnline, PostLogin } from "@/api/Login";
|
import { PostLogin } from "@/api/Login";
|
||||||
import { agora } from "@/utils/package/agora";
|
import { agora } from "@/utils/package/agora";
|
||||||
import QuitTips from "@/components/QuitTips";
|
import QuitTips from "@/components/QuitTips";
|
||||||
|
import { GetLeave } from "@/api/Meeting";
|
||||||
import ShareScreenWindow from "@/page/Meeting/ShareScreenWindow";
|
import ShareScreenWindow from "@/page/Meeting/ShareScreenWindow";
|
||||||
import UserListWindow from "@/page/Meeting/UserListWindow";
|
import UserListWindow from "@/page/Meeting/UserListWindow";
|
||||||
import ChatSmallWindow from "@/page/Meeting/ChatSmallWindow";
|
import ChatSmallWindow from "@/page/Meeting/ChatSmallWindow";
|
||||||
import ChatBigWindow from "@/page/Meeting/ChatBigWindow";
|
import ChatBigWindow from "@/page/Meeting/ChatBigWindow";
|
||||||
import NoticeWindow from "@/page/Meeting/NoticeWindow";
|
import NoticeWindow from "@/page/Meeting/NoticeWindow";
|
||||||
import { getKeyOpenChildWindow, getTitle, setKeyOpenChildWindow, storageSeeting } from "./utils/package/public";
|
import { getKeyOpenChildWindow, getTitle, setKeyOpenChildWindow, storageSeeting } from "./utils/package/public";
|
||||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
|
||||||
const { confirm } = Modal;
|
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
@ -42,43 +41,20 @@ const App: React.FC = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let userInfo = JSON.parse(storage.getItem('user') as string)
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
||||||
const login = () => {
|
window.electron.setEnv(import.meta.env.VITE_ENV);
|
||||||
PostLogin({
|
|
||||||
account: loginInfo.account,
|
|
||||||
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
|
||||||
}).then(async (res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
storage.setItem('user', JSON.stringify(res.data))
|
|
||||||
storage.setItem('userLogin', true)
|
|
||||||
toSrc('/home')
|
|
||||||
await window.electron.startSignalr(res.data)
|
|
||||||
} else {
|
|
||||||
toSrc('/login')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (userInfo && !userInfo.isAnonymous) {
|
if (userInfo && !userInfo.isAnonymous) {
|
||||||
if (loginInfo && loginInfo.isAutoLogin) {
|
if (loginInfo && loginInfo.isAutoLogin) {
|
||||||
GetCheckOnline(loginInfo.account).then(req => {
|
PostLogin({
|
||||||
if (req.code === 200) {
|
account: loginInfo.account,
|
||||||
if (req.data) {
|
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
||||||
confirm({
|
}).then(async (res) => {
|
||||||
title: '提示',
|
if (res.code === 200) {
|
||||||
icon: <ExclamationCircleFilled />,
|
storage.setItem('user', JSON.stringify(res.data))
|
||||||
content: `账号已在其他地方登录,是否强制登陆?`,
|
storage.setItem('userLogin', true)
|
||||||
centered: true,
|
toSrc('/home')
|
||||||
okText: '确定',
|
await window.electron.startSignalr(res.data)
|
||||||
cancelText: '取消',
|
} else {
|
||||||
async onOk() {
|
toSrc('/login')
|
||||||
login()
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
toSrc('/login')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
login()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -103,7 +79,6 @@ const App: React.FC = () => {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.electron.startLoad();
|
|
||||||
window.electron.downFile(async (_e: any, data: any) => {
|
window.electron.downFile(async (_e: any, data: any) => {
|
||||||
const response = await fetch(data.filePath);
|
const response = await fetch(data.filePath);
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
|
@ -152,7 +127,9 @@ const App: React.FC = () => {
|
||||||
}, [])
|
}, [])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.electron.onUpdate((_e: any, data: any) => {
|
window.electron.onUpdate((_e: any, data: any) => {
|
||||||
updateModalRef.current.changeModal(data)
|
if (location.hash.indexOf('/meeting') === -1) {
|
||||||
|
updateModalRef.current.changeModal(data)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if (!storage.getItem('setting')) {
|
if (!storage.getItem('setting')) {
|
||||||
storage.setItem('setting', JSON.stringify(storageSeeting))
|
storage.setItem('setting', JSON.stringify(storageSeeting))
|
||||||
|
|
@ -187,24 +164,16 @@ const App: React.FC = () => {
|
||||||
if (location.href.indexOf('/login') !== -1) {
|
if (location.href.indexOf('/login') !== -1) {
|
||||||
window.electron.onStop()
|
window.electron.onStop()
|
||||||
}
|
}
|
||||||
if (location.hash && location.hash.indexOf('/meeting') === -1) {
|
|
||||||
window.electron.updateHandle()
|
|
||||||
}
|
|
||||||
message.destroy('cameraTemporarily')
|
message.destroy('cameraTemporarily')
|
||||||
}, [navigate])
|
}, [navigate])
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('keydown', async (event) => {
|
document.addEventListener('keydown', (event) => {
|
||||||
if (event.keyCode == 122) {
|
if (event.key === 'F11') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (((event.ctrlKey && event.keyCode == 82) || event.keyCode == 116)) {
|
|
||||||
let env = await window.electron.getEnv()
|
|
||||||
if (env !== 'development') {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
getTitle()
|
document.getElementsByTagName('title')[0].innerText = getTitle(import.meta.env.VITE_ENV)
|
||||||
}, [])
|
}, [])
|
||||||
const handleResize = (): void => {
|
const handleResize = (): void => {
|
||||||
setWindowSize({
|
setWindowSize({
|
||||||
|
|
@ -231,10 +200,8 @@ const App: React.FC = () => {
|
||||||
if (item.msg) {
|
if (item.msg) {
|
||||||
message.error(item.msg)
|
message.error(item.msg)
|
||||||
}
|
}
|
||||||
await leaveChannel()
|
await leaveChannel(true)
|
||||||
setTimeout(() => {
|
toSrc('/login')
|
||||||
toSrc('/login')
|
|
||||||
}, 5000);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -256,7 +223,7 @@ const App: React.FC = () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
const leaveChannel = async (): Promise<void> => {
|
const leaveChannel = async (bool?: boolean): Promise<void> => {
|
||||||
if (location.hash.indexOf('/meeting') === 1) {
|
if (location.hash.indexOf('/meeting') === 1) {
|
||||||
window.electron.closeChildWindow('shareScreenWindow')
|
window.electron.closeChildWindow('shareScreenWindow')
|
||||||
setKeyOpenChildWindow('shareScreenWindow', false)
|
setKeyOpenChildWindow('shareScreenWindow', false)
|
||||||
|
|
@ -273,9 +240,11 @@ const App: React.FC = () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const data = JSON.parse(localStorage.stateInfo);
|
const data = JSON.parse(localStorage.stateInfo);
|
||||||
await window.electron.onInvoke('levelChannel', {
|
if (!bool) {
|
||||||
roomNum: data.channelId
|
await GetLeave({
|
||||||
})
|
roomNum: data.channelId,
|
||||||
|
})
|
||||||
|
}
|
||||||
await agora.leaveChannel()
|
await agora.leaveChannel()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -291,8 +260,6 @@ const App: React.FC = () => {
|
||||||
storage.removeItem('user')
|
storage.removeItem('user')
|
||||||
navigate('/login')
|
navigate('/login')
|
||||||
}
|
}
|
||||||
} else if (e.key === 'env') {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,6 @@ export const GetRoom = (data: { pageIndex: number, pageSize: number }) =>
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
|
|
||||||
export const PostFeedback = (data: any) =>
|
|
||||||
request({
|
|
||||||
url: `/home/feedback`,
|
|
||||||
method: 'post',
|
|
||||||
data,
|
|
||||||
})
|
|
||||||
export const PostRoom = (data: any) =>
|
export const PostRoom = (data: any) =>
|
||||||
request({
|
request({
|
||||||
url: `/home/room`,
|
url: `/home/room`,
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,4 @@ export const PostAnonLogin = (data: any) =>
|
||||||
url: `/auth/anon-login`,
|
url: `/auth/anon-login`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
})
|
|
||||||
|
|
||||||
export const GetCheckOnline = (account: string) =>
|
|
||||||
request({
|
|
||||||
url: `/auth/check-online?account=${account}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
})
|
||||||
|
|
@ -71,20 +71,14 @@ export const PostRoomManager = (data: any) =>
|
||||||
request({
|
request({
|
||||||
url: `/room/manager`,
|
url: `/room/manager`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: {
|
data
|
||||||
...data,
|
|
||||||
SettingUserId: ''
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const DeleteRoomManager = (data: any) =>
|
export const DeleteRoomManager = (data: any) =>
|
||||||
request({
|
request({
|
||||||
url: `/room/manager`,
|
url: `/room/manager`,
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
data: {
|
data
|
||||||
...data,
|
|
||||||
SettingUserId: ''
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export const GetRoomKickout = (roomNum: string, kickUid: string) =>
|
export const GetRoomKickout = (roomNum: string, kickUid: string) =>
|
||||||
|
|
@ -160,25 +154,4 @@ export const PutAlterUname = (data: any) =>
|
||||||
url: `/room/alter-uname`,
|
url: `/room/alter-uname`,
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data
|
data
|
||||||
})
|
|
||||||
export const GetSharedScreen = (roomNum: string) =>
|
|
||||||
request({
|
|
||||||
url: `/room/shared-screen?roomNum=${roomNum}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
export const PostSharedScreen = (roomNum: string) =>
|
|
||||||
request({
|
|
||||||
url: `/room/shared-screen?roomNum=${roomNum}`,
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
export const PostStopSharedScreen = (roomNum: string) =>
|
|
||||||
request({
|
|
||||||
url: `/room/stop-shared-screen?roomNum=${roomNum}`,
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
export const PostHomeVerLog = (data: any) =>
|
|
||||||
request({
|
|
||||||
url: `/home/ver-log`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
})
|
||||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 712 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 838 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 600 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 921 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 1.2 MiB |
|
|
@ -1,5 +1,5 @@
|
||||||
import styles from '@/components/Avatar/index.module.scss'
|
import styles from '@/components/Avatar/index.module.scss'
|
||||||
import { memo, useImperativeHandle, forwardRef } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
const Avatar = forwardRef((props: any, ref: any) => {
|
const Avatar = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
getData: () => {
|
getData: () => {
|
||||||
|
|
@ -15,4 +15,4 @@ const Avatar = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(Avatar)
|
export default Avatar
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
|
||||||
import { Empty, Popover } from 'antd';
|
|
||||||
import { GetQrcode } from '@/api/Home/Index';
|
|
||||||
import { memo, useImperativeHandle, forwardRef, useState } from "react";
|
|
||||||
const Code = forwardRef((props: any, ref: any) => {
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
getData: () => {
|
|
||||||
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
const [baseImage, setBaseImage] = useState('');
|
|
||||||
const [roomNum, setRoomNum] = useState(props.roomNum);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Popover
|
|
||||||
placement="bottom"
|
|
||||||
onOpenChange={async (e: boolean) => {
|
|
||||||
setBaseImage('')
|
|
||||||
if (e) {
|
|
||||||
let env = await window.electron.getEnv()
|
|
||||||
GetQrcode(roomNum, env === 'development' ? 'trial' : 'release').then(res => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
setBaseImage(res.data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
content={
|
|
||||||
baseImage ? <div>
|
|
||||||
<img style={{ width: '200px', margin: '0 auto' }} src={`data:image/png;base64,${baseImage}`} alt="" />
|
|
||||||
<div style={{ color: 'white', textAlign: 'center', fontSize: '16px', marginTop: '10px' }}>
|
|
||||||
<span>微信中长按图片识别小程序码</span><br />
|
|
||||||
<span>加入会议</span>
|
|
||||||
</div>
|
|
||||||
</div> : <div>
|
|
||||||
<Empty description={'二维码加载中,请稍后'} />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div title='小程序'>
|
|
||||||
<img src={ImageUrl.icon55} alt="" style={{ width: '16px' }} />
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default memo(Code)
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import styles from '@/components/EquipmentManagement/index.module.scss'
|
import styles from '@/components/EquipmentManagement/index.module.scss'
|
||||||
import { getKeyOpenChildWindow } from '@/utils/package/public';
|
import { getKeyOpenChildWindow } from '@/utils/package/public';
|
||||||
import { Button, Modal, Select, Slider, message } from 'antd';
|
import { Button, Modal, Select, Slider, message } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
const EquipmentManagement = forwardRef((props: any, ref: any) => {
|
const EquipmentManagement = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
changeModal: async (uid: string, userName: string) => {
|
changeModal: async (uid: string, userName: string) => {
|
||||||
|
|
@ -116,4 +116,4 @@ const EquipmentManagement = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(EquipmentManagement)
|
export default EquipmentManagement
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
.feedBackModel {
|
|
||||||
max-height: 80vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.feedBackModelContent {
|
|
||||||
flex-grow: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
margin: 10px 0;
|
|
||||||
|
|
||||||
.feedBackModelContentRate {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
background-color: #101215;
|
|
||||||
padding: 10px 20px 30px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedBackModelContentList {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
>div:nth-child(2) {
|
|
||||||
>div {
|
|
||||||
background-color: #101215;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #7F859B;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px transparent solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.active {
|
|
||||||
color: white;
|
|
||||||
border: 1px #495EAD solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.feedBackModelFooter {
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
import { PostFeedback } from '@/api/Home/Index';
|
|
||||||
import styles from '@/components/FeedBackModel/index.module.scss'
|
|
||||||
import { Button, message, Modal, Rate } from 'antd';
|
|
||||||
import TextArea from 'antd/es/input/TextArea';
|
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
|
||||||
const FeedBackModel = forwardRef((_props: any, ref: any) => {
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
changeModal: () => {
|
|
||||||
setIsFeedBackModel(true)
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
const [isFeedBackModel, setIsFeedBackModel] = useState(false);
|
|
||||||
const [feedBackForm, setFeedBackForm] = useState({
|
|
||||||
rateValue: 0,
|
|
||||||
otherContent: '',
|
|
||||||
});
|
|
||||||
const [feedBackList, setFeedBackList] = useState([
|
|
||||||
{
|
|
||||||
text: "软件卡顿",
|
|
||||||
value: 2,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "设计不合理",
|
|
||||||
value: 3,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "功能太少",
|
|
||||||
value: 4,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "通话不流畅",
|
|
||||||
value: 5,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "视频卡顿",
|
|
||||||
value: 6,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "操作麻烦",
|
|
||||||
value: 7,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "其他,需要手动填写",
|
|
||||||
value: 1,
|
|
||||||
active: false,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal
|
|
||||||
title="反馈建议评分"
|
|
||||||
open={isFeedBackModel}
|
|
||||||
footer={null}
|
|
||||||
destroyOnClose={true}
|
|
||||||
onCancel={() => setIsFeedBackModel(false)}
|
|
||||||
centered
|
|
||||||
width={'500px'}
|
|
||||||
>
|
|
||||||
<div className={styles.feedBackModel}>
|
|
||||||
<div className={styles.feedBackModelContent}>
|
|
||||||
<div className={styles.feedBackModelContentRate}>
|
|
||||||
<div style={{ color: 'white', fontSize: '14px', marginBottom: '4px' }}>评分:</div>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'center' }}>
|
|
||||||
<Rate value={feedBackForm.rateValue} allowHalf style={{ transform: 'scale(2)' }} allowClear onChange={(e) => {
|
|
||||||
setFeedBackForm({
|
|
||||||
...feedBackForm,
|
|
||||||
rateValue: e
|
|
||||||
})
|
|
||||||
}} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.feedBackModelContentList}>
|
|
||||||
<div style={{ color: 'white', fontSize: '14px', marginBottom: '4px' }}>建议:</div>
|
|
||||||
<div>
|
|
||||||
{
|
|
||||||
feedBackList.map((item, index) => {
|
|
||||||
return (
|
|
||||||
<div key={index} className={item.active ? styles.active : ''} onClick={() => {
|
|
||||||
const feedBackListTemp = [...feedBackList]
|
|
||||||
feedBackListTemp[index].active = !feedBackListTemp[index].active
|
|
||||||
setFeedBackList(feedBackListTemp)
|
|
||||||
}}>
|
|
||||||
<span>{item.text}</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.feedBackModelContentList} style={{ visibility: feedBackList[feedBackList.length - 1].active ? 'visible' : 'hidden' }}>
|
|
||||||
<TextArea
|
|
||||||
placeholder="填写意见"
|
|
||||||
value={feedBackForm.otherContent}
|
|
||||||
autoSize={{ minRows: 3, maxRows: 6 }}
|
|
||||||
onChange={(e) => {
|
|
||||||
setFeedBackForm({
|
|
||||||
...feedBackForm,
|
|
||||||
otherContent: e.target.value
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={styles.feedBackModelFooter}>
|
|
||||||
<Button type="primary" className='m-ant-btn'
|
|
||||||
onClick={() => {
|
|
||||||
let parmes = {
|
|
||||||
score: feedBackForm.rateValue,
|
|
||||||
otherContent: feedBackList[feedBackList.length - 1].active ? feedBackForm.otherContent : '',
|
|
||||||
types: feedBackList.filter(row => row.active).map((item: any) => item.value),
|
|
||||||
}
|
|
||||||
if (feedBackForm.rateValue === 0) {
|
|
||||||
message.error('请选择评分')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
PostFeedback(parmes).then(res => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
message.success('提交成功!')
|
|
||||||
setIsFeedBackModel(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}}>提交</Button>
|
|
||||||
<Button type="primary" style={{ backgroundColor: 'rgb(16,20,24)', marginLeft: '20px' }}
|
|
||||||
onClick={() => setIsFeedBackModel(false)}>关闭</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
export default memo(FeedBackModel)
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import styles from '@/components/InvitingPersonnelModal/index.module.scss'
|
import styles from '@/components/InvitingPersonnelModal/index.module.scss'
|
||||||
import { Button, Checkbox, Input, Modal, Pagination, Radio, message } from 'antd';
|
import { Button, Checkbox, Input, Modal, Pagination, Radio, message } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, useEffect, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef, useEffect } from "react";
|
||||||
import { SearchOutlined } from '@ant-design/icons';
|
import { SearchOutlined } from '@ant-design/icons';
|
||||||
import { GetUserList } from '@/api/Home/User';
|
import { GetUserList } from '@/api/Home/User';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
@ -197,4 +197,4 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export default memo(InvitingPersonnelModal)
|
export default InvitingPersonnelModal
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import styles from '@/components/JoinMeetingModal/index.module.scss'
|
import styles from '@/components/JoinMeetingModal/index.module.scss'
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { Modal, message } from 'antd';
|
import { Modal, message } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, useRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef, useRef } from "react";
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import JoinSetting from '../JoinSetting';
|
import JoinSetting from '../JoinSetting';
|
||||||
const JoinMeetingModal = forwardRef((props: any, ref: any) => {
|
const JoinMeetingModal = forwardRef((props: any, ref: any) => {
|
||||||
|
|
@ -55,4 +55,4 @@ const JoinMeetingModal = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(JoinMeetingModal)
|
export default JoinMeetingModal
|
||||||
|
|
@ -3,13 +3,12 @@ import { storage } from '@/utils';
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { GetCheckoutRoomNum, GetRoomRtcToken, GetRoomInfo } from '@/api/Home/Index';
|
import { GetCheckoutRoomNum, GetRoomRtcToken, GetRoomInfo } from '@/api/Home/Index';
|
||||||
import { Button, Modal, message } from 'antd';
|
import { Button, Modal, message } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
import { PostRefresh } from '@/api/Login';
|
import { PostRefresh } from '@/api/Login';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { agora } from '@/utils/package/agora';
|
import { agora } from '@/utils/package/agora';
|
||||||
import { role } from '@/config/role';
|
import { role } from '@/config/role';
|
||||||
import { PostHomeVerLog } from '@/api/Meeting';
|
|
||||||
const { setInterval, clearInterval } = require('timers');
|
const { setInterval, clearInterval } = require('timers');
|
||||||
let time = null as any;
|
let time = null as any;
|
||||||
const JoinSetting = forwardRef((_props: any, ref: any) => {
|
const JoinSetting = forwardRef((_props: any, ref: any) => {
|
||||||
|
|
@ -171,7 +170,7 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
|
||||||
setJoinRoomSettingForm(list)
|
setJoinRoomSettingForm(list)
|
||||||
if (index === 1) {
|
if (index === 1) {
|
||||||
if (list[index].active) {
|
if (list[index].active) {
|
||||||
agora.startPreview('videoPreview', Number(user.screenShareId), +new Date())
|
agora.startPreview('videoPreview', Number(user.screenShareId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -202,13 +201,6 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
|
||||||
GetRoomInfo(roomNumber).then(async (res) => {
|
GetRoomInfo(roomNumber).then(async (res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
await agora.release()
|
await agora.release()
|
||||||
await window.electron.getVersion().then(async req => {
|
|
||||||
await PostHomeVerLog({
|
|
||||||
version: req,
|
|
||||||
platformType: 1,
|
|
||||||
roomNum: roomNumber,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
navigate(`/meeting`, {
|
navigate(`/meeting`, {
|
||||||
state: {
|
state: {
|
||||||
channelId: roomNumber,
|
channelId: roomNumber,
|
||||||
|
|
@ -244,4 +236,4 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(JoinSetting)
|
export default JoinSetting
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import styles from '@/components/MeetingDisconnected/index.module.scss'
|
import styles from '@/components/MeetingDisconnected/index.module.scss'
|
||||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
const MeetingDisconnected = forwardRef((props: any, ref: any) => {
|
const MeetingDisconnected = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
changeModal: (bool: boolean) => {
|
changeModal: (bool: boolean) => {
|
||||||
|
|
@ -17,4 +17,4 @@ const MeetingDisconnected = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(MeetingDisconnected)
|
export default MeetingDisconnected
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import styles from '@/components/Operation/index.module.scss'
|
import styles from '@/components/Operation/index.module.scss'
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { useEffect, useState, memo } from "react";
|
import { useEffect, useState } from "react";
|
||||||
type OperationKeyType = 'minimize' | 'quit' | 'maximize' | 'unmaximize' | 'hide' | 'show';
|
type OperationKeyType = 'minimize' | 'quit' | 'maximize' | 'unmaximize' | 'hide' | 'show';
|
||||||
type OperationType = {
|
type OperationType = {
|
||||||
icon: string;
|
icon: string;
|
||||||
|
|
@ -100,4 +100,4 @@ const Operation: React.FC = () => {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default memo(Operation)
|
export default Operation
|
||||||
|
|
@ -2,7 +2,7 @@ import styles from '@/components/QuitTips/index.module.scss'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||||
import { Button, Checkbox, Modal, Radio } from 'antd';
|
import { Button, Checkbox, Modal, Radio } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
type OperationKeyType = 'minimize' | 'quit' | 'maximize' | 'unmaximize' | 'hide' | 'show';
|
type OperationKeyType = 'minimize' | 'quit' | 'maximize' | 'unmaximize' | 'hide' | 'show';
|
||||||
const QuitTips = forwardRef((props: any, ref: any) => {
|
const QuitTips = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
@ -66,4 +66,4 @@ const QuitTips = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(QuitTips)
|
export default QuitTips
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
VerticalAlignBottomOutlined
|
VerticalAlignBottomOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { Button, Input, message, Modal, Pagination, Popconfirm, Progress, Table } from 'antd';
|
import { Button, Input, message, Modal, Pagination, Popconfirm, Progress, Table } from 'antd';
|
||||||
import { forwardRef, useEffect, useImperativeHandle, useState, useRef, memo } from "react";
|
import { forwardRef, useEffect, useImperativeHandle, useState, useRef } from "react";
|
||||||
import { DeleteRoomFile, GetRoomFile, GetRoomFileDwUrl, GetRoomUpFileurl, GetRoomUserItem, PostRoomFile } from '@/api/Meeting';
|
import { DeleteRoomFile, GetRoomFile, GetRoomFileDwUrl, GetRoomUpFileurl, GetRoomUserItem, PostRoomFile } from '@/api/Meeting';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
@ -393,4 +393,4 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(SharedFilesModel)
|
export default SharedFilesModel
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { GetRoomSingnIn, PostRoomSingnIn } from '@/api/Meeting';
|
||||||
import styles from '@/components/SingIn/index.module.scss'
|
import styles from '@/components/SingIn/index.module.scss'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { Button, message, Modal } from 'antd';
|
import { Button, message, Modal } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
const SingIn = forwardRef((props: any, ref: any) => {
|
const SingIn = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
changeModal: () => {
|
changeModal: () => {
|
||||||
|
|
@ -85,4 +85,4 @@ const SingIn = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(SingIn)
|
export default SingIn
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import styles from '@/components/SpeakerModeModal/index.module.scss'
|
import styles from '@/components/SpeakerModeModal/index.module.scss'
|
||||||
import { Checkbox, Modal } from 'antd';
|
import { Checkbox, Modal } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { GetSyncView } from '@/api/Meeting';
|
import { GetSyncView } from '@/api/Meeting';
|
||||||
|
|
@ -147,4 +147,4 @@ const FourScreenMode: React.FC<Props> = ({ onClick, meetingMode }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(SpeakerModeModal)
|
export default SpeakerModeModal
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import styles from '@/components/StupWizard/index.module.scss'
|
import styles from '@/components/StupWizard/index.module.scss'
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { Button, Checkbox, Empty, Input, message, Modal, Popover, Radio, Select, Slider, Space } from 'antd';
|
import { Button, Checkbox, Empty, Input, message, Modal, Popover, Radio, Select, Slider, Space } from 'antd';
|
||||||
import { forwardRef, useEffect, useImperativeHandle, useState, memo } from "react";
|
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
||||||
import { agora } from '@/utils/package/agora'
|
import { agora } from '@/utils/package/agora'
|
||||||
import { CloseOutlined, LoadingOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
import { CloseOutlined, LoadingOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
|
|
@ -11,7 +11,6 @@ import { storageSeeting } from '@/utils/package/public';
|
||||||
let meetingUserInfo = '' as any;
|
let meetingUserInfo = '' as any;
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
let c = +new Date();
|
|
||||||
const StupWizard = forwardRef((_props: any, ref: any) => {
|
const StupWizard = forwardRef((_props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
changeModal: (index: number = 0, data: any) => {
|
changeModal: (index: number = 0, data: any) => {
|
||||||
|
|
@ -34,9 +33,6 @@ const StupWizard = forwardRef((_props: any, ref: any) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storage.setItem('setting', JSON.stringify(setting))
|
storage.setItem('setting', JSON.stringify(setting))
|
||||||
},
|
|
||||||
getStupWizardModal: () => {
|
|
||||||
return isStupWizard
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
const [list, setList] = useState([
|
const [list, setList] = useState([
|
||||||
|
|
@ -88,8 +84,6 @@ const StupWizard = forwardRef((_props: any, ref: any) => {
|
||||||
{list.map((row: any, index: number) => {
|
{list.map((row: any, index: number) => {
|
||||||
return (
|
return (
|
||||||
<div key={index} className={`${row.active ? styles.active : ''}`} onClick={async () => {
|
<div key={index} className={`${row.active ? styles.active : ''}`} onClick={async () => {
|
||||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
|
||||||
await agora.destroyRendererByConfigPreview(Number(userInfo.screenShareId), c)
|
|
||||||
const newList = [...list];
|
const newList = [...list];
|
||||||
newList.forEach(item => item.active = false);
|
newList.forEach(item => item.active = false);
|
||||||
newList[index].active = true;
|
newList[index].active = true;
|
||||||
|
|
@ -112,11 +106,9 @@ const StupWizard = forwardRef((_props: any, ref: any) => {
|
||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
}}
|
}}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
|
||||||
if (location.hash.indexOf('/meeting') === -1) {
|
if (location.hash.indexOf('/meeting') === -1) {
|
||||||
agora.release()
|
agora.release()
|
||||||
}
|
}
|
||||||
await agora.destroyRendererByConfigPreview(Number(userInfo.screenShareId), c)
|
|
||||||
setIsStupWizard(false)
|
setIsStupWizard(false)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -133,11 +125,9 @@ const StupWizard = forwardRef((_props: any, ref: any) => {
|
||||||
})
|
})
|
||||||
const CurrencyComponents = () => {
|
const CurrencyComponents = () => {
|
||||||
const [optionsValue, setOperationValue] = useState<'hide' | 'quit'>('hide');
|
const [optionsValue, setOperationValue] = useState<'hide' | 'quit'>('hide');
|
||||||
const [voiceStimulation, setVoiceStimulation] = useState(true);
|
|
||||||
const setting = JSON.parse(storage.getItem('setting') as string)
|
const setting = JSON.parse(storage.getItem('setting') as string)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setOperationValue(setting.closeSetting)
|
setOperationValue(setting.closeSetting)
|
||||||
setVoiceStimulation(setting.voiceStimulation)
|
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -156,33 +146,6 @@ const CurrencyComponents = () => {
|
||||||
<Radio value={'hide'}>不退出程序,最小化到托盘</Radio>
|
<Radio value={'hide'}>不退出程序,最小化到托盘</Radio>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<span>语音激励 <Popover
|
|
||||||
content={
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
color: 'white'
|
|
||||||
}}>
|
|
||||||
开启语音激励后,会优先显示正在说话的与会成员。
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
title=""
|
|
||||||
>
|
|
||||||
<QuestionCircleOutlined style={{
|
|
||||||
color: 'white',
|
|
||||||
cursor: 'pointer',
|
|
||||||
marginRight: '10px'
|
|
||||||
}} />
|
|
||||||
</Popover></span>
|
|
||||||
<Radio.Group onChange={(e: any) => {
|
|
||||||
setting.voiceStimulation = e.target.value;
|
|
||||||
storage.setItem('setting', JSON.stringify(setting))
|
|
||||||
setVoiceStimulation(e.target.value)
|
|
||||||
}} style={{ flexShrink: 0, margin: '10px 0' }} value={voiceStimulation}>
|
|
||||||
<Radio value={true}>开启</Radio>
|
|
||||||
<Radio value={false}>关闭</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -245,25 +208,23 @@ const VideoComponents = () => {
|
||||||
}, [darkLightEnhancement]);
|
}, [darkLightEnhancement]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof virtualBackground.sourceIndex === 'number') {
|
if (typeof virtualBackground.sourceIndex === 'number') {
|
||||||
window.electron.getEnv().then(res=>{
|
if (import.meta.env.VITE_ENV === 'development') {
|
||||||
if (res === 'development') {
|
window.electron.getAppPath().then((res: string) => {
|
||||||
window.electron.getAppPath().then((res: string) => {
|
const imagePath = path.join(res, 'src', 'assets', 'virtualBackground', `${virtualBackground.sourceIndex + 1}.png`);
|
||||||
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, {
|
agora.enableVirtualBackground(virtualBackground.isVirtualBackground, {
|
||||||
source: imagePath,
|
source: imagePath,
|
||||||
background_source_type: 2,
|
background_source_type: 2,
|
||||||
color: Number(virtualBackground.color),
|
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 {
|
} else {
|
||||||
agora.enableVirtualBackground(virtualBackground.isVirtualBackground, {
|
agora.enableVirtualBackground(virtualBackground.isVirtualBackground, {
|
||||||
background_source_type: 1,
|
background_source_type: 1,
|
||||||
|
|
@ -286,7 +247,7 @@ const VideoComponents = () => {
|
||||||
})
|
})
|
||||||
if (setting.videoDeviceId && list.length) {
|
if (setting.videoDeviceId && list.length) {
|
||||||
await agora.setVideoDeviceManager(setting.videoDeviceId)
|
await agora.setVideoDeviceManager(setting.videoDeviceId)
|
||||||
await agora.startPreview('videoPreview', Number(userInfo.screenShareId), c)
|
await agora.startPreview('videoPreview', Number(userInfo.screenShareId))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +305,7 @@ const VideoComponents = () => {
|
||||||
agora.setVideoDeviceManager(e)
|
agora.setVideoDeviceManager(e)
|
||||||
if (!setting.videoDeviceId) {
|
if (!setting.videoDeviceId) {
|
||||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
const userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
await agora.startPreview('videoPreview', Number(userInfo.screenShareId), c)
|
await agora.startPreview('videoPreview', Number(userInfo.screenShareId))
|
||||||
}
|
}
|
||||||
setting.videoDeviceId = e;
|
setting.videoDeviceId = e;
|
||||||
storage.setItem('setting', JSON.stringify(setting))
|
storage.setItem('setting', JSON.stringify(setting))
|
||||||
|
|
@ -730,18 +691,7 @@ const AudioComponents = () => {
|
||||||
ecordingVolume: e,
|
ecordingVolume: e,
|
||||||
})
|
})
|
||||||
}} disabled={!audioDeviceManager.ecordingItem} />
|
}} disabled={!audioDeviceManager.ecordingItem} />
|
||||||
{/* || audioDeviceManager.autoEcordingVolume */}
|
|
||||||
</div>
|
</div>
|
||||||
{/* <div style={{ marginBottom: '10px' }}>
|
|
||||||
<Checkbox onChange={async (e) => {
|
|
||||||
setting.autoEcordingVolume = e.target.checked;
|
|
||||||
storage.setItem('setting', JSON.stringify(setting))
|
|
||||||
setAudioDeviceManager({
|
|
||||||
...audioDeviceManager,
|
|
||||||
autoEcordingVolume: e.target.checked
|
|
||||||
})
|
|
||||||
}} checked={audioDeviceManager.autoEcordingVolume}>自动调整麦克风音量</Checkbox>
|
|
||||||
</div> */}
|
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<Checkbox checked={audioDeviceManager.isAINoiseReduction} onChange={(e) => {
|
<Checkbox checked={audioDeviceManager.isAINoiseReduction} onChange={(e) => {
|
||||||
|
|
@ -774,6 +724,16 @@ const AudioComponents = () => {
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/* <div>
|
||||||
|
<Checkbox onChange={async (e) => {
|
||||||
|
setting.autoEcordingVolume = e.target.checked;
|
||||||
|
storage.setItem('setting', JSON.stringify(setting))
|
||||||
|
setAudioDeviceManager({
|
||||||
|
...audioDeviceManager,
|
||||||
|
autoEcordingVolume: e.target.checked
|
||||||
|
})
|
||||||
|
}} checked={audioDeviceManager.autoEcordingVolume}>自动调整麦克风音量</Checkbox>
|
||||||
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.audioComponentsSelect}>
|
<div className={styles.audioComponentsSelect}>
|
||||||
|
|
@ -1004,4 +964,4 @@ const FileComponents = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(StupWizard)
|
export default StupWizard
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, memo } from "react";
|
import { useEffect } from "react";
|
||||||
import '@/components/TldrawView/index.scss'
|
import '@/components/TldrawView/index.scss'
|
||||||
import {
|
import {
|
||||||
Tldraw,
|
Tldraw,
|
||||||
|
|
@ -44,4 +44,4 @@ const TldrawView: React.FC = () => {
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default memo(TldrawView)
|
export default TldrawView
|
||||||
|
|
@ -1,106 +1,45 @@
|
||||||
import styles from '@/components/UpdateModal/index.module.scss'
|
import styles from '@/components/UpdateModal/index.module.scss'
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { getUpdateUrl, isVersion } from '@/utils/package/public';
|
import { getUpdateUrl } from '@/utils/package/public';
|
||||||
import { ExclamationCircleFilled } from '@ant-design/icons';
|
|
||||||
import { Button, Flex, Modal, Progress } from 'antd';
|
import { Button, Flex, Modal, Progress } from 'antd';
|
||||||
import { forwardRef, useImperativeHandle, useState, memo, useEffect } from "react";
|
import { forwardRef, useImperativeHandle, useState } from "react";
|
||||||
const { confirm } = Modal;
|
|
||||||
|
|
||||||
const UpdateModal = forwardRef((_props: any, ref: any) => {
|
const UpdateModal = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
changeModal: (data: any) => {
|
changeModal: (data: any) => {
|
||||||
if (JSON.stringify(data).includes('Error') || JSON.stringify(data).includes('{}')) {
|
let dataJson = JSON.parse(data)
|
||||||
setIsError(res => {
|
getContent()
|
||||||
if (res) {
|
if (dataJson.type === '0') { // 打开弹窗
|
||||||
setIsError(false)
|
setIsUpdateModal(true)
|
||||||
confirm({
|
} else if (dataJson.type === '1') { // 下载中 返回进度值
|
||||||
keyboard: false,
|
setProgress(dataJson.value.toFixed(2))
|
||||||
title: '提示',
|
} else if (dataJson.type === '2') { // 下载完成
|
||||||
icon: <ExclamationCircleFilled />,
|
setProgress(100)
|
||||||
content: `更新失败,请尝试手动更新!`,
|
|
||||||
centered: true,
|
|
||||||
okText: '立即更新',
|
|
||||||
wrapClassName: 'hideCancelText',
|
|
||||||
cancelText: '',
|
|
||||||
async onOk() {
|
|
||||||
isVersion((bool: boolean, req: any) => {
|
|
||||||
if (bool && req) {
|
|
||||||
window.electron.getEnv().then(res => {
|
|
||||||
location.href = `${getUpdateUrl(res)}/${req.path}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
let dataJson = JSON.parse(data)
|
|
||||||
if (dataJson.type === '0') { // 打开弹窗
|
|
||||||
setProgress(res => {
|
|
||||||
if (res) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
window.electron.onDownload('1')
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
})
|
|
||||||
} else if (dataJson.type === '1') { // 下载中 返回进度值
|
|
||||||
if (dataJson.value === 100 && location.hash.indexOf('/meeting') === -1) {
|
|
||||||
setIsUpdateModal(true)
|
|
||||||
getContent()
|
|
||||||
}
|
|
||||||
setProgress(dataJson.value.toFixed(2))
|
|
||||||
} else if (dataJson.type === '2') { // 下载完成
|
|
||||||
setProgress(100)
|
|
||||||
if (location.hash.indexOf('/meeting') === -1) {
|
|
||||||
setIsUpdateModal(true)
|
|
||||||
getContent()
|
|
||||||
}
|
|
||||||
} else if (dataJson.type === '3') {
|
|
||||||
if (location.hash.indexOf('/meeting') === -1) {
|
|
||||||
setIsUpdateModal(true)
|
|
||||||
getContent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
const [isUpdateModal, setIsUpdateModal] = useState(false);
|
const [isUpdateModal, setIsUpdateModal] = useState(false);
|
||||||
const [progress, setProgress] = useState(0); // 下载进度值
|
const [progress, setProgress] = useState(0); // 下载进度值
|
||||||
const [updateContent, setUpdateContent] = useState('') // 版本更新内容
|
const [updateContent, setUpdateContent] = useState('') // 版本更新内容
|
||||||
const [env, setEnv] = useState('')
|
|
||||||
const [_isError, setIsError] = useState(true)
|
|
||||||
useEffect(() => {
|
|
||||||
window.electron.getEnv().then(res => {
|
|
||||||
setEnv(res)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
function getContent() {
|
function getContent() {
|
||||||
window.electron.getEnv().then(res => {
|
fetch(`${getUpdateUrl(import.meta.env.VITE_ENV)}/update.txt?t=${+new Date()}`) // 配置服务器地址
|
||||||
fetch(`${getUpdateUrl(res)}/update.txt?t=${+new Date()}`) // 配置服务器地址
|
.then(async response => {
|
||||||
.then(async response => {
|
if (response.status === 200) {
|
||||||
if (response.status === 200) {
|
return setUpdateContent(await response.text())
|
||||||
return setUpdateContent(await response.text())
|
}
|
||||||
}
|
throw new Error('Network response was not ok.');
|
||||||
throw new Error('Network response was not ok.');
|
})
|
||||||
})
|
.then(textContent => {
|
||||||
.then(_textContent => {
|
})
|
||||||
})
|
.catch(error => {
|
||||||
.catch(_error => {
|
});
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
// if (progress != 100) {
|
if (progress != 100) {
|
||||||
// window.electron.onDownload('0') // 取消下载
|
window.electron.onDownload('0') // 取消下载
|
||||||
// }
|
}
|
||||||
setIsUpdateModal(false)
|
setIsUpdateModal(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,12 +49,12 @@ const UpdateModal = forwardRef((_props: any, ref: any) => {
|
||||||
title=""
|
title=""
|
||||||
open={isUpdateModal}
|
open={isUpdateModal}
|
||||||
footer={null}
|
footer={null}
|
||||||
onCancel={() => closeModal()}
|
// onCancel={() => closeModal()}
|
||||||
centered
|
centered
|
||||||
width={'400px'}
|
width={'400px'}
|
||||||
className='modal-padding'
|
className='modal-padding'
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
closeIcon={progress === 100 ? false : true}
|
closeIcon={false}
|
||||||
>
|
>
|
||||||
<div className={styles.isUpdateModal} style={{ backgroundImage: `url(${ImageUrl.icon7})` }}>
|
<div className={styles.isUpdateModal} style={{ backgroundImage: `url(${ImageUrl.icon7})` }}>
|
||||||
<div className={styles.remarks} dangerouslySetInnerHTML={{ __html: updateContent }}>
|
<div className={styles.remarks} dangerouslySetInnerHTML={{ __html: updateContent }}>
|
||||||
|
|
@ -128,7 +67,7 @@ const UpdateModal = forwardRef((_props: any, ref: any) => {
|
||||||
style={{ width: '100%', height: '40px', marginBottom: '10px' }}
|
style={{ width: '100%', height: '40px', marginBottom: '10px' }}
|
||||||
className={`m-ant-btn`}
|
className={`m-ant-btn`}
|
||||||
>立即更新</Button>
|
>立即更新</Button>
|
||||||
{env === "development" ? <div className={styles.button2} onClick={() => setIsUpdateModal(false)}>暂不更新</div> : null}
|
{import.meta.env.VITE_ENV === "development" ? <div className={styles.button2} onClick={() => setIsUpdateModal(false)}>暂不更新</div> : null}
|
||||||
</div> : progress < 100 ?
|
</div> : progress < 100 ?
|
||||||
<div style={{ margin: '20px 0' }}>
|
<div style={{ margin: '20px 0' }}>
|
||||||
下载进度:{progress}%
|
下载进度:{progress}%
|
||||||
|
|
@ -148,4 +87,4 @@ const UpdateModal = forwardRef((_props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(UpdateModal)
|
export default UpdateModal
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { PutAlterUname } from '@/api/Meeting';
|
||||||
import styles from '@/components/UserName/index.module.scss'
|
import styles from '@/components/UserName/index.module.scss'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { Button, Input, message, Modal } from 'antd';
|
import { Button, Input, message, Modal } from 'antd';
|
||||||
import { useState, useImperativeHandle, forwardRef, memo } from "react";
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
const UserName = forwardRef((props: any, ref: any) => {
|
const UserName = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
changeModal: (data: any) => {
|
changeModal: (data: any) => {
|
||||||
|
|
@ -47,10 +47,6 @@ const UserName = forwardRef((props: any, ref: any) => {
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const stateInfo = await JSON.parse(storage.getItem('stateInfo') as string);
|
const stateInfo = await JSON.parse(storage.getItem('stateInfo') as string);
|
||||||
if (info.userName) {
|
if (info.userName) {
|
||||||
if (info.userName.length > 10) {
|
|
||||||
message.error('用户名称最多10个字!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
PutAlterUname({
|
PutAlterUname({
|
||||||
nickName: info.userName,
|
nickName: info.userName,
|
||||||
roomNum: stateInfo.channelId,
|
roomNum: stateInfo.channelId,
|
||||||
|
|
@ -75,4 +71,4 @@ const UserName = forwardRef((props: any, ref: any) => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
export default memo(UserName)
|
export default UserName
|
||||||
|
|
@ -3,7 +3,7 @@ import styles from '@/components/UserVideo/index.module.scss'
|
||||||
import { GetPolling } from '@/api/Meeting';
|
import { GetPolling } from '@/api/Meeting';
|
||||||
import { agora } from '@/utils/package/agora';
|
import { agora } from '@/utils/package/agora';
|
||||||
import { Button, Empty, Select, message } from 'antd';
|
import { Button, Empty, Select, message } from 'antd';
|
||||||
import { useEffect, useState, memo } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useLocation } from 'react-router';
|
import { useLocation } from 'react-router';
|
||||||
import { VideoStreamType } from 'agora-electron-sdk';
|
import { VideoStreamType } from 'agora-electron-sdk';
|
||||||
const { setInterval, clearInterval } = require('timers');
|
const { setInterval, clearInterval } = require('timers');
|
||||||
|
|
@ -154,4 +154,4 @@ const UserVideo: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(UserVideo)
|
export default UserVideo
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,14 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
>div:nth-child(2) {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
>div:nth-child(2) {
|
>div:nth-child(2) {
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,17 @@ import styles from '@/page/Home/Index/index.module.scss'
|
||||||
import { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import Operation from '@/components/Operation';
|
import Operation from '@/components/Operation';
|
||||||
import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker, Select, Radio } from "antd";
|
import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker, Select, Radio } from "antd";
|
||||||
import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord, PostRoomInfo } from '@/api/Home/Index';
|
import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord, PostRoomInfo, GetQrcode } from '@/api/Home/Index';
|
||||||
import ImageUrl from '@/utils/package/imageUrl'
|
import ImageUrl from '@/utils/package/imageUrl'
|
||||||
import { ExclamationCircleFilled, ReloadOutlined } from '@ant-design/icons';
|
import { ExclamationCircleFilled, ReloadOutlined } from '@ant-design/icons';
|
||||||
import JoinSetting from '@/components/JoinSetting';
|
import JoinSetting from '@/components/JoinSetting';
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { PostRefresh } from '@/api/Login';
|
import { PostRefresh } from '@/api/Login';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { role } from '@/config/role';
|
import { role } from '@/config/role';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import StupWizard from '@/components/StupWizard';
|
import StupWizard from '@/components/StupWizard';
|
||||||
import { GetSubDpList } from '@/api/Home/User';
|
import { GetSubDpList } from '@/api/Home/User';
|
||||||
import FeedBackModel from '@/components/FeedBackModel';
|
|
||||||
import { PostHomeVerLog } from '@/api/Meeting';
|
|
||||||
import Code from '@/components/Code';
|
|
||||||
import { isVersion } from "@/utils/package/public";
|
|
||||||
|
|
||||||
const { setInterval, clearInterval } = require('timers');
|
const { setInterval, clearInterval } = require('timers');
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
|
|
@ -25,7 +20,6 @@ const { RangePicker } = DatePicker;
|
||||||
const { confirm } = Modal;
|
const { confirm } = Modal;
|
||||||
const Index: React.FC = () => {
|
const Index: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { state } = useLocation();
|
|
||||||
const [list, setList] = useState({
|
const [list, setList] = useState({
|
||||||
data: [],
|
data: [],
|
||||||
total: 0,
|
total: 0,
|
||||||
|
|
@ -43,19 +37,16 @@ const Index: React.FC = () => {
|
||||||
})
|
})
|
||||||
const joinSettingRef = useRef<any>();
|
const joinSettingRef = useRef<any>();
|
||||||
const stupWizardRef = useRef<any>();
|
const stupWizardRef = useRef<any>();
|
||||||
const feedBackModelRef = useRef<any>();
|
|
||||||
const [user, setUser] = useState<any>({});
|
const [user, setUser] = useState<any>({});
|
||||||
const [currentRoomInfo, setCurrentRoomInfo] = useState<any>({});
|
const [currentRoomInfo, setCurrentRoomInfo] = useState<any>({});
|
||||||
const [subjectList, setSubjectList] = useState<any>([]);
|
const [subjectList, setSubjectList] = useState<any>([]);
|
||||||
const [timeData, setTimeData] = useState<any>([]);
|
const [timeData, setTimeData] = useState<any>([]);
|
||||||
const [isCreateRoom, setIsCreateRoom] = useState<boolean>(false);
|
const [isCreateRoom, setIsCreateRoom] = useState<boolean>(false);
|
||||||
const [allowAnonymous, setAllowAnonymous] = useState(true);
|
const [allowAnonymous, setAllowAnonymous] = useState(true);
|
||||||
|
const [baseImage, setBaseImage] = useState('');
|
||||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
const userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUser(userInfo)
|
setUser(userInfo)
|
||||||
if (state?.currentSeconds >= 600) {
|
|
||||||
feedBackModelRef.current.changeModal()
|
|
||||||
}
|
|
||||||
}, [])
|
}, [])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let time = null as any
|
let time = null as any
|
||||||
|
|
@ -248,7 +239,35 @@ const Index: React.FC = () => {
|
||||||
<span>{item.roomNum}</span>
|
<span>{item.roomNum}</span>
|
||||||
<img src={ImageUrl.icon10} alt="" />
|
<img src={ImageUrl.icon10} alt="" />
|
||||||
</div>
|
</div>
|
||||||
<Code roomNum={item.roomNum}></Code>
|
<Popover
|
||||||
|
placement="bottom"
|
||||||
|
onOpenChange={(e: boolean) => {
|
||||||
|
setBaseImage('')
|
||||||
|
if (e) {
|
||||||
|
GetQrcode(item.roomNum, import.meta.env.VITE_ENV === 'development' ? 'trial' : 'release').then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
setBaseImage(res.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
content={
|
||||||
|
baseImage ? <div>
|
||||||
|
<img style={{ width: '200px', margin: '0 auto' }} src={`data:image/png;base64,${baseImage}`} alt="" />
|
||||||
|
<div style={{ color: 'white', textAlign: 'center', fontSize: '16px', marginTop: '10px' }}>
|
||||||
|
<span>微信中长按图片识别小程序码</span><br />
|
||||||
|
<span>加入会议</span>
|
||||||
|
</div>
|
||||||
|
</div> : <div>
|
||||||
|
<Empty description={'二维码加载中,请稍后'} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div title='小程序'>
|
||||||
|
<img src={ImageUrl.icon55} alt="" />
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{role.ID.includes(userInfo.roleId) ? <Popover
|
{role.ID.includes(userInfo.roleId) ? <Popover
|
||||||
|
|
@ -310,43 +329,28 @@ const Index: React.FC = () => {
|
||||||
<Button type="primary"
|
<Button type="primary"
|
||||||
iconPosition={'end'}
|
iconPosition={'end'}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
storage.setItem('loading', true)
|
if (role.ID.includes(userInfo.roleId)) {
|
||||||
isVersion((bool: boolean) => {
|
joinSettingRef.current.changeModal(item.roomNum)
|
||||||
storage.setItem('loading', false)
|
} else {
|
||||||
if (bool) {
|
storage.setItem('loading', true)
|
||||||
window.electron.onDownload('3')
|
postRefresh(() => {
|
||||||
} else {
|
getRoomRtcToken(item.roomNum, (options: any) => {
|
||||||
if (role.ID.includes(userInfo.roleId)) {
|
if (options) {
|
||||||
joinSettingRef.current.changeModal(item.roomNum)
|
navigate(`/meeting`, {
|
||||||
} else {
|
state: {
|
||||||
storage.setItem('loading', true)
|
channelId: item.roomNum,
|
||||||
postRefresh(() => {
|
token: options.token,
|
||||||
getRoomRtcToken(item.roomNum, async (options: any) => {
|
tokenA: options.tokenA,
|
||||||
if (options) {
|
roomId: item.id,
|
||||||
await window.electron.getVersion().then(async req => {
|
roomName: item.roomName,
|
||||||
await PostHomeVerLog({
|
enableMicr: false,
|
||||||
version: req,
|
enableCamera: false,
|
||||||
platformType: 1,
|
|
||||||
roomNum: item.roomNum,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
navigate(`/meeting`, {
|
|
||||||
state: {
|
|
||||||
channelId: item.roomNum,
|
|
||||||
token: options.token,
|
|
||||||
tokenA: options.tokenA,
|
|
||||||
roomId: item.id,
|
|
||||||
roomName: item.roomName,
|
|
||||||
enableMicr: false,
|
|
||||||
enableCamera: false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
}}
|
}}
|
||||||
icon={<img src={ImageUrl.icon9} alt="" />}
|
icon={<img src={ImageUrl.icon9} alt="" />}
|
||||||
className='m-ant-btn'>
|
className='m-ant-btn'>
|
||||||
|
|
@ -547,7 +551,6 @@ const Index: React.FC = () => {
|
||||||
</Modal>
|
</Modal>
|
||||||
<JoinSetting ref={joinSettingRef} />
|
<JoinSetting ref={joinSettingRef} />
|
||||||
<StupWizard ref={stupWizardRef} />
|
<StupWizard ref={stupWizardRef} />
|
||||||
<FeedBackModel ref={feedBackModelRef} />
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -458,9 +458,6 @@ const User: React.FC = () => {
|
||||||
if (!addUserFrom.UserName && isCreateUser !== 'batch') {
|
if (!addUserFrom.UserName && isCreateUser !== 'batch') {
|
||||||
return message.error('请输入用户名称!')
|
return message.error('请输入用户名称!')
|
||||||
}
|
}
|
||||||
if (addUserFrom.UserName.length > 10) {
|
|
||||||
return message.error('用户名称最多10个字!')
|
|
||||||
}
|
|
||||||
if (addUserFrom.year === '') {
|
if (addUserFrom.year === '') {
|
||||||
return message.error('请输入届!')
|
return message.error('请输入届!')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,26 +120,8 @@
|
||||||
|
|
||||||
@else if $i ==4 {
|
@else if $i ==4 {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
color: #ccc;
|
||||||
>div:nth-child(1) {
|
font-size: 16px;
|
||||||
color: #ccc;
|
|
||||||
font-size: 16px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
>span:nth-child(2) {
|
|
||||||
background-color: red;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 0px 4px;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>div:nth-child(2) {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@else if $i ==5 {
|
@else if $i ==5 {
|
||||||
|
|
@ -148,7 +130,7 @@
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
|
||||||
@for $i from 1 through 3 {
|
@for $i from 1 through 2 {
|
||||||
>div:nth-child(#{$i}) {
|
>div:nth-child(#{$i}) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -162,16 +144,13 @@
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
|
||||||
@if $i ==1 {
|
@if $i ==1 {
|
||||||
background: url('/src/assets/icon56.png') no-repeat center/120%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $i ==2 {
|
|
||||||
background: url('/src/assets/icon16.png') no-repeat center/cover;
|
background: url('/src/assets/icon16.png') no-repeat center/cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@else if $i ==3 {
|
@else if $i ==2 {
|
||||||
background: url('/src/assets/icon15.png') no-repeat center/cover;
|
background: url('/src/assets/icon15.png') no-repeat center/cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
|
|
@ -183,14 +162,10 @@
|
||||||
&:hover {
|
&:hover {
|
||||||
>div {
|
>div {
|
||||||
@if $i ==1 {
|
@if $i ==1 {
|
||||||
background: url('/src/assets/icon56-active.png') no-repeat center/120%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $i ==2 {
|
|
||||||
background: url('/src/assets/icon16-active.png') no-repeat center/cover;
|
background: url('/src/assets/icon16-active.png') no-repeat center/cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
@else if $i ==3 {
|
@else if $i ==2 {
|
||||||
background: url('/src/assets/icon15-active.png') no-repeat center/cover;
|
background: url('/src/assets/icon15-active.png') no-repeat center/cover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import styles from '@/page/Home/index.module.scss'
|
import styles from '@/page/Home/index.module.scss'
|
||||||
import { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import { Outlet, useNavigate } from 'react-router-dom';
|
import { Outlet, useNavigate } from 'react-router-dom';
|
||||||
import { Button, Popconfirm, Popover } from 'antd';
|
import { Popconfirm } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import 'dayjs/locale/zh-cn'
|
import 'dayjs/locale/zh-cn'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
|
|
@ -45,7 +45,6 @@ const Home: React.FC = () => {
|
||||||
]);
|
]);
|
||||||
const [userInfo, setUserInfo] = useState<any>({})
|
const [userInfo, setUserInfo] = useState<any>({})
|
||||||
const [version, setVersion] = useState<string>('')
|
const [version, setVersion] = useState<string>('')
|
||||||
const [update, setUpdate] = useState(false)
|
|
||||||
const [dateInfo, setDateInfo] = useState<{
|
const [dateInfo, setDateInfo] = useState<{
|
||||||
work: string;
|
work: string;
|
||||||
time: string;
|
time: string;
|
||||||
|
|
@ -68,18 +67,11 @@ const Home: React.FC = () => {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
const timer = setInterval(updateTime, 1000);
|
const timer = setInterval(updateTime, 1000);
|
||||||
window.addEventListener('customStorageChange', handleCustomStorageChange);
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('customStorageChange', handleCustomStorageChange);
|
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleCustomStorageChange = (e: any): void => {
|
|
||||||
if (e.key === 'isUpdate') {
|
|
||||||
setUpdate(e.value)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const changtNavList = (index: number, bool?: boolean): void => {
|
const changtNavList = (index: number, bool?: boolean): void => {
|
||||||
const newNavList = [...navList];
|
const newNavList = [...navList];
|
||||||
if (typeof bool === 'boolean') {
|
if (typeof bool === 'boolean') {
|
||||||
|
|
@ -134,29 +126,10 @@ const Home: React.FC = () => {
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className='drag'>
|
<div>
|
||||||
<div>
|
版本号:{version}
|
||||||
<span>版本号:{version}</span>
|
|
||||||
{update ? <span>new</span> : null}
|
|
||||||
</div>
|
|
||||||
{update ? <div>
|
|
||||||
<Button type="primary" className='m-ant-btn' style={{ width: '100%' }} onClick={() => {
|
|
||||||
window.electron.onDownload('3')
|
|
||||||
}}>立即更新</Button>
|
|
||||||
</div> : null}
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Popover
|
|
||||||
placement="right"
|
|
||||||
content={
|
|
||||||
<img style={{ width: '400px' }} src={`https://meeting-api.23544.com/meeting/update/ddq.png?t=${+new Date()}`} alt="" />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className='drag' title='反馈建议'>
|
|
||||||
<div></div>
|
|
||||||
<span>反馈建议</span>
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
<div className='drag' title='设置' onClick={() => {
|
<div className='drag' title='设置' onClick={() => {
|
||||||
stupWizardRef.current.changeModal()
|
stupWizardRef.current.changeModal()
|
||||||
}}>
|
}}>
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,11 @@ import { useEffect, useState } from "react";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Input, Button, Checkbox, message, Modal } from "antd"
|
import { Input, Button, Checkbox, message, Modal } from "antd"
|
||||||
import { storage } from '@/utils'
|
import { storage } from '@/utils'
|
||||||
import { GetCheckOnline, GetCheckUser, PostAnonLogin, PostLogin } from '@/api/Login'
|
import { GetCheckUser, PostAnonLogin, PostLogin } from '@/api/Login'
|
||||||
import * as CryptoJS from 'crypto-js';
|
import * as CryptoJS from 'crypto-js';
|
||||||
import ImageUrl from '@/utils/package/imageUrl'
|
import ImageUrl from '@/utils/package/imageUrl'
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { GetCheckoutRoomNum, GetRoomInfo, GetRoomRtcToken } from '@/api/Home/Index';
|
import { GetCheckoutRoomNum, GetRoomInfo, GetRoomRtcToken } from '@/api/Home/Index';
|
||||||
import { ExclamationCircleFilled } from '@ant-design/icons';
|
|
||||||
import { isVersion } from '@/utils/package/public';
|
|
||||||
const { confirm } = Modal;
|
|
||||||
const Login: React.FC = () => {
|
const Login: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [accountPasswordStatus, setAccountPasswordStatus] = useState<boolean>(false);
|
const [accountPasswordStatus, setAccountPasswordStatus] = useState<boolean>(false);
|
||||||
|
|
@ -40,16 +37,13 @@ const Login: React.FC = () => {
|
||||||
roomNum: '',
|
roomNum: '',
|
||||||
})
|
})
|
||||||
const [nameModal, setNameModal] = useState(false)
|
const [nameModal, setNameModal] = useState(false)
|
||||||
const [env, setEnv] = useState('')
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.electron.setMainWindowSize({
|
window.electron.setMainWindowSize({
|
||||||
width: 752,
|
width: 752,
|
||||||
height: 520,
|
height: 520,
|
||||||
key: 'login'
|
key: 'login'
|
||||||
})
|
})
|
||||||
window.electron.getEnv().then(res => {
|
|
||||||
setEnv(res)
|
|
||||||
})
|
|
||||||
if (storage.getItem('login')) {
|
if (storage.getItem('login')) {
|
||||||
const login = JSON.parse(storage.getItem('login') as string);
|
const login = JSON.parse(storage.getItem('login') as string);
|
||||||
const data = {
|
const data = {
|
||||||
|
|
@ -106,32 +100,7 @@ const Login: React.FC = () => {
|
||||||
}
|
}
|
||||||
GetCheckUser(operation.account).then(res => {
|
GetCheckUser(operation.account).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
if (res.data) {
|
res.data ? setAccountPasswordStatus(true) : message.error('账号不存在!')
|
||||||
GetCheckOnline(operation.account).then(req => {
|
|
||||||
if (req.code === 200) {
|
|
||||||
if (req.data) {
|
|
||||||
confirm({
|
|
||||||
title: '提示',
|
|
||||||
icon: <ExclamationCircleFilled />,
|
|
||||||
content: `账号已在其他地方登录,是否强制登陆?`,
|
|
||||||
centered: true,
|
|
||||||
okText: '确定',
|
|
||||||
cancelText: '取消',
|
|
||||||
async onOk() {
|
|
||||||
setAccountPasswordStatus(true)
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
setAccountPasswordStatus(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
message.error('账号不存在!')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -204,7 +173,7 @@ const Login: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<div className={styles.login}>
|
<div className={styles.login}>
|
||||||
<div className={styles.loginBg}>
|
<div className={styles.loginBg}>
|
||||||
{env ? <img src={env === 'xy' ? ImageUrl.icon53 : ImageUrl.icon1} alt="" /> : null}
|
<img src={import.meta.env.VITE_ENV === 'xy' ? ImageUrl.icon53 : ImageUrl.icon1} alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.loginContent}>
|
<div className={styles.loginContent}>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -346,58 +315,47 @@ const Login: React.FC = () => {
|
||||||
if (!anonInfo.nickName) {
|
if (!anonInfo.nickName) {
|
||||||
return message.error('请输入参会昵称!')
|
return message.error('请输入参会昵称!')
|
||||||
}
|
}
|
||||||
if (anonInfo.nickName.length > 10) {
|
|
||||||
return message.error('参会昵称最多10个字!')
|
|
||||||
}
|
|
||||||
storage.setItem('loading', true)
|
storage.setItem('loading', true)
|
||||||
isVersion((bool: boolean) => {
|
PostAnonLogin(anonInfo).then(async (res) => {
|
||||||
storage.setItem('loading', false)
|
if (res.code == 200) {
|
||||||
if (bool) {
|
storage.setItem('user', JSON.stringify(res.data))
|
||||||
window.electron.onDownload('3')
|
storage.setItem('userLogin', true)
|
||||||
} else {
|
await window.electron.startSignalr(res.data)
|
||||||
storage.setItem('loading', true)
|
getRoomRtcToken(anonInfo.roomNum, (options: any) => {
|
||||||
PostAnonLogin(anonInfo).then(async (res) => {
|
if (options) {
|
||||||
if (res.code == 200) {
|
GetRoomInfo(anonInfo.roomNum).then(async (res) => {
|
||||||
storage.setItem('user', JSON.stringify(res.data))
|
if (res.code === 200) {
|
||||||
storage.setItem('userLogin', true)
|
setTimeout(() => {
|
||||||
await window.electron.startSignalr(res.data)
|
|
||||||
getRoomRtcToken(anonInfo.roomNum, (options: any) => {
|
|
||||||
if (options) {
|
|
||||||
GetRoomInfo(anonInfo.roomNum).then(async (res) => {
|
|
||||||
if (res.code === 200) {
|
|
||||||
setTimeout(() => {
|
|
||||||
storage.setItem('loading', false)
|
|
||||||
window.electron.getWindowSize().then((res: any) => {
|
|
||||||
window.electron.setMainWindowSize({
|
|
||||||
width: Math.ceil(res.width / 1.5),
|
|
||||||
height: Math.ceil(res.height / 1.3),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
navigate(`/meeting`, {
|
|
||||||
state: {
|
|
||||||
channelId: anonInfo.roomNum,
|
|
||||||
token: options.token,
|
|
||||||
tokenA: options.tokenA,
|
|
||||||
roomId: res.data.id,
|
|
||||||
roomName: res.data.roomName,
|
|
||||||
enableMicr: false,
|
|
||||||
enableCamera: false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, 2000)
|
|
||||||
} else {
|
|
||||||
storage.setItem('loading', false)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
storage.setItem('loading', false)
|
storage.setItem('loading', false)
|
||||||
})
|
window.electron.getWindowSize().then((res: any) => {
|
||||||
|
window.electron.setMainWindowSize({
|
||||||
|
width: Math.ceil(res.width / 1.5),
|
||||||
|
height: Math.ceil(res.height / 1.3),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
navigate(`/meeting`, {
|
||||||
|
state: {
|
||||||
|
channelId: anonInfo.roomNum,
|
||||||
|
token: options.token,
|
||||||
|
tokenA: options.tokenA,
|
||||||
|
roomId: res.data.id,
|
||||||
|
roomName: res.data.roomName,
|
||||||
|
enableMicr: false,
|
||||||
|
enableCamera: false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 2000)
|
||||||
|
} else {
|
||||||
|
storage.setItem('loading', false)
|
||||||
}
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
storage.setItem('loading', false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
|
||||||
storage.setItem('loading', false)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
storage.setItem('loading', false)
|
||||||
})
|
})
|
||||||
}}>进入</Button>
|
}}>进入</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,6 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {}
|
>div {}
|
||||||
|
|
@ -79,8 +77,6 @@
|
||||||
>span {
|
>span {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
|
|
|
||||||
|
|
@ -206,30 +206,19 @@ const ChatBigWindow: React.FC = () => {
|
||||||
>移出会议</Button> : null}
|
>移出会议</Button> : null}
|
||||||
</div> : <div style={{ color: 'white' }}>用户不在房间内</div>
|
</div> : <div style={{ color: 'white' }}>用户不在房间内</div>
|
||||||
}>
|
}>
|
||||||
<div title={item.userName}>
|
<div>
|
||||||
<div><Avatar name={item.userName} /></div>
|
<div><Avatar name={item.userName} /></div>
|
||||||
{item.uid !== user.uid ?
|
{item.uid !== user.uid ?
|
||||||
<span>
|
<span>{item.userName} <span style={{ fontSize: '12px', color: '#ccc', marginLeft: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')}</span></span> :
|
||||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '150px' }}>{item.userName}</span>
|
<span> <span style={{ fontSize: '12px', color: '#ccc', marginRight: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')} </span>{item.userName}</span>
|
||||||
<span style={{ fontSize: '12px', color: '#ccc', marginLeft: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')}</span>
|
|
||||||
</span> :
|
|
||||||
<span>
|
|
||||||
<span style={{ fontSize: '12px', color: '#ccc', marginRight: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')}</span>
|
|
||||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '150px' }}>{item.userName}</span>
|
|
||||||
</span>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Popover> : <div title={item.userName}>
|
</Popover> : <div>
|
||||||
<div><Avatar name={item.userName} /></div>
|
<div><Avatar name={item.userName} /></div>
|
||||||
{item.uid !== user.uid ?
|
{item.uid !== user.uid ?
|
||||||
<span>
|
<span>{item.userName}<span style={{ fontSize: '12px', color: '#ccc', marginLeft: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')}</span></span> :
|
||||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '150px' }}>{item.userName}</span>
|
<span><span style={{ fontSize: '12px', color: '#ccc', marginRight: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')} </span>{item.userName}</span>
|
||||||
<span style={{ fontSize: '12px', color: '#ccc', marginLeft: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')}</span>
|
|
||||||
</span> :
|
|
||||||
<span>
|
|
||||||
<span style={{ fontSize: '12px', color: '#ccc', marginRight: '4px' }}>{dayjs(item.timestamp).format('HH:mm:ss')}</span>
|
|
||||||
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '150px' }}>{item.userName}</span>
|
|
||||||
</span>
|
|
||||||
}
|
}
|
||||||
</div>}
|
</div>}
|
||||||
<div>{item.message}</div>
|
<div>{item.message}</div>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
>span:nth-child(1) {
|
>span:nth-child(1) {
|
||||||
word-break: break-all;
|
white-space: nowrap;
|
||||||
color: #ff970f;
|
color: #ff970f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,7 @@ const NoticeWindow: React.FC = () => {
|
||||||
api.open({
|
api.open({
|
||||||
message: '',
|
message: '',
|
||||||
description: <div>
|
description: <div>
|
||||||
<div style={{ fontSize: '16px' }}>
|
<span style={{ fontSize: '16px' }}>{noticeItem.uname}申请发言</span>
|
||||||
<div style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={noticeItem.uname}>{noticeItem.uname}</div>
|
|
||||||
<div>申请发言</div>
|
|
||||||
</div>
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className='drag'>
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }} className='drag'>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -71,15 +68,13 @@ const NoticeWindow: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
setTimeout(() => {
|
const dom = document.getElementsByClassName('ant-notification')
|
||||||
const dom = document.getElementsByClassName('ant-notification')
|
if (dom.length === 0) {
|
||||||
if (dom.length === 0) {
|
window.electron.setChildWindowShow({
|
||||||
window.electron.setChildWindowShow({
|
key: 'noticeWindow',
|
||||||
key: 'noticeWindow',
|
bool: false
|
||||||
bool: false
|
})
|
||||||
})
|
}
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
},
|
},
|
||||||
duration: 10,
|
duration: 10,
|
||||||
placement: 'bottomRight',
|
placement: 'bottomRight',
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import styles from '@/page/Meeting/ShareScreenWindow/index.module.scss'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
|
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
|
||||||
import { RtcStats } from 'agora-electron-sdk';
|
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
@ -51,12 +50,6 @@ const ShareScreenWindow: React.FC = () => {
|
||||||
const [timeStr, setTimeStr] = useState(0)
|
const [timeStr, setTimeStr] = useState(0)
|
||||||
const [isExpand, setIsExpand] = useState(false)
|
const [isExpand, setIsExpand] = useState(false)
|
||||||
const [roomUserLists, setRoomUserLists] = useState<any>([])
|
const [roomUserLists, setRoomUserLists] = useState<any>([])
|
||||||
const [currentEffective, setCurrentEffective] = useState(3)
|
|
||||||
const [networkOther, setNetworkOther] = useState<RtcStats>({})
|
|
||||||
const [networkQuality, setNetworkQuality] = useState({
|
|
||||||
level: '佳',
|
|
||||||
text: '网络质量极好'
|
|
||||||
})
|
|
||||||
const channel = new BroadcastChannel('meeting_channel');
|
const channel = new BroadcastChannel('meeting_channel');
|
||||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
const userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
let timeout: NodeJS.Timeout;
|
let timeout: NodeJS.Timeout;
|
||||||
|
|
@ -104,11 +97,6 @@ const ShareScreenWindow: React.FC = () => {
|
||||||
case 'roomUserList':
|
case 'roomUserList':
|
||||||
setRoomUserLists(data.parmes.roomUserList)
|
setRoomUserLists(data.parmes.roomUserList)
|
||||||
break;
|
break;
|
||||||
case 'nnetworkStatus':
|
|
||||||
setCurrentEffective(data.parmes.currentEffective)
|
|
||||||
setNetworkQuality(data.parmes.networkQuality)
|
|
||||||
setNetworkOther(data.parmes.networkOther)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -153,19 +141,13 @@ const ShareScreenWindow: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<div className={styles.shareScreenWindow} style={{ width: isExpand ? '100%' : '100%' }}>
|
<div className={styles.shareScreenWindow} style={{ width: isExpand ? '100%' : '100%' }}>
|
||||||
<div className={styles.shareScreenWindowTitle}>
|
<div className={styles.shareScreenWindowTitle}>
|
||||||
<span>{changeCurrentSeconds(timeStr)} {!isExpand ? '共享中' : ''}
|
<span>{changeCurrentSeconds(timeStr)} 共享中</span>
|
||||||
{networkIcon(currentEffective)}
|
{isExpand ? <span className='drag' onClick={() => {
|
||||||
<span style={{ color: 'white', marginLeft: '30px' }}>
|
|
||||||
{!isExpand ? <span style={{ marginRight: '10px' }}>网络质量:{networkQuality.level}</span> : ''}
|
|
||||||
<span>延迟:{networkOther.lastmileDelay}ms</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
{isExpand ? <span className='drag' style={{ flexShrink: 0 }} onClick={() => {
|
|
||||||
channel.postMessage({
|
channel.postMessage({
|
||||||
type: 'shareScreenWindowClose',
|
type: 'shareScreenWindowClose',
|
||||||
shareScreenWindowClose: timeStr
|
shareScreenWindowClose: timeStr
|
||||||
});
|
});
|
||||||
}}>结束共享</span> : <span style={{ visibility: 'hidden', flexShrink: 0 }}>结束共享</span>}
|
}}>结束共享</span> : <span style={{ visibility: 'hidden' }}>结束共享</span>}
|
||||||
</div>
|
</div>
|
||||||
{isExpand ? null : <div className={`${styles.shareScreenWindowContent} drag`}>
|
{isExpand ? null : <div className={`${styles.shareScreenWindowContent} drag`}>
|
||||||
<div className={styles.shareScreenWindowContentList}>
|
<div className={styles.shareScreenWindowContentList}>
|
||||||
|
|
@ -202,7 +184,7 @@ const ShareScreenWindow: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
key={index}>
|
key={index}>
|
||||||
<div>
|
<div>
|
||||||
{!item.active ? <div style={{ backgroundImage: `url(${ImageUrl.icon49})`, transition: '0.18s' }} id={`micr-item-${userInfo.uid}`}>
|
{!item.active ? <div style={{ backgroundImage: `url(${ImageUrl.icon49})` }} id={`micr-item-${userInfo.uid}`}>
|
||||||
</div> : ''}
|
</div> : ''}
|
||||||
{item.select ? <img src={item.iconSelect} alt="" /> : <img src={item.active ? item.iconActive : item.icon} alt="" />}
|
{item.select ? <img src={item.iconSelect} alt="" /> : <img src={item.active ? item.iconActive : item.icon} alt="" />}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -223,7 +205,7 @@ const ShareScreenWindow: React.FC = () => {
|
||||||
<div className={`${styles.shareScreenWindowExpand} drag`} onClick={() => {
|
<div className={`${styles.shareScreenWindowExpand} drag`} onClick={() => {
|
||||||
setIsExpand(!isExpand)
|
setIsExpand(!isExpand)
|
||||||
window.electron.setChildWindow({
|
window.electron.setChildWindow({
|
||||||
width: isExpand ? 440 : 440 / 1.6,
|
width: isExpand ? 440 : 440 / 2,
|
||||||
key: 'shareScreenWindow',
|
key: 'shareScreenWindow',
|
||||||
})
|
})
|
||||||
}}>
|
}}>
|
||||||
|
|
@ -235,60 +217,4 @@ const ShareScreenWindow: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const networkIcon = (network: number) => {
|
|
||||||
switch (network) {
|
|
||||||
case 0:
|
|
||||||
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
||||||
<g clip-path="url(#clip0_21262_3609)">
|
|
||||||
<path d="M4.44094 32C3.03695 32 1.90039 31.15 1.90039 30.1V15.3C1.90039 14.25 3.03695 13.4 4.44094 13.4C5.84492 13.4 6.98149 14.25 6.98149 15.3V30.1C6.98149 31.15 5.84492 32 4.44094 32ZM17.01 32C15.606 32 14.4694 31.15 14.4694 30.1V8.9C14.4694 7.85 15.606 7 17.01 7C18.4139 7 19.5505 7.85 19.5505 8.9V30.1C19.5505 31.15 18.4139 32 17.01 32ZM29.579 32C28.175 32 27.0384 31.15 27.0384 30.1V1.9C27.0384 0.85 28.175 0 29.579 0C30.983 0 32.1195 0.85 32.1195 1.9V30.1C32.1195 31.15 30.983 32 29.579 32Z" fill="#7C8280" />
|
|
||||||
<path d="M7.00124 2.11509L5.01758 4.09875L3.03391 2.11509C2.77629 1.85747 2.35122 1.85747 2.0936 2.11509C1.83599 2.37271 1.83599 2.79778 2.0936 3.0554L4.07727 5.03906L2.0936 7.02273C1.83599 7.28035 1.83599 7.70542 2.0936 7.96304C2.35122 8.22065 2.77629 8.22065 3.03391 7.96304L5.01758 5.97937L7.00124 7.96304C7.25886 8.22065 7.68393 8.22065 7.94155 7.96304C8.19917 7.70542 8.19917 7.28035 7.94155 7.02273L5.95789 5.03906L7.94155 3.0554C8.19917 2.79778 8.19917 2.37271 7.94155 2.11509C7.68393 1.85747 7.25886 1.85747 7.00124 2.11509Z" fill="#F90000" />
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0_21262_3609">
|
|
||||||
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
case 1:
|
|
||||||
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
||||||
<g clip-path="url(#clip0_21262_3615)">
|
|
||||||
<path d="M26.9316 30.1C26.9316 31.15 28.0918 32 29.5249 32C30.9581 32 32.1182 31.15 32.1182 30.1V1.9C32.1182 0.85 30.9581 0 29.5249 0C28.0918 0 26.9316 0.85 26.9316 1.9V30.1Z" fill="#7C8280" />
|
|
||||||
<path d="M14.1035 30.1C14.1035 31.15 15.2637 32 16.6968 32C18.1299 32 19.2901 31.15 19.2901 30.1V8.9C19.2901 7.85 18.1299 7 16.6968 7C15.2637 7 14.1035 7.85 14.1035 8.9V30.1Z" fill="#7C8280" />
|
|
||||||
<path d="M1.27344 30.1004C1.27344 31.1504 2.4336 32.0004 3.86673 32.0004C5.29986 32.0004 6.46002 31.1504 6.46002 30.1004V15.3004C6.46002 14.2504 5.29986 13.4004 3.86673 13.4004C2.4336 13.4004 1.27344 14.2504 1.27344 15.3004V30.1004Z" fill="#FF800B" />
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0_21262_3615">
|
|
||||||
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
case 2:
|
|
||||||
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
||||||
<g clip-path="url(#clip0_21262_3621)">
|
|
||||||
<path d="M26.9316 30.1C26.9316 31.15 28.0918 32 29.5249 32C30.9581 32 32.1182 31.15 32.1182 30.1V1.9C32.1182 0.85 30.9581 0 29.5249 0C28.0918 0 26.9316 0.85 26.9316 1.9V30.1Z" fill="#7C8280" />
|
|
||||||
<path d="M14.1035 30.1C14.1035 31.15 15.2637 32 16.6968 32C18.1299 32 19.2901 31.15 19.2901 30.1V8.9C19.2901 7.85 18.1299 7 16.6968 7C15.2637 7 14.1035 7.85 14.1035 8.9V30.1Z" fill="#FF800B" />
|
|
||||||
<path d="M1.27344 30.1004C1.27344 31.1504 2.4336 32.0004 3.86673 32.0004C5.29986 32.0004 6.46002 31.1504 6.46002 30.1004V15.3004C6.46002 14.2504 5.29986 13.4004 3.86673 13.4004C2.4336 13.4004 1.27344 14.2504 1.27344 15.3004V30.1004Z" fill="#FF800B" />
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0_21262_3621">
|
|
||||||
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
case 3:
|
|
||||||
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
||||||
<g clip-path="url(#clip0_21262_3625)">
|
|
||||||
<path d="M26.9316 30.1C26.9316 31.15 28.0918 32 29.5249 32C30.9581 32 32.1182 31.15 32.1182 30.1V1.9C32.1182 0.85 30.9581 0 29.5249 0C28.0918 0 26.9316 0.85 26.9316 1.9V30.1Z" fill="#02B188" />
|
|
||||||
<path d="M14.1035 30.1C14.1035 31.15 15.2637 32 16.6968 32C18.1299 32 19.2901 31.15 19.2901 30.1V8.9C19.2901 7.85 18.1299 7 16.6968 7C15.2637 7 14.1035 7.85 14.1035 8.9V30.1Z" fill="#02B188" />
|
|
||||||
<path d="M1.27344 30.1004C1.27344 31.1504 2.4336 32.0004 3.86673 32.0004C5.29986 32.0004 6.46002 31.1504 6.46002 30.1004V15.3004C6.46002 14.2504 5.29986 13.4004 3.86673 13.4004C2.4336 13.4004 1.27344 14.2504 1.27344 15.3004V30.1004Z" fill="#02B188" />
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0_21262_3625">
|
|
||||||
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ShareScreenWindow
|
export default ShareScreenWindow
|
||||||
|
|
|
||||||
|
|
@ -232,11 +232,6 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
#videoView {
|
|
||||||
position: relative;
|
|
||||||
border: 1px red solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.standardModeIcon {
|
.standardModeIcon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
@ -303,17 +298,13 @@
|
||||||
|
|
||||||
// 演讲者模式
|
// 演讲者模式
|
||||||
.meetingContentBodyLeftSpeakerMode {
|
.meetingContentBodyLeftSpeakerMode {
|
||||||
width: 270px;
|
width: 18%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.meetingContentSwiperCard {
|
.meetingContentSwiperCard {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.meetingContentSwiperCard {
|
|
||||||
height: 160px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 单画面模式
|
// 单画面模式
|
||||||
|
|
@ -379,7 +370,7 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
width: calc(100% - 270px) !important;
|
width: calc(100% - 18%) !important;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -390,7 +381,7 @@
|
||||||
|
|
||||||
.meetingContentSwiperCard {
|
.meetingContentSwiperCard {
|
||||||
height: 160px;
|
height: 160px;
|
||||||
width: 270px;
|
width: calc(100% / 6);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -436,22 +427,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.meetingContentSwiperCaret {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
color: white;
|
|
||||||
border: 1px white solid;
|
|
||||||
font-size: 20px;
|
|
||||||
width: 25px;
|
|
||||||
height: 25px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.meetingContentBodyLeftBlock {
|
.meetingContentBodyLeftBlock {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: #1F2022;
|
background-color: #1F2022;
|
||||||
|
|
@ -549,8 +524,6 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
|
|
@ -662,8 +635,6 @@
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,8 +664,6 @@
|
||||||
>span {
|
>span {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
|
|
@ -804,7 +773,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
>img {
|
>img {
|
||||||
height: 35px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
|
|
@ -826,8 +795,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
>label {
|
>label {
|
||||||
height: 35px;
|
height: 50px;
|
||||||
height: 35px;
|
height: 50px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,8 @@ export interface IElectronAPI {
|
||||||
downFile: (callBack: Function) => void;
|
downFile: (callBack: Function) => void;
|
||||||
quitAndInstall: (callBack: Function) => void;
|
quitAndInstall: (callBack: Function) => void;
|
||||||
isOpenWindows: (callBack: Function) => void;
|
isOpenWindows: (callBack: Function) => void;
|
||||||
startLoad: () => any;
|
setEnv: (str: string) => any;
|
||||||
updateHandle: () => any;
|
|
||||||
getVersion: () => Promise<string>;
|
getVersion: () => Promise<string>;
|
||||||
getEnv: () => Promise<string>;
|
|
||||||
isVisible: () => Promise<string>;
|
isVisible: () => Promise<string>;
|
||||||
setRegistry: (uuid: string) => any;
|
setRegistry: (uuid: string) => any;
|
||||||
getRegistry: () => any;
|
getRegistry: () => any;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
declare module 'react-dom/client';
|
declare module 'react-dom/client';
|
||||||
declare module 'crypto-js';
|
declare module 'crypto-js';
|
||||||
declare module 'js-yaml';
|
|
||||||
declare module 'uuid';
|
declare module 'uuid';
|
||||||
|
|
@ -9,6 +9,7 @@ import {
|
||||||
AudioAinsMode,
|
AudioAinsMode,
|
||||||
SimulcastStreamMode,
|
SimulcastStreamMode,
|
||||||
VideoStreamType,
|
VideoStreamType,
|
||||||
|
QualityType,
|
||||||
RtcConnection,
|
RtcConnection,
|
||||||
RtcStats,
|
RtcStats,
|
||||||
AudioVolumeInfo,
|
AudioVolumeInfo,
|
||||||
|
|
@ -21,8 +22,7 @@ import {
|
||||||
ColorEnhanceOptions,
|
ColorEnhanceOptions,
|
||||||
LowlightEnhanceOptions,
|
LowlightEnhanceOptions,
|
||||||
VirtualBackgroundSource,
|
VirtualBackgroundSource,
|
||||||
AudienceLatencyLevelType,
|
AudienceLatencyLevelType
|
||||||
StreamPublishState
|
|
||||||
} from "agora-electron-sdk";
|
} from "agora-electron-sdk";
|
||||||
import { GetRoomRtcToken, GetAgoraConf } from "@/api/Home/Index";
|
import { GetRoomRtcToken, GetAgoraConf } from "@/api/Home/Index";
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
|
|
@ -32,6 +32,7 @@ const os = require("os");
|
||||||
const option: any = {
|
const option: any = {
|
||||||
appId: '',
|
appId: '',
|
||||||
token: '',
|
token: '',
|
||||||
|
tokenA: '',
|
||||||
channelId: '',
|
channelId: '',
|
||||||
uid: '',
|
uid: '',
|
||||||
screenShareId: '',
|
screenShareId: '',
|
||||||
|
|
@ -125,25 +126,23 @@ export const agora = {
|
||||||
if (settingData.darkLightEnhancement) agora.setLowlightEnhanceOptions(settingData.darkLightEnhancement.isDarkLightEnhancement, settingData.darkLightEnhancement)
|
if (settingData.darkLightEnhancement) agora.setLowlightEnhanceOptions(settingData.darkLightEnhancement.isDarkLightEnhancement, settingData.darkLightEnhancement)
|
||||||
if (settingData.virtualBackground) {
|
if (settingData.virtualBackground) {
|
||||||
if (typeof settingData.virtualBackground.sourceIndex === 'number') {
|
if (typeof settingData.virtualBackground.sourceIndex === 'number') {
|
||||||
window.electron.getEnv().then(res => {
|
if (import.meta.env.VITE_ENV === 'development') {
|
||||||
if (res === 'development') {
|
window.electron.getAppPath().then((res: string) => {
|
||||||
window.electron.getAppPath().then((res: string) => {
|
const imagePath = path.join(res, 'src', 'assets', 'virtualBackground', `${settingData.virtualBackground.sourceIndex + 1}.png`);
|
||||||
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, {
|
agora.enableVirtualBackground(settingData.virtualBackground.isVirtualBackground, {
|
||||||
source: imagePath,
|
source: imagePath,
|
||||||
background_source_type: 2,
|
background_source_type: 2,
|
||||||
color: Number(settingData.virtualBackground.color),
|
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 {
|
} else {
|
||||||
agora.enableVirtualBackground(settingData.virtualBackground.isVirtualBackground, {
|
agora.enableVirtualBackground(settingData.virtualBackground.isVirtualBackground, {
|
||||||
background_source_type: 1,
|
background_source_type: 1,
|
||||||
|
|
@ -154,7 +153,7 @@ export const agora = {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
// 事件回调
|
// 事件回调
|
||||||
registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication, onRtcStats, onConnectionStateChanged, onLocalVideoStateChanged, onConnectionLost, onTokenPrivilegeWillExpire, onActiveSpeaker, onVideoPublishStateChanged, onAudioPublishStateChanged }: any) => {
|
registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication, onNetworkQuality, onRtcStats, onConnectionStateChanged, onLocalVideoStateChanged, onConnectionLost }: any) => {
|
||||||
rtcEngine.registerEventHandler({
|
rtcEngine.registerEventHandler({
|
||||||
// 监听本地用户加入频道事件
|
// 监听本地用户加入频道事件
|
||||||
onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
|
onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
|
||||||
|
|
@ -169,17 +168,25 @@ export const agora = {
|
||||||
await onUserOffline?.(connection, remoteUid, reason)
|
await onUserOffline?.(connection, remoteUid, reason)
|
||||||
},
|
},
|
||||||
// // 视频发布状态改变回调
|
// // 视频发布状态改变回调
|
||||||
onVideoPublishStateChanged: (source: VideoSourceType, channel: string, oldState: StreamPublishState, newState: StreamPublishState, elapseSinceLastState: number) => {
|
// onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
||||||
onVideoPublishStateChanged?.(source, channel, oldState, newState, elapseSinceLastState)
|
// if (newState === 1) {
|
||||||
},
|
|
||||||
|
// }
|
||||||
|
// },
|
||||||
// // 音频发布状态改变回调
|
// // 音频发布状态改变回调
|
||||||
onAudioPublishStateChanged: (channel: string, oldState: StreamPublishState, newState: StreamPublishState, elapseSinceLastState: number) => {
|
// onAudioPublishStateChanged: (channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
||||||
onAudioPublishStateChanged?.(channel, oldState, newState, elapseSinceLastState)
|
// if (newState === 1) {
|
||||||
},
|
|
||||||
|
// }
|
||||||
|
// },
|
||||||
// // 用户音量提示回调。
|
// // 用户音量提示回调。
|
||||||
onAudioVolumeIndication: async (_connection: RtcConnection, speakers: AudioVolumeInfo[], _speakerNumber: number, _totalVolume: number) => {
|
onAudioVolumeIndication: async (_connection: RtcConnection, speakers: AudioVolumeInfo[], _speakerNumber: number, _totalVolume: number) => {
|
||||||
await onAudioVolumeIndication?.(speakers)
|
await onAudioVolumeIndication?.(speakers)
|
||||||
},
|
},
|
||||||
|
//通话中每个用户的网络上下行 last mile 质量报告回调。
|
||||||
|
onNetworkQuality: async (connection: RtcConnection, remoteUid: number, txQuality: QualityType, rxQuality: QualityType) => {
|
||||||
|
await onNetworkQuality?.(connection, remoteUid, txQuality, rxQuality)
|
||||||
|
},
|
||||||
//当前通话相关的统计信息回调。
|
//当前通话相关的统计信息回调。
|
||||||
onRtcStats: async (_connection: RtcConnection, stats: RtcStats) => {
|
onRtcStats: async (_connection: RtcConnection, stats: RtcStats) => {
|
||||||
await onRtcStats?.(stats)
|
await onRtcStats?.(stats)
|
||||||
|
|
@ -195,26 +202,9 @@ export const agora = {
|
||||||
// 网络连接中断,且 SDK 无法在 10 秒内连接服务器回调。
|
// 网络连接中断,且 SDK 无法在 10 秒内连接服务器回调。
|
||||||
onConnectionLost: (_connection: RtcConnection) => {
|
onConnectionLost: (_connection: RtcConnection) => {
|
||||||
onConnectionLost?.()
|
onConnectionLost?.()
|
||||||
},
|
|
||||||
// Token 即将在 30s 内过期回调。
|
|
||||||
onTokenPrivilegeWillExpire: (connection: RtcConnection, token: string) => {
|
|
||||||
onTokenPrivilegeWillExpire?.(connection, token)
|
|
||||||
},
|
|
||||||
// 监测到远端最活跃用户回调。
|
|
||||||
onActiveSpeaker: (connection: RtcConnection, uid: number) => {
|
|
||||||
const setting = JSON.parse(storage.getItem('setting') as string);
|
|
||||||
if (setting.voiceStimulation) {
|
|
||||||
onActiveSpeaker?.(connection, uid)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 刷新token
|
|
||||||
refreshToken: async (data: any) => {
|
|
||||||
await rtcEngine.updateChannelMediaOptionsEx({
|
|
||||||
token: data.token,
|
|
||||||
}, data.connection);
|
|
||||||
},
|
|
||||||
// 获取视图模式
|
// 获取视图模式
|
||||||
getRrenderMode: (uid: number) => {
|
getRrenderMode: (uid: number) => {
|
||||||
if (String(uid).length === 9) {
|
if (String(uid).length === 9) {
|
||||||
|
|
@ -230,7 +220,7 @@ export const agora = {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await rtcEngine.setupLocalVideo({
|
await rtcEngine.setupLocalVideo({
|
||||||
renderMode: item.renderMode || agora.getRrenderMode(item.uid),
|
renderMode: agora.getRrenderMode(item.uid),
|
||||||
sourceType: item.sourceType,
|
sourceType: item.sourceType,
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
view: item.view,
|
view: item.view,
|
||||||
|
|
@ -243,7 +233,7 @@ export const agora = {
|
||||||
if (item.view?.childNodes.length === 1) {
|
if (item.view?.childNodes.length === 1) {
|
||||||
await rtcEngine.setupRemoteVideo(
|
await rtcEngine.setupRemoteVideo(
|
||||||
{
|
{
|
||||||
renderMode: item.renderMode || agora.getRrenderMode(item.uid),
|
renderMode: agora.getRrenderMode(item.uid),
|
||||||
sourceType: VideoSourceType.VideoSourceRemote,
|
sourceType: VideoSourceType.VideoSourceRemote,
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
view: item.view,
|
view: item.view,
|
||||||
|
|
@ -257,7 +247,7 @@ export const agora = {
|
||||||
if (item.view?.childNodes.length === 1) {
|
if (item.view?.childNodes.length === 1) {
|
||||||
await rtcEngine.setupRemoteVideoEx(
|
await rtcEngine.setupRemoteVideoEx(
|
||||||
{
|
{
|
||||||
renderMode: item.renderMode || agora.getRrenderMode(item.uid),
|
renderMode: agora.getRrenderMode(item.uid),
|
||||||
sourceType: VideoSourceType.VideoSourceRemote,
|
sourceType: VideoSourceType.VideoSourceRemote,
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
view: item.view,
|
view: item.view,
|
||||||
|
|
@ -271,7 +261,7 @@ export const agora = {
|
||||||
setupRemoteVideo: async (item: any) => {
|
setupRemoteVideo: async (item: any) => {
|
||||||
await rtcEngine.setupRemoteVideo(
|
await rtcEngine.setupRemoteVideo(
|
||||||
{
|
{
|
||||||
renderMode: item.renderMode || agora.getRrenderMode(item.uid),
|
renderMode: agora.getRrenderMode(item.uid),
|
||||||
sourceType: VideoSourceType.VideoSourceRemote,
|
sourceType: VideoSourceType.VideoSourceRemote,
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
view: item.view,
|
view: item.view,
|
||||||
|
|
@ -295,7 +285,7 @@ export const agora = {
|
||||||
},
|
},
|
||||||
// 加入频道
|
// 加入频道
|
||||||
joinChannel: async () => {
|
joinChannel: async () => {
|
||||||
await rtcEngine.enableAudioVolumeIndication(200, 3, true)
|
await rtcEngine.enableAudioVolumeIndication(100, 3, true)
|
||||||
await rtcEngine.joinChannel(option.token, option.channelId, option.uid);
|
await rtcEngine.joinChannel(option.token, option.channelId, option.uid);
|
||||||
await rtcEngine.setDualStreamModeEx(
|
await rtcEngine.setDualStreamModeEx(
|
||||||
SimulcastStreamMode.EnableSimulcastStream,
|
SimulcastStreamMode.EnableSimulcastStream,
|
||||||
|
|
@ -308,7 +298,6 @@ export const agora = {
|
||||||
},
|
},
|
||||||
{ channelId: option.channelId, localUid: Number(option.uid) }
|
{ channelId: option.channelId, localUid: Number(option.uid) }
|
||||||
);
|
);
|
||||||
await rtcEngine.setAudioScenario(8)
|
|
||||||
},
|
},
|
||||||
// 更新频道配置
|
// 更新频道配置
|
||||||
updateChannelMediaOptions: async (bool: boolean) => {
|
updateChannelMediaOptions: async (bool: boolean) => {
|
||||||
|
|
@ -331,10 +320,10 @@ export const agora = {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// 共享屏幕单独用户
|
// 共享屏幕单独用户
|
||||||
joinChannelEx: async (uid: any, token: string) => {
|
joinChannelEx: async (uid: any) => {
|
||||||
await agora.leaveChannelEx(uid)
|
await agora.leaveChannelEx(uid)
|
||||||
await rtcEngine.joinChannelEx(
|
await rtcEngine.joinChannelEx(
|
||||||
token,
|
option.token,
|
||||||
{ channelId: option.channelId, localUid: Number(uid) },
|
{ channelId: option.channelId, localUid: Number(uid) },
|
||||||
{
|
{
|
||||||
autoSubscribeAudio: false,//设置是否自动订阅所有音频流
|
autoSubscribeAudio: false,//设置是否自动订阅所有音频流
|
||||||
|
|
@ -347,11 +336,11 @@ export const agora = {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
// 所有用户加入的第二个房间
|
// 所有用户加入的第二个房间
|
||||||
allJoinChannelEx: async (bool: boolean = false, token: string) => {
|
allJoinChannelEx: async (bool: boolean = false) => {
|
||||||
const user = await JSON.parse(storage.getItem('user') as string)
|
const user = await JSON.parse(storage.getItem('user') as string)
|
||||||
await agora.startCameraCapture(true)
|
await agora.startCameraCapture(true)
|
||||||
await rtcEngine.joinChannelEx(
|
await rtcEngine.joinChannelEx(
|
||||||
token,
|
option.tokenA,
|
||||||
{ channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) },
|
{ channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) },
|
||||||
{
|
{
|
||||||
clientRoleType: bool ? ClientRoleType.ClientRoleAudience : ClientRoleType.ClientRoleBroadcaster, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
|
clientRoleType: bool ? ClientRoleType.ClientRoleAudience : ClientRoleType.ClientRoleBroadcaster, //用户角色 ClientRoleBroadcaster 主播 ClientRoleAudience 观众
|
||||||
|
|
@ -393,14 +382,10 @@ export const agora = {
|
||||||
},
|
},
|
||||||
// 销毁视频渲染dom
|
// 销毁视频渲染dom
|
||||||
destroyRendererByConfig: async (uid: number, channelId?: string) => {
|
destroyRendererByConfig: async (uid: number, channelId?: string) => {
|
||||||
await rtcEngine.destroyRendererByConfig(option.uid === uid ? VideoSourceType.VideoSourceCameraPrimary : VideoSourceType.VideoSourceRemote, channelId, uid);
|
await rtcEngine.destroyRendererByConfig(VideoSourceType.VideoSourceRemote, channelId, uid);
|
||||||
},
|
},
|
||||||
destroyRendererByConfigPreview: async (uid: number, channelId: number) => {
|
destroyRendererByView: async () => {
|
||||||
await agora.destroyRendererByView('videoPreview')
|
let dom = document.getElementById(`meetingAbsoluteVideo`);
|
||||||
await rtcEngine.leaveChannelEx({ channelId: `${channelId + uid}`, localUid: Number(uid) })
|
|
||||||
},
|
|
||||||
destroyRendererByView: async (key: string) => {
|
|
||||||
let dom = document.getElementById(key);
|
|
||||||
if (dom) {
|
if (dom) {
|
||||||
await rtcEngine.destroyRendererByView(dom);
|
await rtcEngine.destroyRendererByView(dom);
|
||||||
}
|
}
|
||||||
|
|
@ -448,8 +433,8 @@ export const agora = {
|
||||||
startCameraCapture: async (bool: boolean = false) => {
|
startCameraCapture: async (bool: boolean = false) => {
|
||||||
await rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {
|
await rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {
|
||||||
format: {
|
format: {
|
||||||
width: bool ? 160 : 1920,
|
width: bool ? 160 : 1280,
|
||||||
height: bool ? 160 : 1080,
|
height: bool ? 160 : 720,
|
||||||
fps: 15,
|
fps: 15,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -461,6 +446,7 @@ export const agora = {
|
||||||
// 加入频道
|
// 加入频道
|
||||||
setJoinChannel: async (data: any) => {
|
setJoinChannel: async (data: any) => {
|
||||||
option.token = data.token;
|
option.token = data.token;
|
||||||
|
option.tokenA = data.tokenA;
|
||||||
option.channelId = data.channelId;
|
option.channelId = data.channelId;
|
||||||
option.uid = Number(data.uid);
|
option.uid = Number(data.uid);
|
||||||
option.screenShareId = data.screenShareId;
|
option.screenShareId = data.screenShareId;
|
||||||
|
|
@ -471,7 +457,7 @@ export const agora = {
|
||||||
return await rtcEngine.getScreenCaptureSources(thumbSize, iconSize, includeScreen)
|
return await rtcEngine.getScreenCaptureSources(thumbSize, iconSize, includeScreen)
|
||||||
},
|
},
|
||||||
// 共享屏幕采集
|
// 共享屏幕采集
|
||||||
setDesktopCapturerVideo: async (targetSource: any, isComputerAudio: boolean, isFluencyPriority: boolean, token: string) => {
|
setDesktopCapturerVideo: async (targetSource: any, isComputerAudio: boolean, isFluencyPriority: boolean) => {
|
||||||
const user = JSON.parse(storage.getItem('user') as string)
|
const user = JSON.parse(storage.getItem('user') as string)
|
||||||
agora.stopScreenCapture();
|
agora.stopScreenCapture();
|
||||||
if (isComputerAudio) {
|
if (isComputerAudio) {
|
||||||
|
|
@ -479,7 +465,7 @@ export const agora = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
frameRate: isFluencyPriority ? 15 : 7,
|
frameRate: isFluencyPriority ? 30 : 15,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 1920,
|
width: 1920,
|
||||||
height: 1080,
|
height: 1080,
|
||||||
|
|
@ -507,7 +493,7 @@ export const agora = {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await agora.joinChannelEx(user.screenShareId, token)
|
await agora.joinChannelEx(user.screenShareId)
|
||||||
},
|
},
|
||||||
// 获取系统中所有的视频设备列表。
|
// 获取系统中所有的视频设备列表。
|
||||||
getVideoDeviceManager: async (): Promise<any> => {
|
getVideoDeviceManager: async (): Promise<any> => {
|
||||||
|
|
@ -521,12 +507,12 @@ export const agora = {
|
||||||
await rtcEngine.getVideoDeviceManager().setDevice(deviceIdUTF8)
|
await rtcEngine.getVideoDeviceManager().setDevice(deviceIdUTF8)
|
||||||
},
|
},
|
||||||
// 开启本地视频预览
|
// 开启本地视频预览
|
||||||
startPreview: async (id: string, uid: number, channelId: number): Promise<void> => {
|
startPreview: async (id: string, uid: number): Promise<void> => {
|
||||||
rtcEngine.enableVideo();
|
rtcEngine.enableVideo();
|
||||||
rtcEngine.startPreview();
|
rtcEngine.startPreview();
|
||||||
await GetRoomRtcToken(`${channelId + uid}`).then(async (res) => {
|
await GetRoomRtcToken(`${+new Date()}`).then(async (res) => {
|
||||||
await rtcEngine.joinChannelEx(res.data, {
|
await rtcEngine.joinChannelEx(res.data, {
|
||||||
channelId: `${channelId + uid}`,
|
channelId: `${+new Date() + uid}`,
|
||||||
localUid: uid,
|
localUid: uid,
|
||||||
}, {
|
}, {
|
||||||
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting,
|
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting,
|
||||||
|
|
|
||||||
|
|
@ -84,8 +84,6 @@ import icon52Select from '@/assets/icon52-select.png'
|
||||||
import icon53 from '@/assets/icon53.png'
|
import icon53 from '@/assets/icon53.png'
|
||||||
import icon54 from '@/assets/icon54.png'
|
import icon54 from '@/assets/icon54.png'
|
||||||
import icon55 from '@/assets/icon55.png'
|
import icon55 from '@/assets/icon55.png'
|
||||||
import icon56 from '@/assets/icon56.png'
|
|
||||||
import icon56Active from '@/assets/icon56-active.png'
|
|
||||||
export default {
|
export default {
|
||||||
loading,
|
loading,
|
||||||
icon,
|
icon,
|
||||||
|
|
@ -172,7 +170,5 @@ export default {
|
||||||
icon52Select,
|
icon52Select,
|
||||||
icon53,
|
icon53,
|
||||||
icon54,
|
icon54,
|
||||||
icon55,
|
icon55
|
||||||
icon56,
|
|
||||||
icon56Active
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import storage from "./storage";
|
import storage from "./storage";
|
||||||
import axios from "axios";
|
|
||||||
import yaml from 'js-yaml'
|
|
||||||
export const setKeyOpenChildWindow = async (key: string, bool: boolean) => {
|
export const setKeyOpenChildWindow = async (key: string, bool: boolean) => {
|
||||||
const openChildWindow = await JSON.parse(storage.getItem('openChildWindow') as string)
|
const openChildWindow = await JSON.parse(storage.getItem('openChildWindow') as string)
|
||||||
openChildWindow[key] = bool;
|
openChildWindow[key] = bool;
|
||||||
|
|
@ -29,7 +27,6 @@ export const storageSeeting: any = {
|
||||||
shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径
|
shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径
|
||||||
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
||||||
closeSetting: 'hide', //关闭按钮设置
|
closeSetting: 'hide', //关闭按钮设置
|
||||||
voiceStimulation: true, //语音激励
|
|
||||||
isAINoiseReduction: true, //是否开启ai降噪
|
isAINoiseReduction: true, //是否开启ai降噪
|
||||||
aINoiseReduction: 1, // 降噪模式
|
aINoiseReduction: 1, // 降噪模式
|
||||||
isRecordingTips: true, //是否开启录制提示
|
isRecordingTips: true, //是否开启录制提示
|
||||||
|
|
@ -62,61 +59,15 @@ export const getUpdateUrl = (env: string) => {
|
||||||
switch (env) {
|
switch (env) {
|
||||||
case 'xy':
|
case 'xy':
|
||||||
return 'https://meeting-api.23544.com/meeting/xysz'
|
return 'https://meeting-api.23544.com/meeting/xysz'
|
||||||
case 'development':
|
|
||||||
return 'http://192.168.2.9:8827'
|
|
||||||
default:
|
default:
|
||||||
return 'https://meeting-api.23544.com/meeting/update'
|
return 'https://meeting-api.23544.com/meeting/update'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const getTitle = async () => {
|
export const getTitle = (env: string) => {
|
||||||
let env = await window.electron.getEnv()
|
|
||||||
let str;
|
|
||||||
switch (env) {
|
switch (env) {
|
||||||
case 'xy':
|
case 'xy':
|
||||||
str = '湖北襄阳四中教研平台'
|
return '湖北襄阳四中教研平台'
|
||||||
break;
|
|
||||||
case 'development':
|
|
||||||
str = '智汇享'
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
str = '智汇享'
|
return '智汇享'
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
document.getElementsByTagName('title')[0].innerText = str
|
|
||||||
}
|
|
||||||
export const compareVersions = (version1: string, version2: string): number => {
|
|
||||||
const v1Parts = version1.split('.').map(Number);
|
|
||||||
const v2Parts = version2.split('.').map(Number);
|
|
||||||
const maxLength = Math.max(v1Parts.length, v2Parts.length);
|
|
||||||
for (let i = 0; i < maxLength; i++) {
|
|
||||||
const v1 = v1Parts[i] || 0;
|
|
||||||
const v2 = v2Parts[i] || 0;
|
|
||||||
if (v1 > v2) {
|
|
||||||
return 1;
|
|
||||||
} else if (v1 < v2) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isVersion = (callBack: Function) => {
|
|
||||||
window.electron.getEnv().then(res => {
|
|
||||||
axios.get(`${getUpdateUrl(res)}/latest.yml`).then(res => {
|
|
||||||
if (res.status === 200 && res.data) {
|
|
||||||
const data = yaml.load(res.data); // 解析 YAML 内容
|
|
||||||
window.electron.getVersion().then(req => {
|
|
||||||
if (compareVersions(data.version, req) == 1) {
|
|
||||||
callBack(true, data)
|
|
||||||
} else {
|
|
||||||
callBack(false, data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
callBack(false)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
callBack(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,8 +3,6 @@ module.exports = {
|
||||||
switch (env) {
|
switch (env) {
|
||||||
case 'xy':
|
case 'xy':
|
||||||
return 'https://meeting-api.23544.com/meeting/xysz'
|
return 'https://meeting-api.23544.com/meeting/xysz'
|
||||||
case 'development':
|
|
||||||
return 'http://192.168.2.9:8827'
|
|
||||||
default:
|
default:
|
||||||
return 'https://meeting-api.23544.com/meeting/update'
|
return 'https://meeting-api.23544.com/meeting/update'
|
||||||
}
|
}
|
||||||
|
|
@ -13,8 +11,6 @@ module.exports = {
|
||||||
switch (env) {
|
switch (env) {
|
||||||
case 'xy':
|
case 'xy':
|
||||||
return '湖北襄阳四中教研平台'
|
return '湖北襄阳四中教研平台'
|
||||||
case 'development':
|
|
||||||
return '智汇享'
|
|
||||||
default:
|
default:
|
||||||
return '智汇享'
|
return '智汇享'
|
||||||
}
|
}
|
||||||
|
|
@ -23,8 +19,6 @@ module.exports = {
|
||||||
switch (env) {
|
switch (env) {
|
||||||
case 'xy':
|
case 'xy':
|
||||||
return 'icon54'
|
return 'icon54'
|
||||||
case 'development':
|
|
||||||
return 'icon'
|
|
||||||
default:
|
default:
|
||||||
return 'icon'
|
return 'icon'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { AxiosRequestConfig, AxiosResponse } from 'axios'
|
import { AxiosRequestConfig, AxiosResponse } from 'axios'
|
||||||
import Request from './request'
|
import Request from './request'
|
||||||
import { constant } from '@/config'
|
import { constant } from '@/config'
|
||||||
let baseURL = !location.hostname.includes('meeting-api.23544.com') ? 'http://192.168.2.9:5192' : 'https://meeting-api.23544.com/pc'
|
|
||||||
// 实例化
|
// 实例化
|
||||||
const req = new Request({
|
const req = new Request({
|
||||||
baseURL,
|
baseURL: import.meta.env.VITE_BASE_URL_API,
|
||||||
timeout: constant.CONFIG_REQUEST_TIMEOUT_TIME as number,
|
timeout: constant.CONFIG_REQUEST_TIMEOUT_TIME as number,
|
||||||
interceptors: {
|
interceptors: {
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
|
|
@ -22,4 +22,5 @@ const request = (config: any) => {
|
||||||
}
|
}
|
||||||
return req.request<any>(config)
|
return req.request<any>(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default request
|
export default request
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,6 @@ class Request {
|
||||||
case 403:
|
case 403:
|
||||||
updatePostRefresh()
|
updatePostRefresh()
|
||||||
break
|
break
|
||||||
case 502:
|
|
||||||
message.error('网络已断开,请检查网络状态')
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
message.error(err.message)
|
message.error(err.message)
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -404,17 +404,4 @@ $pagination-hover-background-color: #5575F2;
|
||||||
|
|
||||||
.ant-tabs {
|
.ant-tabs {
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
}
|
|
||||||
|
|
||||||
.ant-rate .ant-rate-star-first,
|
|
||||||
.ant-rate .ant-rate-star-second {
|
|
||||||
color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hideCancelText {
|
|
||||||
.ant-modal-confirm-btns {
|
|
||||||
>button:nth-child(1){
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -64,6 +64,7 @@ export default defineConfig({
|
||||||
AudioAinsMode,
|
AudioAinsMode,
|
||||||
SimulcastStreamMode,
|
SimulcastStreamMode,
|
||||||
VideoStreamType,
|
VideoStreamType,
|
||||||
|
QualityType,
|
||||||
RtcConnection,
|
RtcConnection,
|
||||||
RtcStats,
|
RtcStats,
|
||||||
AudioVolumeInfo,
|
AudioVolumeInfo,
|
||||||
|
|
@ -76,9 +77,7 @@ export default defineConfig({
|
||||||
ColorEnhanceOptions,
|
ColorEnhanceOptions,
|
||||||
LowlightEnhanceOptions,
|
LowlightEnhanceOptions,
|
||||||
VirtualBackgroundSource,
|
VirtualBackgroundSource,
|
||||||
AudienceLatencyLevelType,
|
AudienceLatencyLevelType
|
||||||
StreamPublishState,
|
|
||||||
IMediaEngine
|
|
||||||
} = require("agora-electron-sdk")
|
} = require("agora-electron-sdk")
|
||||||
export {
|
export {
|
||||||
createAgoraRtcEngine,
|
createAgoraRtcEngine,
|
||||||
|
|
@ -91,6 +90,7 @@ export default defineConfig({
|
||||||
AudioAinsMode,
|
AudioAinsMode,
|
||||||
SimulcastStreamMode,
|
SimulcastStreamMode,
|
||||||
VideoStreamType,
|
VideoStreamType,
|
||||||
|
QualityType,
|
||||||
RtcConnection,
|
RtcConnection,
|
||||||
RtcStats,
|
RtcStats,
|
||||||
AudioVolumeInfo,
|
AudioVolumeInfo,
|
||||||
|
|
@ -103,9 +103,7 @@ export default defineConfig({
|
||||||
ColorEnhanceOptions,
|
ColorEnhanceOptions,
|
||||||
LowlightEnhanceOptions,
|
LowlightEnhanceOptions,
|
||||||
VirtualBackgroundSource,
|
VirtualBackgroundSource,
|
||||||
AudienceLatencyLevelType,
|
AudienceLatencyLevelType
|
||||||
StreamPublishState,
|
|
||||||
IMediaEngine
|
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
|
|
|
||||||