This commit is contained in:
parent
0df7896ee5
commit
1674f227a3
16
main.js
16
main.js
|
|
@ -1,4 +1,4 @@
|
||||||
const { app, BrowserWindow, screen, Tray, nativeImage, Menu, ipcMain, clipboard, dialog } = require('electron');
|
const { app, BrowserWindow, screen, Tray, nativeImage, Menu, ipcMain, clipboard, dialog, webFrame } = require('electron');
|
||||||
const path = require('node:path')
|
const path = require('node:path')
|
||||||
app.allowRendererProcessReuse = false;
|
app.allowRendererProcessReuse = false;
|
||||||
let mainWindow = null;
|
let mainWindow = null;
|
||||||
|
|
@ -136,20 +136,6 @@ app.on('ready', () => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 下载文件并放置选择的文件夹
|
|
||||||
ipcMain.handle('dwFile', (event, url) => {
|
|
||||||
dialog.showOpenDialog(mainWindow, {
|
|
||||||
properties: ['openDirectory']
|
|
||||||
}).then(result => {
|
|
||||||
if (!result.canceled) {
|
|
||||||
const selectedPath = result.filePaths[0];
|
|
||||||
console.log('Selected download folder:', selectedPath);
|
|
||||||
console.log(url);
|
|
||||||
}
|
|
||||||
}).catch(err => {
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 导出是否全屏
|
// 导出是否全屏
|
||||||
ipcMain.handle('getIsMaximized', () => {
|
ipcMain.handle('getIsMaximized', () => {
|
||||||
return mainWindow.isMaximized();
|
return mainWindow.isMaximized();
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,5 @@ window.electron = {
|
||||||
// 复制文字
|
// 复制文字
|
||||||
setWriteText: (text) => {
|
setWriteText: (text) => {
|
||||||
return ipcRenderer.invoke('setWriteText', text)
|
return ipcRenderer.invoke('setWriteText', text)
|
||||||
},
|
|
||||||
// 下载文件并放置选择的文件夹
|
|
||||||
dwFile: (url) => {
|
|
||||||
ipcRenderer.invoke('dwFile', url)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { request } from '@/utils'
|
import { request } from '@/utils'
|
||||||
export const GetCheckUser = (userName: string) =>
|
export const GetCheckUser = (account: string) =>
|
||||||
request({
|
request({
|
||||||
url: `/auth/check-user?userName=${userName}`,
|
url: `/auth/check-user?account=${account}`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,3 +32,9 @@ export const GetRoomFileDwUrl = (fileUrl: string, fileId: string) =>
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const GetRoomUser = (roomNum: string) =>
|
||||||
|
request({
|
||||||
|
url: `/room/user?roomNum=${roomNum}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 754 B |
|
|
@ -0,0 +1,85 @@
|
||||||
|
// 设置向导
|
||||||
|
.stupWizard {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
>div:nth-child(1) {
|
||||||
|
padding: 20px 0 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
max-height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
>div:nth-child(1) {
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>div:nth-child(2) {
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 22px;
|
||||||
|
|
||||||
|
>span {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #828282;
|
||||||
|
font-size: 18px;
|
||||||
|
width: 130px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>div:nth-child(3) {
|
||||||
|
margin-top: 34px;
|
||||||
|
|
||||||
|
>span {
|
||||||
|
color: #828282;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 36px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>div {
|
||||||
|
flex-grow: 1;
|
||||||
|
height: 40px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
>div {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 0%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>div:nth-child(2) {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
import styles from '@/components/StupWizard/index.module.scss'
|
||||||
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
|
import { Button, message, Modal, Select, Slider } from 'antd';
|
||||||
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
|
import agora from '@/utils/package/agora'
|
||||||
|
const StupWizard = forwardRef((props: any, ref: any) => {
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
changeIsStupWizard: () => {
|
||||||
|
setIsStupWizard(true)
|
||||||
|
getAudioMediaList(true)
|
||||||
|
agora.startPlaybackDeviceTest()
|
||||||
|
agora.setPlaybackDeviceVolume(100)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const [isStupWizard, setIsStupWizard] = useState(false);
|
||||||
|
const [stepsStatus, setStepsStatus] = useState<number>(1);
|
||||||
|
const [isVideoLoad, setIsVideoLoad] = useState<boolean>(false);
|
||||||
|
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
|
||||||
|
currentDevices: [],
|
||||||
|
currentDevice: {},
|
||||||
|
currentVolume: 0,
|
||||||
|
});
|
||||||
|
// agora.startRecordingDeviceTest(200)
|
||||||
|
const getAudioMediaList = (bool: boolean): void => {
|
||||||
|
const { currentDevices, currentVolume, currentDevice } = agora.getAudioMediaList(bool);
|
||||||
|
setAudioDeviceManager({
|
||||||
|
currentDevices: currentDevices.map((row: any) => {
|
||||||
|
return {
|
||||||
|
value: row.deviceId,
|
||||||
|
label: row.deviceName
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
currentDevice: currentDevice.deviceId,
|
||||||
|
currentVolume,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 音频设置向导
|
||||||
|
// 视频测试
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal title="设置向导" open={isStupWizard} footer={null} closable={false} centered width={'40vw'}>
|
||||||
|
<div className={styles.stupWizard}>
|
||||||
|
<div>
|
||||||
|
<div>音频设置向导</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<span>音频输出设备:</span>
|
||||||
|
<Select
|
||||||
|
options={audioDeviceManager.currentDevices} style={{ flexGrow: 1 }}
|
||||||
|
value={audioDeviceManager.currentDevice} onChange={(e) => {
|
||||||
|
setAudioDeviceManager({
|
||||||
|
...audioDeviceManager,
|
||||||
|
currentDevice: e
|
||||||
|
})
|
||||||
|
agora.setPlaybackDevice(e)
|
||||||
|
}} />;
|
||||||
|
<audio src="" id='startAudio'></audio>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>调节声音大小:</span>
|
||||||
|
<Slider min={0} max={255} value={audioDeviceManager.currentVolume} onChange={(e) => {
|
||||||
|
setAudioDeviceManager({
|
||||||
|
...audioDeviceManager,
|
||||||
|
currentVolume: e
|
||||||
|
})
|
||||||
|
agora.setPlaybackDeviceVolume(e)
|
||||||
|
}} style={{ flexGrow: 1 }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>正在播放语音,听到语音代表放音设备没问题</span>
|
||||||
|
<div>
|
||||||
|
<img src={ImageUrl.icon36} alt="" />
|
||||||
|
<div>
|
||||||
|
<img src={ImageUrl.icon34} alt="" />
|
||||||
|
<div id='recordingDeviceTest'>
|
||||||
|
<img src={ImageUrl.icon35} alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<Button type="primary" className='m-ant-btn' onClick={() => {
|
||||||
|
|
||||||
|
}}>下一步</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <div className={styles.stupWizard}>
|
||||||
|
<div>
|
||||||
|
<div>音频设置向导</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<span>音频输入设备:</span>
|
||||||
|
<Select
|
||||||
|
options={audioDeviceManager.currentDevices} style={{ flexGrow: 1 }}
|
||||||
|
value={audioDeviceManager.currentDevice} onChange={(e) => {
|
||||||
|
setAudioDeviceManager({
|
||||||
|
...audioDeviceManager,
|
||||||
|
currentDevice: e
|
||||||
|
})
|
||||||
|
agora.setRecordingDevice(e);
|
||||||
|
getAudioMediaList()
|
||||||
|
}} />;
|
||||||
|
<audio src="" id='startAudio'></audio>
|
||||||
|
</div>
|
||||||
|
{stepsStatus ? <div>
|
||||||
|
<span>调节声音大小:</span>
|
||||||
|
<Slider min={0} max={255} value={audioDeviceManager.currentVolume} onChange={(e) => {
|
||||||
|
setAudioDeviceManager({
|
||||||
|
...audioDeviceManager,
|
||||||
|
currentVolume: e
|
||||||
|
})
|
||||||
|
agora.setRecordingDeviceVolume(e)
|
||||||
|
}} style={{ flexGrow: 1 }} />
|
||||||
|
</div> :
|
||||||
|
<div>
|
||||||
|
<span>视频预览:</span>
|
||||||
|
<video id='startPreview'
|
||||||
|
poster={ImageUrl.error}
|
||||||
|
style={{ width: '226px', height: '136px', backgroundColor: 'black' }}>
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>您可以对着麦克风说话,试听表克风的输入质量</span>
|
||||||
|
<div>
|
||||||
|
<img src={ImageUrl.icon33} alt="" />
|
||||||
|
<div>
|
||||||
|
<img src={ImageUrl.icon34} alt="" />
|
||||||
|
<div id='recordingDeviceTest'>
|
||||||
|
<img src={ImageUrl.icon35} alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<Button type="primary" className='m-ant-btn' onClick={() => {
|
||||||
|
let audio = document.getElementById('startAudio') as any;
|
||||||
|
if (audio.srcObject) {
|
||||||
|
const tracks = audio.srcObject.getTracks();
|
||||||
|
tracks.forEach((track: any) => {
|
||||||
|
track.stop();
|
||||||
|
});
|
||||||
|
audio.srcObject = null;
|
||||||
|
}
|
||||||
|
// setStepsStatus(false)
|
||||||
|
agora.startPreview().then((res: boolean) => {
|
||||||
|
setIsVideoLoad(res)
|
||||||
|
})
|
||||||
|
}}>下一步</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
style={{ backgroundColor: '#31353A', marginRight: '14px' }}
|
||||||
|
onClick={() => {
|
||||||
|
if (isVideoLoad) {
|
||||||
|
setIsVideoLoad(false)
|
||||||
|
agora.stopAudioDeviceLoopbackTest()
|
||||||
|
setStepsStatus(true)
|
||||||
|
agora.startRecordingDeviceTest(200)
|
||||||
|
} else {
|
||||||
|
message.error('视频加载中!')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>上一步</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
className='m-ant-btn'
|
||||||
|
onClick={() => {
|
||||||
|
if (isVideoLoad) {
|
||||||
|
agora.stopAudioDeviceLoopbackTest()
|
||||||
|
agora.setRecordingDeviceVolume(audioDeviceManager.currentVolume)
|
||||||
|
setIsStupWizard(false)
|
||||||
|
setStepsStatus(true)
|
||||||
|
setIsVideoLoad(false)
|
||||||
|
} else {
|
||||||
|
message.error('视频加载中!')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>完成
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
export default StupWizard
|
||||||
|
|
@ -577,93 +577,6 @@
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置向导
|
|
||||||
.stupWizard {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
>div:nth-child(1) {
|
|
||||||
padding: 20px 0 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
max-height: 60vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
>div:nth-child(1) {
|
|
||||||
color: #EEEEEE;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
>div:nth-child(2) {
|
|
||||||
>div {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 22px;
|
|
||||||
|
|
||||||
>span {
|
|
||||||
flex-shrink: 0;
|
|
||||||
color: #828282;
|
|
||||||
font-size: 18px;
|
|
||||||
width: 130px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>div:nth-child(3) {
|
|
||||||
margin-top: 34px;
|
|
||||||
|
|
||||||
>span {
|
|
||||||
color: #828282;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
>div {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
>img {
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 36px;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
>div {
|
|
||||||
flex-grow: 1;
|
|
||||||
height: 40px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
>img {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
>div {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 0%;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
>img {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>div:nth-child(2) {
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 共享文件
|
// 共享文件
|
||||||
.sharedFilesModel {
|
.sharedFilesModel {
|
||||||
>div:nth-child(1) {
|
>div:nth-child(1) {
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,27 @@
|
||||||
import styles from '@/page/Meeting/index.module.scss'
|
import styles from '@/page/Meeting/index.module.scss'
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import Operation from '@/components/Operation';
|
import Operation from '@/components/Operation';
|
||||||
import { Navigation, Pagination } from 'swiper/modules';
|
import { Navigation, Pagination } from 'swiper/modules';
|
||||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
import 'swiper/css';
|
import 'swiper/css';
|
||||||
import 'swiper/css/navigation';
|
import 'swiper/css/navigation';
|
||||||
import 'swiper/css/pagination';
|
import 'swiper/css/pagination';
|
||||||
import { Button, Input, Popover, Modal, Checkbox, message, Select, Slider, Table, Pagination as AntdPagination } from "antd";
|
import { Button, Input, Popover, Modal, Checkbox, message, Table, Pagination as AntdPagination } from "antd";
|
||||||
import { DeleteOutlined, FolderOutlined, ProfileOutlined, ReloadOutlined, SearchOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, ProfileOutlined, ReloadOutlined, SearchOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { thumbImageBufferToBase64 } from '@/utils/package/base64'
|
import { thumbImageBufferToBase64 } from '@/utils/package/base64'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { GetRoomFile, PostRoomFile, DeleteRoomFile, GetRoomUpFileurl, GetRoomFileDwUrl } from '@/api/Meeting';
|
import { GetRoomFile, PostRoomFile, DeleteRoomFile, GetRoomUpFileurl, GetRoomFileDwUrl, GetRoomUser } from '@/api/Meeting';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import ImageUrl from '@/utils/package/imageUrl'
|
import ImageUrl from '@/utils/package/imageUrl'
|
||||||
import agora from '@/utils/package/agora'
|
import agora from '@/utils/package/agora'
|
||||||
|
import StupWizard from '@/components/StupWizard';
|
||||||
|
import { onInvoke } from '@/utils/package/signalr';
|
||||||
const { Column } = Table
|
const { Column } = Table
|
||||||
const Meeting: React.FC = () => {
|
const Meeting: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { state } = useLocation();
|
const { state } = useLocation();
|
||||||
|
const stupWizardRef = useRef<any>();
|
||||||
const [statusList, setStatusList] = useState({
|
const [statusList, setStatusList] = useState({
|
||||||
userList: false,
|
userList: false,
|
||||||
userChatList: false,
|
userChatList: false,
|
||||||
|
|
@ -27,7 +30,6 @@ const Meeting: React.FC = () => {
|
||||||
const [isSharedScreenModal, setIsSharedScreenModal] = useState(false);
|
const [isSharedScreenModal, setIsSharedScreenModal] = useState(false);
|
||||||
const [isInit, setIsInit] = useState(true);
|
const [isInit, setIsInit] = useState(true);
|
||||||
const [user, setUser] = useState<any>({});
|
const [user, setUser] = useState<any>({});
|
||||||
const [isStupWizard, setIsStupWizard] = useState(false);
|
|
||||||
const [showRowSelection, setShowRowSelection] = useState(false);
|
const [showRowSelection, setShowRowSelection] = useState(false);
|
||||||
const [isSharedFilesModel, setIsSharedFilesModel] = useState(false);
|
const [isSharedFilesModel, setIsSharedFilesModel] = useState(false);
|
||||||
const [sharedScreenList, setSharedScreenList] = useState<any>([]);
|
const [sharedScreenList, setSharedScreenList] = useState<any>([]);
|
||||||
|
|
@ -97,11 +99,6 @@ const Meeting: React.FC = () => {
|
||||||
itemIndex: 0,
|
itemIndex: 0,
|
||||||
rowIndex: 0,
|
rowIndex: 0,
|
||||||
});
|
});
|
||||||
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
|
|
||||||
currentDevices: [],
|
|
||||||
currentDevice: {},
|
|
||||||
currentVolume: 0,
|
|
||||||
});
|
|
||||||
const [fileList, setFileList] = useState({
|
const [fileList, setFileList] = useState({
|
||||||
data: [],
|
data: [],
|
||||||
keyword: '',
|
keyword: '',
|
||||||
|
|
@ -109,27 +106,31 @@ const Meeting: React.FC = () => {
|
||||||
pageIndex: 1,
|
pageIndex: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
})
|
})
|
||||||
|
const [roomUserList, setRoomUserList] = useState<any>([])
|
||||||
|
|
||||||
const [stepsStatus, setStepsStatus] = useState<boolean>(true);
|
|
||||||
const [isVideoLoad, setIsVideoLoad] = useState<boolean>(false);
|
|
||||||
const [list] = useState<number[]>([1, 2, 3, 4, 5, 6, 7])
|
const [list] = useState<number[]>([1, 2, 3, 4, 5, 6, 7])
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const [videoID, setVideoID] = useState('')
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isInit) {
|
if (isInit) {
|
||||||
setUser(JSON.parse(storage.getItem('user') as string))
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
// agora.setJoinChannel({
|
agora.init()
|
||||||
// channelId: state.channelId,
|
agora.setJoinChannel({
|
||||||
// userid: user.userName,
|
channelId: state.channelId,
|
||||||
// token: state.token,
|
userid: userInfo.account,
|
||||||
// })
|
token: state.token,
|
||||||
|
})
|
||||||
|
setUser(userInfo)
|
||||||
setIsInit(false)
|
setIsInit(false)
|
||||||
|
window.addEventListener('customStorageChange', handleCustomStorageChange);
|
||||||
} else {
|
} else {
|
||||||
getRoomFile()
|
getRoomFile()
|
||||||
}
|
}
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('customStorageChange', handleCustomStorageChange);
|
||||||
|
};
|
||||||
}, [fileList.pageIndex]);
|
}, [fileList.pageIndex]);
|
||||||
|
|
||||||
|
// 操作按钮
|
||||||
const changeStatusList = async (row: any, itemIndex: number, rowIndex: number): Promise<void> => {
|
const changeStatusList = async (row: any, itemIndex: number, rowIndex: number): Promise<void> => {
|
||||||
const footerListTemplate = [...footerList]
|
const footerListTemplate = [...footerList]
|
||||||
setFooterListIndex({
|
setFooterListIndex({
|
||||||
|
|
@ -182,9 +183,7 @@ const Meeting: React.FC = () => {
|
||||||
agora.muteLocalVideoStream(false)
|
agora.muteLocalVideoStream(false)
|
||||||
break;
|
break;
|
||||||
case '设置向导':
|
case '设置向导':
|
||||||
getAudioMediaList()
|
stupWizardRef.current.changeIsStupWizard()
|
||||||
agora.startRecordingDeviceTest(200)
|
|
||||||
setIsStupWizard(true)
|
|
||||||
break;
|
break;
|
||||||
case '录制':
|
case '录制':
|
||||||
footerListTemplate[itemIndex][rowIndex].title = '录制中'
|
footerListTemplate[itemIndex][rowIndex].title = '录制中'
|
||||||
|
|
@ -205,23 +204,19 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeVdeio = async (bool: boolean): Promise<void> => {
|
// 分享屏幕
|
||||||
if (bool) {
|
const clickSharedScreen = async (): Promise<void> => {
|
||||||
|
let data = sharedScreenList.find((item: any) => item.sourceId === sharedScreenItem.sourceId)
|
||||||
|
if (data) {
|
||||||
|
const footerListTemplate = [...footerList]
|
||||||
|
footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享'
|
||||||
|
setIsSharedScreenModal(false)
|
||||||
|
agora.setDesktopCapturerVideo(sharedScreenItem)
|
||||||
} else {
|
} else {
|
||||||
let data = sharedScreenList.find((item: any) => item.sourceId === sharedScreenItem.sourceId)
|
message.error('请选择应用!')
|
||||||
if (data) {
|
|
||||||
const footerListTemplate = [...footerList]
|
|
||||||
footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享'
|
|
||||||
setIsSharedScreenModal(false)
|
|
||||||
agora.setDesktopCapturerVideo(sharedScreenItem)
|
|
||||||
setVideoID(agora.getVideoId())
|
|
||||||
} else {
|
|
||||||
message.error('请选择应用!')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 获取桌面可共享屏幕的引用
|
||||||
const getDesktopCapturerVideo = (): void => {
|
const getDesktopCapturerVideo = (): void => {
|
||||||
agora.getDesktopCapturerVideo().then((res: any) => {
|
agora.getDesktopCapturerVideo().then((res: any) => {
|
||||||
if (sharedScreenList.length !== res.length) {
|
if (sharedScreenList.length !== res.length) {
|
||||||
|
|
@ -238,20 +233,7 @@ const Meeting: React.FC = () => {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAudioMediaList = (): void => {
|
// 获取共享文件列表
|
||||||
const { currentDevices, currentDevice, currentVolume } = agora.getAudioMediaList();
|
|
||||||
setAudioDeviceManager({
|
|
||||||
currentDevices: currentDevices.map((row: any) => {
|
|
||||||
return {
|
|
||||||
value: row.deviceId,
|
|
||||||
label: row.deviceName
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
currentDevice: currentDevice.deviceId,
|
|
||||||
currentVolume,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const getRoomFile = async (): Promise<void> => {
|
const getRoomFile = async (): Promise<void> => {
|
||||||
await GetRoomFile({
|
await GetRoomFile({
|
||||||
pageIndex: fileList.pageIndex,
|
pageIndex: fileList.pageIndex,
|
||||||
|
|
@ -274,6 +256,33 @@ const Meeting: React.FC = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取房间用户
|
||||||
|
const getRoomUser = async (): Promise<void> => {
|
||||||
|
await GetRoomUser(state.channelId).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
setRoomUserList(res.data)
|
||||||
|
setTimeout(() => {
|
||||||
|
res.data.forEach((item: any) => {
|
||||||
|
agora.setVideo(Number(item.account), document.getElementById(`video-${item.account}`), state.channelId)
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleCustomStorageChange = (e: any): void => {
|
||||||
|
if (e.key === 'isJoin') {
|
||||||
|
if (e.value) {
|
||||||
|
onInvoke('joinChannel', {
|
||||||
|
roomNum: state.channelId
|
||||||
|
})
|
||||||
|
getRoomUser()
|
||||||
|
} else {
|
||||||
|
onInvoke('levelChannel', {
|
||||||
|
roomNum: state.channelId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.meeting}>
|
<div className={styles.meeting}>
|
||||||
|
|
@ -287,7 +296,7 @@ const Meeting: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
<div>00:13:45</div>
|
<div>00:13:45</div>
|
||||||
</div>
|
</div>
|
||||||
<div>会议号:2323235</div>
|
<div>会议号:{state.channelId}</div>
|
||||||
<div className='drag'>
|
<div className='drag'>
|
||||||
<div className={styles.meetingGrayButton}>演讲者模式</div>
|
<div className={styles.meetingGrayButton}>演讲者模式</div>
|
||||||
<Operation></Operation>
|
<Operation></Operation>
|
||||||
|
|
@ -313,11 +322,11 @@ const Meeting: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
onSlideChange={() => { }}
|
onSlideChange={() => { }}
|
||||||
>
|
>
|
||||||
{list.map((item, index) =>
|
{roomUserList.map((item: any, index: number) =>
|
||||||
<SwiperSlide key={item}>
|
<SwiperSlide key={index}>
|
||||||
<div className={styles.meetingContentSwiperCard}>
|
<div className={styles.meetingContentSwiperCard}>
|
||||||
<div className={styles.meetingContentSwiperCardVdeio} id={`video-${index}`}></div>
|
<div className={styles.meetingContentSwiperCardVdeio} id={`video-${item.account}`}></div>
|
||||||
{meetingContentUser()}
|
{meetingContentUser(item)}
|
||||||
</div>
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
)}
|
)}
|
||||||
|
|
@ -325,7 +334,7 @@ const Meeting: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles.meetingContentVideo} drag`}>
|
<div className={`${styles.meetingContentVideo} drag`}>
|
||||||
<div className={styles.meetingContentVideoDom}></div>
|
<div className={styles.meetingContentVideoDom}></div>
|
||||||
{meetingContentUser()}
|
{/* {meetingContentUser()} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
|
|
@ -463,114 +472,12 @@ const Meeting: React.FC = () => {
|
||||||
}}>共享电脑音频</Checkbox>
|
}}>共享电脑音频</Checkbox>
|
||||||
<div>
|
<div>
|
||||||
<Button type="primary" onClick={() => { setIsSharedScreenModal(false) }} style={{ backgroundColor: '#31353A', marginRight: '14px' }}>取消</Button>
|
<Button type="primary" onClick={() => { setIsSharedScreenModal(false) }} style={{ backgroundColor: '#31353A', marginRight: '14px' }}>取消</Button>
|
||||||
<Button type="primary" className='m-ant-btn' onClick={() => changeVdeio(false)}>共享</Button>
|
<Button type="primary" className='m-ant-btn' onClick={() => clickSharedScreen()}>共享</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal title="设置向导" open={isStupWizard} footer={null} closable={false} centered width={'40vw'}>
|
<StupWizard ref={stupWizardRef} />
|
||||||
<div className={styles.stupWizard}>
|
|
||||||
<div>
|
|
||||||
<div>{stepsStatus ? '音频设置向导' : '视频测试'}</div>
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<span>音频输出设备:</span>
|
|
||||||
<Select
|
|
||||||
options={audioDeviceManager.currentDevices} style={{ flexGrow: 1 }}
|
|
||||||
value={audioDeviceManager.currentDevice} onChange={(e) => {
|
|
||||||
setAudioDeviceManager({
|
|
||||||
...audioDeviceManager,
|
|
||||||
currentDevice: e
|
|
||||||
})
|
|
||||||
agora.setRecordingDevice(e);
|
|
||||||
getAudioMediaList()
|
|
||||||
}} />;
|
|
||||||
<audio src="" id='startAudio'></audio>
|
|
||||||
</div>
|
|
||||||
{stepsStatus ? <div>
|
|
||||||
<span>调节声音大小:</span>
|
|
||||||
<Slider min={0} max={255} value={audioDeviceManager.currentVolume} onChange={(e) => {
|
|
||||||
setAudioDeviceManager({
|
|
||||||
...audioDeviceManager,
|
|
||||||
currentVolume: e
|
|
||||||
})
|
|
||||||
agora.setRecordingDeviceVolume(e)
|
|
||||||
}} style={{ flexGrow: 1 }} />
|
|
||||||
</div> :
|
|
||||||
<div>
|
|
||||||
<span>视频预览:</span>
|
|
||||||
<video id='startPreview'
|
|
||||||
poster={ImageUrl.error}
|
|
||||||
style={{ width: '226px', height: '136px', backgroundColor: 'black' }}>
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{stepsStatus ? <div>
|
|
||||||
<span>您可以对着麦克风说话,试听表克风的输入质量</span>
|
|
||||||
<div>
|
|
||||||
<img src={ImageUrl.icon33} alt="" />
|
|
||||||
<div>
|
|
||||||
<img src={ImageUrl.icon34} alt="" />
|
|
||||||
<div id='recordingDeviceTest'>
|
|
||||||
<img src={ImageUrl.icon35} alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> : null}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{stepsStatus ? <div>
|
|
||||||
<Button type="primary" className='m-ant-btn' onClick={() => {
|
|
||||||
let audio = document.getElementById('startAudio') as any;
|
|
||||||
if (audio.srcObject) {
|
|
||||||
const tracks = audio.srcObject.getTracks();
|
|
||||||
tracks.forEach((track: any) => {
|
|
||||||
track.stop();
|
|
||||||
});
|
|
||||||
audio.srcObject = null;
|
|
||||||
}
|
|
||||||
setStepsStatus(false)
|
|
||||||
agora.startPreview().then((res: boolean) => {
|
|
||||||
setIsVideoLoad(res)
|
|
||||||
})
|
|
||||||
}}>下一步</Button>
|
|
||||||
</div> :
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
style={{ backgroundColor: '#31353A', marginRight: '14px' }}
|
|
||||||
onClick={() => {
|
|
||||||
if (isVideoLoad) {
|
|
||||||
setIsVideoLoad(false)
|
|
||||||
agora.stopAudioDeviceLoopbackTest()
|
|
||||||
setStepsStatus(true)
|
|
||||||
agora.startRecordingDeviceTest(200)
|
|
||||||
} else {
|
|
||||||
message.error('视频加载中!')
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>上一步</Button>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
className='m-ant-btn'
|
|
||||||
onClick={() => {
|
|
||||||
if (isVideoLoad) {
|
|
||||||
agora.stopAudioDeviceLoopbackTest()
|
|
||||||
agora.setRecordingDeviceVolume(audioDeviceManager.currentVolume)
|
|
||||||
setIsStupWizard(false)
|
|
||||||
setStepsStatus(true)
|
|
||||||
setIsVideoLoad(false)
|
|
||||||
} else {
|
|
||||||
message.error('视频加载中!')
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>完成
|
|
||||||
</Button>
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
<Modal
|
<Modal
|
||||||
title="共享文件"
|
title="共享文件"
|
||||||
open={isSharedFilesModel}
|
open={isSharedFilesModel}
|
||||||
|
|
@ -703,7 +610,11 @@ const Meeting: React.FC = () => {
|
||||||
<VerticalAlignBottomOutlined title='下载' style={{ color: '#5575F2', cursor: 'pointer' }} onClick={() => {
|
<VerticalAlignBottomOutlined title='下载' style={{ color: '#5575F2', cursor: 'pointer' }} onClick={() => {
|
||||||
GetRoomFileDwUrl(item.fileUrl, item.id).then(res => {
|
GetRoomFileDwUrl(item.fileUrl, item.id).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
window.electron.dwFile(res.data)
|
const downloadLink = document.createElement("a");
|
||||||
|
downloadLink.href = res.data;
|
||||||
|
downloadLink.download = item.fileName;
|
||||||
|
downloadLink.click();
|
||||||
|
getRoomFile()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}} />
|
}} />
|
||||||
|
|
@ -730,16 +641,16 @@ const Meeting: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const meetingContentUser = () => {
|
const meetingContentUser = (item: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.meetingContentUser}>
|
<div className={styles.meetingContentUser}>
|
||||||
<div className={styles.meetingContentUserRole}>
|
{item.roleId === '1' ? <div className={styles.meetingContentUserRole}>
|
||||||
<img src={ImageUrl.icon32} alt="" />
|
<img src={ImageUrl.icon32} alt="" />
|
||||||
</div>
|
</div> : null}
|
||||||
<div className={styles.meetingContentUserName}>
|
<div className={styles.meetingContentUserName}>
|
||||||
<img src={ImageUrl.icon22} alt="" />
|
<img src={ImageUrl.icon22} alt="" />
|
||||||
<span>张大龙</span>
|
<span>{item.userName}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -4,30 +4,9 @@ export interface IElectronAPI {
|
||||||
setViewStatus: (status: 'quit' | 'maximize' | 'minimize' | 'unmaximize') => void;
|
setViewStatus: (status: 'quit' | 'maximize' | 'minimize' | 'unmaximize') => void;
|
||||||
getIsMaximized: () => Promise<boolean>;
|
getIsMaximized: () => Promise<boolean>;
|
||||||
setWriteText: (text: string) => void;
|
setWriteText: (text: string) => void;
|
||||||
dwFile: (url: string) => void;
|
|
||||||
}
|
|
||||||
export interface Agora {
|
|
||||||
getDesktopCapturerVideo: () => Promise<void>;
|
|
||||||
setDesktopCapturerVideo: (data: any) => void;
|
|
||||||
setCameraCapture: (data: any) => void;
|
|
||||||
getAudioMediaList: () => { currentDevice: any, currentDevices: any, currentVolume: number };
|
|
||||||
setRecordingDeviceVolume: (volume: number) => void;
|
|
||||||
setRecordingDevice: (deviceId: string) => void;
|
|
||||||
setJoinChannel: (data: { channelId: string, userid: string, token: string }) => Promise<void>;
|
|
||||||
getVideoId: () => string;
|
|
||||||
startRecordingDeviceTest: (indicationInterval: number) => void;
|
|
||||||
stopAudioDeviceLoopbackTest: () => void;
|
|
||||||
startPreview: () => Promise<boolean>;
|
|
||||||
startRecording: () => void;
|
|
||||||
stopRecording: () => void;
|
|
||||||
leaveChannel: () => void;
|
|
||||||
stopScreenCapture: () => void;
|
|
||||||
muteLocalAudioStream: (mute: boolean) => void;
|
|
||||||
muteLocalVideoStream: (mute: boolean) => void;
|
|
||||||
}
|
}
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
electron: IElectronAPI;
|
electron: IElectronAPI;
|
||||||
agora: Agora
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import storage from "./storage";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
createAgoraRtcEngine,
|
createAgoraRtcEngine,
|
||||||
ClientRoleType,
|
ClientRoleType,
|
||||||
|
|
@ -10,89 +12,105 @@ const {
|
||||||
MediaRecorderStreamType
|
MediaRecorderStreamType
|
||||||
} = require("agora-electron-sdk");
|
} = require("agora-electron-sdk");
|
||||||
const { message } = require('antd');
|
const { message } = require('antd');
|
||||||
const rtcEngine = createAgoraRtcEngine();
|
|
||||||
const option: any = {
|
const option: any = {
|
||||||
appId: 'dcfc466a6ecb4a1f972630065dfb1e75',
|
appId: 'dcfc466a6ecb4a1f972630065dfb1e75',
|
||||||
token: '',
|
token: '',
|
||||||
channelId: '',
|
channelId: '',
|
||||||
userid: '',
|
userid: '',
|
||||||
}
|
}
|
||||||
rtcEngine.initialize({
|
|
||||||
appId: option.appId,
|
|
||||||
});
|
|
||||||
|
|
||||||
rtcEngine.registerEventHandler({
|
|
||||||
// 监听本地用户加入频道事件
|
|
||||||
onJoinChannelSuccess: ({ channelId, localUid }: any, elapsed: any) => {
|
|
||||||
console.log({ channelId, localUid }, elapsed, '加入房间');
|
|
||||||
// 本地用户加入频道后,设置本地视频窗口
|
|
||||||
rtcEngine.setupLocalVideo({
|
|
||||||
renderMode: RenderModeType.RenderModeFit,
|
|
||||||
// sourceType: VideoSourceType.VideoSourceScreen,
|
|
||||||
sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
|
||||||
uid: localUid,
|
|
||||||
view: agora.getDom(),
|
|
||||||
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 监听远端用户加入频道事件
|
|
||||||
onUserJoined: ({ channelId, localUid }: any, remoteUid: any, elapsed: any) => {
|
|
||||||
console.log({ channelId, localUid }, remoteUid, '远端加入频道');
|
|
||||||
// 远端用户加入频道后,设置远端视频窗口
|
|
||||||
rtcEngine.setupRemoteVideo(
|
|
||||||
{
|
|
||||||
renderMode: RenderModeType.RenderModeFit,
|
|
||||||
sourceType: VideoSourceType.VideoSourceRemote,
|
|
||||||
uid: remoteUid,
|
|
||||||
view: agora.getDom(),
|
|
||||||
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
|
||||||
},
|
|
||||||
{ channelId },
|
|
||||||
);
|
|
||||||
|
|
||||||
},
|
|
||||||
// 监听用户离开频道事件
|
|
||||||
onUserOffline: ({ channelId, localUid }: any, remoteUid: any, reason: any) => {
|
|
||||||
// 远端用户离开频道后,关闭远端视频窗口
|
|
||||||
console.log({ channelId, localUid }, remoteUid, '离开频道');
|
|
||||||
rtcEngine.setupRemoteVideo(
|
|
||||||
{
|
|
||||||
renderMode: RenderModeType.RenderModeFit,
|
|
||||||
sourceType: VideoSourceType.VideoSourceRemote,
|
|
||||||
uid: remoteUid,
|
|
||||||
view: agora.getDom(),
|
|
||||||
setupMode: VideoViewSetupMode.VideoViewSetupRemove,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
// 视频发布状态改变回调
|
|
||||||
onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
|
||||||
if (newState === 1) {
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 音频发布状态改变回调
|
|
||||||
onAudioPublishStateChanged: (channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
|
||||||
if (newState === 1) {
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 用户音量提示回调。
|
|
||||||
onAudioVolumeIndication: (connection: any, speakers: any, speakerNumber: any, totalVolume: any,) => {
|
|
||||||
const percentage = (totalVolume / 255) * 100
|
|
||||||
const dom = document.getElementById('recordingDeviceTest') as any;
|
|
||||||
if (dom) {
|
|
||||||
dom.style.width = `${percentage}%`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let videoID: string = '';
|
|
||||||
let iMediaRecorder: any = '';
|
let iMediaRecorder: any = '';
|
||||||
|
let rtcEngine: any = '';
|
||||||
|
|
||||||
const agora = {
|
const agora = {
|
||||||
getDom: () => {
|
// 初始化
|
||||||
return document.getElementById('video-1');
|
init: () => {
|
||||||
|
rtcEngine = createAgoraRtcEngine();
|
||||||
|
rtcEngine.initialize({
|
||||||
|
appId: option.appId,
|
||||||
|
});
|
||||||
|
rtcEngine.registerEventHandler({
|
||||||
|
// 监听本地用户加入频道事件
|
||||||
|
onJoinChannelSuccess: (info: any, elapsed: any) => {
|
||||||
|
storage.setItem('isJoin', true)
|
||||||
|
},
|
||||||
|
// 监听远端用户加入频道事件
|
||||||
|
onUserJoined: (info: any, remoteUid: any, elapsed: any) => {
|
||||||
|
console.log(info, remoteUid, '远端加入频道');
|
||||||
|
// 远端用户加入频道后,设置远端视频窗口
|
||||||
|
rtcEngine.setupRemoteVideo(
|
||||||
|
{
|
||||||
|
renderMode: RenderModeType.RenderModeFit,
|
||||||
|
sourceType: VideoSourceType.VideoSourceRemote,
|
||||||
|
uid: remoteUid,
|
||||||
|
view: '',
|
||||||
|
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
||||||
|
},
|
||||||
|
{ channelId: info.channelId },
|
||||||
|
);
|
||||||
|
|
||||||
|
},
|
||||||
|
// 监听用户离开频道事件
|
||||||
|
onUserOffline: ({ channelId, localUid }: any, remoteUid: any, reason: any) => {
|
||||||
|
// 远端用户离开频道后,关闭远端视频窗口
|
||||||
|
console.log({ channelId, localUid }, remoteUid, '离开频道');
|
||||||
|
rtcEngine.setupRemoteVideo(
|
||||||
|
{
|
||||||
|
renderMode: RenderModeType.RenderModeFit,
|
||||||
|
sourceType: VideoSourceType.VideoSourceRemote,
|
||||||
|
uid: remoteUid,
|
||||||
|
view: '',
|
||||||
|
setupMode: VideoViewSetupMode.VideoViewSetupRemove,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// 视频发布状态改变回调
|
||||||
|
onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
||||||
|
if (newState === 1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 音频发布状态改变回调
|
||||||
|
onAudioPublishStateChanged: (channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
||||||
|
if (newState === 1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 用户音量提示回调。
|
||||||
|
onAudioVolumeIndication: (connection: any, speakers: any, speakerNumber: any, totalVolume: any,) => {
|
||||||
|
const percentage = (totalVolume / 255) * 100
|
||||||
|
const dom = document.getElementById('recordingDeviceTest') as any;
|
||||||
|
if (dom) {
|
||||||
|
dom.style.width = `${percentage}%`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 渲染视频
|
||||||
|
setVideo: (localUid: number, view: any, channelId: string) => {
|
||||||
|
console.log(view, localUid, channelId);
|
||||||
|
if (option.userid === localUid) {
|
||||||
|
rtcEngine.setupLocalVideo({
|
||||||
|
renderMode: RenderModeType.RenderModeFit,
|
||||||
|
// sourceType: VideoSourceType.VideoSourceScreen,
|
||||||
|
sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
||||||
|
uid: localUid,
|
||||||
|
view,
|
||||||
|
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
rtcEngine.setupRemoteVideo(
|
||||||
|
{
|
||||||
|
renderMode: RenderModeType.RenderModeFit,
|
||||||
|
sourceType: VideoSourceType.VideoSourceRemote,
|
||||||
|
uid: localUid,
|
||||||
|
view,
|
||||||
|
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
||||||
|
},
|
||||||
|
{ channelId },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
// 离开频道
|
// 离开频道
|
||||||
leaveChannel: () => {
|
leaveChannel: () => {
|
||||||
|
|
@ -101,6 +119,8 @@ const agora = {
|
||||||
stopAllEffect: true,
|
stopAllEffect: true,
|
||||||
stopMicrophoneRecording: true,
|
stopMicrophoneRecording: true,
|
||||||
})
|
})
|
||||||
|
rtcEngine.release()
|
||||||
|
storage.setItem('isJoin', false)
|
||||||
},
|
},
|
||||||
// 加入频道
|
// 加入频道
|
||||||
joinChannel: (bool: boolean) => {
|
joinChannel: (bool: boolean) => {
|
||||||
|
|
@ -211,11 +231,19 @@ const agora = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 获取音频设备列表
|
// 获取音频设备列表
|
||||||
getAudioMediaList: () => {
|
getAudioMediaList: (bool: boolean) => {
|
||||||
return {
|
if (bool) {
|
||||||
currentDevice: rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice(),
|
return {
|
||||||
currentDevices: rtcEngine.getAudioDeviceManager().enumerateRecordingDevices(),
|
currentDevices: rtcEngine.getAudioDeviceManager().enumeratePlaybackDevices(),
|
||||||
currentVolume: rtcEngine.getAudioDeviceManager().getRecordingDeviceVolume()
|
currentDevice: rtcEngine.getAudioDeviceManager().getPlaybackDefaultDevice(),
|
||||||
|
currentVolume: 100,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
currentDevices: rtcEngine.getAudioDeviceManager().enumerateRecordingDevices(),
|
||||||
|
currentDevice: rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice(),
|
||||||
|
currentVolume: rtcEngine.getAudioDeviceManager().getRecordingDeviceVolume()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 设置音频设备音量
|
// 设置音频设备音量
|
||||||
|
|
@ -226,10 +254,26 @@ const agora = {
|
||||||
setRecordingDevice: (deviceId: string) => {
|
setRecordingDevice: (deviceId: string) => {
|
||||||
rtcEngine.getAudioDeviceManager().setRecordingDevice(deviceId)
|
rtcEngine.getAudioDeviceManager().setRecordingDevice(deviceId)
|
||||||
},
|
},
|
||||||
|
// 启动音频播放设备测试。
|
||||||
|
startPlaybackDeviceTest: () => {
|
||||||
|
rtcEngine.getAudioDeviceManager().startPlaybackDeviceTest('https://wgshare.oss-cn-chengdu.aliyuncs.com/TestAudio.mp3')
|
||||||
|
},
|
||||||
|
// 停止音频播放设备测试。
|
||||||
|
stopPlaybackDeviceTest: () => {
|
||||||
|
rtcEngine.getAudioDeviceManager().stopPlaybackDeviceTest()
|
||||||
|
},
|
||||||
|
// 设置播放设备音量
|
||||||
|
setPlaybackDeviceVolume: (volume: number) => {
|
||||||
|
rtcEngine.getAudioDeviceManager().setPlaybackDeviceVolume(volume)
|
||||||
|
},
|
||||||
|
// 指定播放设备
|
||||||
|
setPlaybackDevice: (deviceId: string) => {
|
||||||
|
rtcEngine.getAudioDeviceManager().setPlaybackDevice(deviceId)
|
||||||
|
},
|
||||||
// 摄像头采集
|
// 摄像头采集
|
||||||
setCameraCapture: () => {
|
setCameraCapture: () => {
|
||||||
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
||||||
// joinChannel(false)
|
agora.joinChannel(false)
|
||||||
},
|
},
|
||||||
// 加入频道
|
// 加入频道
|
||||||
setJoinChannel: (data: any) => {
|
setJoinChannel: (data: any) => {
|
||||||
|
|
@ -237,7 +281,7 @@ const agora = {
|
||||||
option.channelId = data.channelId;
|
option.channelId = data.channelId;
|
||||||
option.userid = Number(data.userid);
|
option.userid = Number(data.userid);
|
||||||
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
||||||
// joinChannel(false)
|
agora.joinChannel(false)
|
||||||
},
|
},
|
||||||
// 取消或恢复发布本地音频流
|
// 取消或恢复发布本地音频流
|
||||||
muteLocalAudioStream: (mute: any) => {
|
muteLocalAudioStream: (mute: any) => {
|
||||||
|
|
@ -247,18 +291,13 @@ const agora = {
|
||||||
muteLocalVideoStream: (mute: any) => {
|
muteLocalVideoStream: (mute: any) => {
|
||||||
rtcEngine.muteLocalVideoStream(mute)
|
rtcEngine.muteLocalVideoStream(mute)
|
||||||
},
|
},
|
||||||
// 获取当前生成的视频id
|
|
||||||
getVideoId: () => {
|
|
||||||
return videoID;
|
|
||||||
},
|
|
||||||
// 桌面捕获音频和视频的媒体源的信息
|
// 桌面捕获音频和视频的媒体源的信息
|
||||||
getDesktopCapturerVideo: async () => {
|
getDesktopCapturerVideo: async () => {
|
||||||
return rtcEngine.getScreenCaptureSources({ width: 300, height: 300 }, { width: 300, height: 300 }, true);
|
return rtcEngine.getScreenCaptureSources({ width: 300, height: 300 }, { width: 300, height: 300 }, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 共享屏幕采集
|
// 共享屏幕采集
|
||||||
setDesktopCapturerVideo: (targetSource: any) => {
|
setDesktopCapturerVideo: (targetSource: any) => {
|
||||||
// stopScreenCapture()
|
agora.stopScreenCapture()
|
||||||
if (
|
if (
|
||||||
targetSource.type ===
|
targetSource.type ===
|
||||||
ScreenCaptureSourceType.ScreencapturesourcetypeScreen
|
ScreenCaptureSourceType.ScreencapturesourcetypeScreen
|
||||||
|
|
@ -283,7 +322,7 @@ const agora = {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// joinChannel(true)
|
agora.joinChannel(true)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import icon32 from '@/assets/icon32.png'
|
||||||
import icon33 from '@/assets/icon33.png'
|
import icon33 from '@/assets/icon33.png'
|
||||||
import icon34 from '@/assets/icon34.png'
|
import icon34 from '@/assets/icon34.png'
|
||||||
import icon35 from '@/assets/icon35.png'
|
import icon35 from '@/assets/icon35.png'
|
||||||
|
import icon36 from '@/assets/icon36.png'
|
||||||
export default {
|
export default {
|
||||||
avatar,
|
avatar,
|
||||||
error,
|
error,
|
||||||
|
|
@ -89,4 +90,5 @@ export default {
|
||||||
icon33,
|
icon33,
|
||||||
icon34,
|
icon34,
|
||||||
icon35,
|
icon35,
|
||||||
|
icon36,
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,12 @@ export const onSignalr = (callBack: Function) => {
|
||||||
callBack(message)
|
callBack(message)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export const onInvoke = (message: string) => {
|
export const onInvoke = (str: string, data: any) => {
|
||||||
connection.invoke("GetUserId", message)
|
switch (str) {
|
||||||
|
case 'joinChannel':
|
||||||
|
case 'levelChannel':
|
||||||
|
connection.invoke(str, data.roomNum)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue