设置向导

This commit is contained in:
yj 2024-07-05 11:25:22 +08:00
parent 130064b8ba
commit 375fb2a022
20 changed files with 533 additions and 799 deletions

View File

@ -1,5 +1,5 @@
#基础API 绝对的 #基础API 绝对的
VITE_BASE_URL_API = 'http://192.168.2.9:6500' VITE_BASE_URL_API = 'http://192.168.2.8:5192'
VITE_BASE_URL_DRAW_API = 'http://192.168.2.9:6555' VITE_BASE_URL_DRAW_API = 'http://192.168.2.9:6555'
#当前IP 相对的 #当前IP 相对的
VITE_BASE_CURRENT_API = '.' VITE_BASE_CURRENT_API = '.'

View File

@ -1,5 +1,5 @@
#基础API 绝对的 #基础API 绝对的
VITE_BASE_URL_API = 'http://192.168.2.9:6500' VITE_BASE_URL_API = 'http://192.168.2.8:5192'
VITE_BASE_URL_DRAW_API = 'http://192.168.2.9:6555' VITE_BASE_URL_DRAW_API = 'http://192.168.2.9:6555'
#当前IP 相对的 #当前IP 相对的
VITE_BASE_CURRENT_API = '.' VITE_BASE_CURRENT_API = '.'

View File

@ -1,5 +1,5 @@
#基础API 绝对的 #基础API 绝对的
VITE_BASE_URL_API = 'http://192.168.2.9:6500' VITE_BASE_URL_API = 'http://192.168.2.8:5192'
VITE_BASE_URL_DRAW_API = 'http://192.168.2.9:6555' VITE_BASE_URL_DRAW_API = 'http://192.168.2.9:6555'
#当前IP 相对的 #当前IP 相对的
VITE_BASE_CURRENT_API = '.' VITE_BASE_CURRENT_API = '.'

2
.npmrc Normal file
View File

@ -0,0 +1,2 @@
agora_electron_sdk_arch=ia32
arch=ia32

786
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,9 @@
"make:prod": "vite build --mode production & electron-forge make" "make:prod": "vite build --mode production & electron-forge make"
}, },
"agora_electron": { "agora_electron": {
"prebuilt": true "platform": "win32",
"prebuilt": true,
"arch": "ia32"
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.3.7", "@ant-design/icons": "^5.3.7",
@ -53,7 +55,7 @@
"@vitejs/plugin-react": "^1.0.7", "@vitejs/plugin-react": "^1.0.7",
"concurrently": "^7.6.0", "concurrently": "^7.6.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"electron": "^17.4.11", "electron": "^31.1.0",
"typescript": "^4.5.4", "typescript": "^4.5.4",
"vite": "^2.8.0" "vite": "^2.8.0"
}, },

View File

@ -7,8 +7,10 @@ const {
VideoViewSetupMode, VideoViewSetupMode,
ScreenCaptureSourceType, ScreenCaptureSourceType,
RenderModeType, RenderModeType,
ChannelProfileType
} = require("agora-electron-sdk"); } = require("agora-electron-sdk");
const agoraAonfig = require('./src/utils/package/agoraConfig') const agoraAonfig = require('./src/utils/package/agoraConfig');
const { message } = require('antd');
const rtcEngine = createAgoraRtcEngine(); const rtcEngine = createAgoraRtcEngine();
rtcEngine.initialize({ rtcEngine.initialize({
appId: agoraAonfig.appid, appId: agoraAonfig.appid,
@ -22,28 +24,26 @@ const getDom = () => {
const EventHandles = { const EventHandles = {
// 监听本地用户加入频道事件 // 监听本地用户加入频道事件
onJoinChannelSuccess: ({ channelId, localUid }, elapsed) => { onJoinChannelSuccess: ({ channelId, localUid }, elapsed) => {
const dom = document.getElementById('video1') console.log({ channelId, localUid });
// 本地用户加入频道后,设置本地视频窗口 // 本地用户加入频道后,设置本地视频窗口
rtcEngine.setupLocalVideo({ rtcEngine.setupLocalVideo({
renderMode: RenderModeType.RenderModeFit, renderMode: RenderModeType.RenderModeFit,
sourceType: VideoSourceType.VideoSourceScreen, sourceType: VideoSourceType.VideoSourceScreen,
// sourceType: VideoSourceType.VideoSourceCameraPrimary,
uid: localUid, uid: localUid,
view: dom, view: getDom(),
// view: getDom(),
setupMode: VideoViewSetupMode.VideoViewSetupAdd, setupMode: VideoViewSetupMode.VideoViewSetupAdd,
}); });
}, },
// 监听远端用户加入频道事件 // 监听远端用户加入频道事件
onUserJoined: ({ channelId, localUid }, remoteUid, elapsed) => { onUserJoined: ({ channelId, localUid }, remoteUid, elapsed) => {
console.log('远端用户 ' + remoteUid + ' 已加入');
const dom = document.getElementById('video2')
// 远端用户加入频道后,设置远端视频窗口 // 远端用户加入频道后,设置远端视频窗口
rtcEngine.setupRemoteVideo( rtcEngine.setupRemoteVideo(
{ {
renderMode: RenderModeType.RenderModeFit, renderMode: RenderModeType.RenderModeFit,
sourceType: VideoSourceType.VideoSourceRemote, sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid, uid: remoteUid,
view: dom, view: getDom(),
setupMode: VideoViewSetupMode.VideoViewSetupAdd, setupMode: VideoViewSetupMode.VideoViewSetupAdd,
}, },
{ channelId }, { channelId },
@ -51,24 +51,28 @@ const EventHandles = {
}, },
// 监听用户离开频道事件 // 监听用户离开频道事件
onUserOffline: (info, remoteUid, reason) => { onUserOffline: ({ channelId, localUid }, remoteUid, reason) => {
console.log('远端用户 ' + remoteUid + ' 已离开频道');
// 远端用户离开频道后,关闭远端视频窗口 // 远端用户离开频道后,关闭远端视频窗口
const dom = document.getElementById('video2')
rtcEngine.setupRemoteVideo( rtcEngine.setupRemoteVideo(
{ {
renderMode: RenderModeType.RenderModeFit, renderMode: RenderModeType.RenderModeFit,
sourceType: VideoSourceType.VideoSourceRemote, sourceType: VideoSourceType.VideoSourceRemote,
uid: remoteUid, uid: remoteUid,
view: dom, view: getDom(),
setupMode: VideoViewSetupMode.VideoViewSetupRemove, setupMode: VideoViewSetupMode.VideoViewSetupRemove,
}, },
); );
}, },
// 用户音量提示回调。
onAudioVolumeIndication: (connection, speakers, speakerNumber, totalVolume) => {
const percentage = (totalVolume / 255) * 100
if (document.getElementById('recordingDeviceTest')) {
document.getElementById('recordingDeviceTest').style.width = `${percentage}%`
}
}
}; };
rtcEngine.registerEventHandler(EventHandles); rtcEngine.registerEventHandler(EventHandles);
contextBridge.exposeInMainWorld( contextBridge.exposeInMainWorld(
'electron', 'electron',
{ {
@ -77,7 +81,7 @@ contextBridge.exposeInMainWorld(
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) => { setDesktopCapturerVideo: (targetSource) => {
rtcEngine.stopScreenCapture() rtcEngine.stopScreenCapture()
if ( if (
@ -105,7 +109,10 @@ contextBridge.exposeInMainWorld(
); );
} }
videoID = `vidoe-${123}-${agoraAonfig.channelId}`; videoID = `vidoe-${123}-${agoraAonfig.channelId}`;
rtcEngine.joinChannel(agoraAonfig.token, agoraAonfig.channelId, 123, { rtcEngine.joinChannelEx(agoraAonfig.token, {
channelId: agoraAonfig.channelId,
localUid: 123,
}, {
autoSubscribeAudio: true, //设置是否自动订阅所有音频流 autoSubscribeAudio: true, //设置是否自动订阅所有音频流
autoSubscribeVideo: true, //设置是否自动订阅所有视频流 autoSubscribeVideo: true, //设置是否自动订阅所有视频流
publishMicrophoneTrack: false, //设置是否发布麦克风采集到的音频 publishMicrophoneTrack: false, //设置是否发布麦克风采集到的音频
@ -114,6 +121,23 @@ contextBridge.exposeInMainWorld(
publishScreenTrack: true, //设置是否发布屏幕采集的视频 publishScreenTrack: true, //设置是否发布屏幕采集的视频
}); });
}, },
// 摄像头采集
setCameraCapture: () => {
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
videoID = `vidoe-${123}-${agoraAonfig.channelId}`;
rtcEngine.joinChannelEx(agoraAonfig.token, {
channelId: agoraAonfig.channelId,
localUid: 123,
}, {
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting, //设置频道场景为直播场景
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //设置用户角色为主播;如果要将用户角色设置为观众,保持默认值即可
publishMicrophoneTrack: true, //发布麦克风采集的音频
publishCameraTrack: true, //发布摄像头采集的视频
autoSubscribeAudio: true, //自动订阅所有音频流
autoSubscribeVideo: true, //自动订阅所有视频流
publishScreenTrack: false, //设置是否发布屏幕采集的视频
});
},
// 加入频道 // 加入频道
setJoinChannel: () => { setJoinChannel: () => {
videoID = `vidoe-${234}-${agoraAonfig.channelId}`; videoID = `vidoe-${234}-${agoraAonfig.channelId}`;
@ -133,18 +157,73 @@ contextBridge.exposeInMainWorld(
getVideoId: () => { getVideoId: () => {
return videoID; return videoID;
}, },
// 获取摄像头以及音频内容 // 获取音频设备列表
getCameraAndMicrophoneMedia: async () => { getAudioMediaList: () => {
try { return {
const stream = await navigator.mediaDevices.getUserMedia({ currentDevice: rtcEngine.getAudioDeviceManager().getRecordingDefaultDevice(),
currentDevices: rtcEngine.getAudioDeviceManager().enumerateRecordingDevices(),
currentVolume: rtcEngine.getAudioDeviceManager().getRecordingDeviceVolume()
}
},
// 设置音频设备音量
setRecordingDeviceVolume: (volume) => {
rtcEngine.getAudioDeviceManager().setRecordingDeviceVolume(volume)
},
// 设置音频采集设备
setRecordingDevice: (deviceId) => {
rtcEngine.getAudioDeviceManager().setRecordingDevice(deviceId)
},
// 启动音频采集设备测试
startRecordingDeviceTest: (indicationInterval) => {
rtcEngine.getAudioDeviceManager().startRecordingDeviceTest(indicationInterval)
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
let dom = document.getElementById('startAudio');
dom.srcObject = stream;
dom.play()
})
.catch((error) => {
message.error('无法获取麦克风!');
});
},
// 停止音频设备回路测试
stopAudioDeviceLoopbackTest: () => {
rtcEngine.getAudioDeviceManager().stopAudioDeviceLoopbackTest()
rtcEngine.getAudioDeviceManager().stopRecordingDeviceTest()
let video = document.getElementById('startPreview');
if (video.srcObject) {
const tracks = video.srcObject.getTracks();
tracks.forEach((track) => {
track.stop();
});
video.srcObject = null;
}
let audio = document.getElementById('startAudio');
if (audio.srcObject) {
const tracks = audio.srcObject.getTracks();
tracks.forEach((track) => {
track.stop();
});
audio.srcObject = null;
}
},
// 开启本地视频预览
startPreview: async () => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.getUserMedia({
video: true, video: true,
audio: true, audio: true,
}).then((stream) => {
let dom = document.getElementById('startPreview');
dom.srcObject = stream;
dom.play()
resolve(true)
}).catch((error) => {
message.error('无法获取摄像头!');
resolve(true)
}); });
stream.getTracks().forEach(track => track.stop()); })
return stream
} catch (error) {
return false;
}
}, },
// 设置窗口大小 // 设置窗口大小
setMainWindowSize: (config) => { setMainWindowSize: (config) => {

View File

@ -1,7 +1,7 @@
import { request } from '@/utils' import { request } from '@/utils'
export const GetViewSize = (data: any) => export const GetCheckUser = (userName: string) =>
request({ request({
url: `/draw/position?X=${data.X}&Y=${data.Y}&Width=${data.Width}&Height=${data.Height}&ImageUrl=${data.ImageUrl}&ImageWidth=${data.ImageWidth}&ImageHeight=${data.ImageHeight}`, url: `/auth/check-user?userName=${userName}`,
method: 'get' method: 'get'
}) })

BIN
src/assets/icon33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

BIN
src/assets/icon34.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/assets/icon35.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -4,6 +4,8 @@ import { useEffect, useState } from "react";
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Input, Button, Checkbox } from "antd" import { Input, Button, Checkbox } from "antd"
import { storage } from '@/utils' import { storage } from '@/utils'
import { GetCheckUser } from '@/api/Login'
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);
@ -124,6 +126,9 @@ const Login: React.FC = () => {
...operation, ...operation,
account: e.target.value account: e.target.value
}) })
// GetCheckUser(e.target.value).then(res => {
// console.log(res);
// })
}} }}
className={`${styles.loginInputIcon} drag`} className={`${styles.loginInputIcon} drag`}
style={{ marginBottom: '12px' }} style={{ marginBottom: '12px' }}
@ -176,12 +181,12 @@ const Login: React.FC = () => {
<span>or</span> <span>or</span>
<div></div> <div></div>
</div> </div>
<div className={`${styles.code} drag`}> {/* <div className={`${styles.code} drag`}>
<div> <div>
<Input placeholder="输入会议号" className={`${styles.loginInput}`} /> <Input placeholder="输入会议号" className={`${styles.loginInput}`} />
</div> </div>
<div><img src="/src/assets/icon3.png" alt="" /></div> <div><img src="/src/assets/icon3.png" alt="" /></div>
</div> </div> */}
</div> </div>
</div> </div>
</div> </div>

View File

@ -128,10 +128,9 @@
width: 1378px; width: 1378px;
margin: 0 auto; margin: 0 auto;
height: 0px; height: 0px;
display: flex;
.meetingContentVideoDom { .meetingContentVideoDom {
border: 1px red solid; width: 100%;
width: 50%;
height: 100%; height: 100%;
background: black url('/src/assets/error.png') no-repeat center/30%; background: black url('/src/assets/error.png') no-repeat center/30%;
} }
@ -507,6 +506,7 @@
} }
} }
// 共享屏幕
.sharedScreenModal { .sharedScreenModal {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -514,10 +514,10 @@
>div:nth-child(1) { >div:nth-child(1) {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
max-height: 50vh;
overflow-y: auto;
align-content: flex-start; align-content: flex-start;
padding: 50px 0 0; padding: 50px 0 0;
max-height: 40vh;
overflow-y: auto;
>div { >div {
display: flex; display: flex;
@ -577,3 +577,89 @@
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;
}
}

View File

@ -6,7 +6,7 @@ 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 } from "antd"; import { Button, Input, Popover, Modal, Checkbox, message, Select, Slider } from "antd";
import { SearchOutlined } from '@ant-design/icons'; import { SearchOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { thumbImageBufferToBase64 } from '@/utils/package/base64' import { thumbImageBufferToBase64 } from '@/utils/package/base64'
@ -17,6 +17,7 @@ const Meeting: React.FC = () => {
userChatList: false, userChatList: false,
}) })
const [isSharedScreenModal, setIsSharedScreenModal] = useState(false); const [isSharedScreenModal, setIsSharedScreenModal] = useState(false);
const [isStupWizard, setIsStupWizard] = useState(false);
const [sharedScreenList, setSharedScreenList] = useState<any>([]); const [sharedScreenList, setSharedScreenList] = useState<any>([]);
const [sharedScreenItem, setSharedScreenItem] = useState<any>(''); const [sharedScreenItem, setSharedScreenItem] = useState<any>('');
const [footerList] = useState([ const [footerList] = useState([
@ -77,6 +78,13 @@ const Meeting: React.FC = () => {
}, },
], ],
]) ])
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
currentDevices: [],
currentDevice: {},
currentVolume: 0,
});
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('') const [videoID, setVideoID] = useState('')
@ -107,7 +115,10 @@ const Meeting: React.FC = () => {
window.electron.setJoinChannel() window.electron.setJoinChannel()
setVideoID(window.electron.getVideoId()) setVideoID(window.electron.getVideoId())
break; break;
default: case '设置向导':
getAudioMediaList()
window.electron.startRecordingDeviceTest(200)
setIsStupWizard(true)
break; break;
} }
} }
@ -126,6 +137,7 @@ const Meeting: React.FC = () => {
} }
} }
} }
const getDesktopCapturerVideo = (): void => { const getDesktopCapturerVideo = (): void => {
window.electron.getDesktopCapturerVideo().then((res: any) => { window.electron.getDesktopCapturerVideo().then((res: any) => {
if (sharedScreenList.length !== res.length) { if (sharedScreenList.length !== res.length) {
@ -141,6 +153,21 @@ const Meeting: React.FC = () => {
} }
}) })
}; };
const getAudioMediaList = (): void => {
const { currentDevices, currentDevice, currentVolume } = window.electron.getAudioMediaList();
setAudioDeviceManager({
currentDevices: currentDevices.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
currentDevice: currentDevice.deviceId,
currentVolume,
})
}
return ( return (
<> <>
<div className={styles.meeting}> <div className={styles.meeting}>
@ -183,8 +210,8 @@ const Meeting: React.FC = () => {
{list.map((item) => {list.map((item) =>
<SwiperSlide key={item}> <SwiperSlide key={item}>
<div className={styles.meetingContentSwiperCard}> <div className={styles.meetingContentSwiperCard}>
<video src="" className={styles.meetingContentSwiperCardVdeio} ></video> <div className={styles.meetingContentSwiperCardVdeio}></div>
<div style={{ color: 'white', position: 'absolute', left: 0, top: 0 }}>{item}</div> {/* <div style={{ color: 'white', position: 'absolute', left: 0, top: 0 }}>{item}</div> */}
{meetingContentUser()} {meetingContentUser()}
</div> </div>
</SwiperSlide> </SwiperSlide>
@ -192,10 +219,8 @@ const Meeting: React.FC = () => {
</Swiper> </Swiper>
</div> </div>
<div className={`${styles.meetingContentVideo} drag`}> <div className={`${styles.meetingContentVideo} drag`}>
<div className={styles.meetingContentVideoDom} id='video1'></div> <div className={styles.meetingContentVideoDom} id={videoID}></div>
<div className={styles.meetingContentVideoDom} id='video2'></div> {meetingContentUser()}
{/* <div className={styles.meetingContentVideoDom} id={videoID}></div> */}
{/* {meetingContentUser()} */}
</div> </div>
</div> </div>
{ {
@ -332,6 +357,109 @@ const Meeting: React.FC = () => {
</div> </div>
</div> </div>
</Modal> </Modal>
<Modal title="设置向导" open={isStupWizard} footer={null} closable={false} centered width={'40vw'}>
<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
})
window.electron.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
})
window.electron.setRecordingDeviceVolume(e)
}} style={{ flexGrow: 1 }} />
</div> :
<div>
<span></span>
<video id='startPreview'
poster={'/src/assets/error.png'}
style={{ width: '226px', height: '136px', backgroundColor: 'black' }}>
</video>
</div>
}
</div>
{stepsStatus ? <div>
<span></span>
<div>
<img src="/src/assets/icon33.png" alt="" />
<div>
<img src="/src/assets/icon34.png" alt="" />
<div id='recordingDeviceTest'>
<img src="/src/assets/icon35.png" 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)
window.electron.startPreview().then((res: boolean) => {
setIsVideoLoad(res)
})
}}></Button>
</div> :
<div>
<Button
type="primary"
style={{ backgroundColor: '#31353A', marginRight: '14px' }}
onClick={() => {
if (isVideoLoad) {
setIsVideoLoad(false)
window.electron.stopAudioDeviceLoopbackTest()
setStepsStatus(true)
window.electron.startRecordingDeviceTest(200)
} else {
message.error('视频加载中!')
}
}}
></Button>
<Button
type="primary"
className='m-ant-btn'
onClick={() => {
if (isVideoLoad) {
window.electron.stopAudioDeviceLoopbackTest()
window.electron.setRecordingDeviceVolume(audioDeviceManager.currentVolume)
setIsStupWizard(false)
setStepsStatus(true)
setIsVideoLoad(false)
} else {
message.error('视频加载中!')
}
}}
>
</Button>
</div>}
</div>
</div>
</Modal>
</> </>
) )
} }

10
src/render.d.ts vendored
View File

@ -1,13 +1,19 @@
// electron-env.d.ts // electron-env.d.ts
export interface IElectronAPI { export interface IElectronAPI {
getDesktopCapturerVideo: () => Promise<void>; getDesktopCapturerVideo: () => Promise<void>;
setDesktopCapturerVideo: (data: any) => Promise<void>; setDesktopCapturerVideo: (data: any) => void;
getCameraAndMicrophoneMedia: () => Promise<void>; setCameraCapture: (data: any) => void;
getAudioMediaList: () => { currentDevice: any, currentDevices: any, currentVolume: number };
setRecordingDeviceVolume: (volume: number) => void;
setRecordingDevice: (deviceId: string) => void;
setMainWindowSize: (config: any) => void; setMainWindowSize: (config: any) => void;
getIsMaximized: () => Promise<boolean>; getIsMaximized: () => Promise<boolean>;
setViewStatus: (status: 'quit' | 'maximize' | 'minimize' | 'unmaximize') => void; setViewStatus: (status: 'quit' | 'maximize' | 'minimize' | 'unmaximize') => void;
setJoinChannel: () => Promise<void>; setJoinChannel: () => Promise<void>;
getVideoId: () => string; getVideoId: () => string;
startRecordingDeviceTest: (indicationInterval:number) => void;
stopAudioDeviceLoopbackTest: () => void;
startPreview: () => Promise<boolean>;
} }
declare global { declare global {

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
appid: "dcfc466a6ecb4a1f972630065dfb1e75", appid: "dcfc466a6ecb4a1f972630065dfb1e75",
token: "007eJxTYNDz89yosT64YN5i3snT6nzY/aVOvs1Tmu3zc9r6qUkXHyxSYEhJTks2MTNLNEtNTjJJNEyzNDcyMzYwMDNNSUsyTDU3FQxuTmsIZGSQn/iShZEBAkF8bgZDc3MjYwMLU2MTMwYGAAHrH7M=", token: "007eJxTYOAzvBU4eaX8g2nNm16Yp0YZ6SzIVbXWteo/H1tr947n0jUFhpTktGQTM7NEs9TkJJNEwzRLcyMzYwMDM9OUtCTDVHPT9MD2tIZARobaiU4MjFAI4nMzGJqbGxkbWJgam5gxMAAA0L4e4A==",
channelId: '17723085346', channelId: '17723085346',
} }

View File

@ -1,95 +0,0 @@
// import AgoraRTC from "agora-rtc-sdk-ng"
// let rtcClient = null as any;
// const options = {
// appId: "dcfc466a6ecb4a1f972630065dfb1e75",
// channel: '17723085346',
// token: "007eJxTYNDlkfJ9fD3lzh2e0KI5Oyy6vdU7phyIXOpV8F36/xPOeS8VGFKS05JNzMwSzVKTk0wSDdMszY3MjA0MzExT0pIMU81Np/g0pTUEMjJExEqyMjJAIIjPzWBobm5kbGBhamxixsAAAC6mH9k=",
// uid: 'eaecab',
// };
// rtcClient = AgoraRTC.createClient({ mode: "live", codec: "vp8" });
// // 以观众身份加入房间
// export async function AudienceJoinChannel(channel: any, uid: string | number) {
// await SetRule(1)
// await rtcClient.join(options.appId, channel, options.token, uid)
// }
// // 加入房间
// export async function JoinChannel(channel: any, uid: string | number) {
// await rtcClient.join(options.appId, channel, options.token, uid)
// }
// // 设置用户角色 1=观众 2=主播
// export async function SetRule(type: number) {
// await rtcClient.setClientRole(type == 1 ? "audience" : "host");
// }
// // 接流
// export async function ReceiveFLow(flowHandld: any) {
// rtcClient.on("user-published", async (user: any, mediaType: any) => {
// await rtcClient.subscribe(user, mediaType);
// console.log(user,'嘻嘻');
// flowHandld(user)
// });
// }
// // 远端取消推流
// export function ChannelFlow(channelHandle: any) {
// rtcClient.on("user-unpublished", (user: any) => {
// channelHandle(user)
// });
// }
// // 离开频道
// export function LeaveChannel() {
// rtcClient.leave()
// }
// // 发布本地音频轨道
// export async function PublishAudio(deviceId: string) {
// var audioTrack = await AgoraRTC.createMicrophoneAudioTrack({
// AEC: true, // 是否开启回声消除
// AGC: true, // 是否开启自动增益
// ANS: true, // 是否开启噪声抑制
// microphoneId: deviceId // 麦克风的设备 ID
// })
// await rtcClient.publish(audioTrack)
// }
// // 发布本地视频轨道 硬件设备
// export async function PublishVideo(deviceId: string) {
// var videoTrack = await AgoraRTC.createCameraVideoTrack({
// cameraId: deviceId,
// encoderConfig: '1080p_3'
// })
// await rtcClient.publish(videoTrack)
// }
// // 发布本地视频轨道 屏幕共享
// export async function PublishVideoScreen(sharedScreenItem: any) {
// var screenTrack = await AgoraRTC.createScreenVideoTrack({
// encoderConfig: "1080p_1",
// electronScreenSourceId: sharedScreenItem.id,
// })
// await rtcClient.publish(screenTrack)
// }
// // 获取麦克风设备列表
// export async function GetMicrophones() {
// return await AgoraRTC.getMicrophones()
// }
// // 获取摄像头设备列表
// export async function GetCameras() {
// return await AgoraRTC.getCameras()
// }
// // 取消发布所有流
// export async function UnpublishAll() {
// await rtcClient.unpublish()
// }

View File

@ -170,3 +170,20 @@
max-height: 70vh; max-height: 70vh;
overflow-y: auto; overflow-y: auto;
} }
.ant-slider:hover .ant-slider-rail {
background-color: white;
}
.ant-slider .ant-slider-rail {
background-color: #D9D9D9;
}
.ant-slider .ant-slider-track {
background-color: #3672E9;
}
.ant-slider .ant-slider-handle::after {
background-color: #3672E9;
box-shadow: 0 0 0 2px #3672E9;
}

View File

@ -1 +1 @@
.ant-input{background-color:#28282C !important;border:1px solid #404145;color:white;box-sizing:border-box}.ant-input::placeholder{color:#E6E6E6}.ant-input-affix-wrapper{background-color:#28282C !important;border:1px solid #404145;box-sizing:border-box}.ant-input-affix-wrapper .ant-input{color:white !important}.ant-input-affix-wrapper .ant-input-password-icon{color:white !important}.m-ant-btn.ant-btn{background-color:#3F51B5;box-shadow:none}.m-ant-btn.ant-btn:hover{background-color:#606fc7 !important}.m-ant-btn.ant-btn:active{background-color:#32408f !important}.m-border-ant-button.ant-btn{border:1px solid #5575F2 !important;color:#5575F2 !important;background-color:#1E1E1F !important}.ant-checkbox-wrapper{color:#848484}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner{background-color:#28282C !important;border:1px solid #404145}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner::after{background-color:#3F51B5 !important}.ant-checkbox-wrapper .ant-checkbox-checked .ant-checkbox-inner{background-color:#3F51B5 !important;border:1px solid #404145}.ant-table{background-color:#1B1E24 !important;border-radius:0px !important}.ant-table .ant-table-header .ant-table-cell{background-color:#1B1E24;color:#808080;box-shadow:none;border-bottom:1px solid transparent}.ant-table .ant-table-header .ant-table-cell::before{visibility:hidden}.ant-table .ant-table-body .ant-table-row{background-color:#16191e;color:white}.ant-table .ant-table-body .ant-table-row .ant-table-cell{border-bottom:1px solid #292F3A}.ant-table .ant-table-body .ant-table-row-selected .ant-table-cell{background-color:#0d0f12 !important;color:white}.ant-table .ant-table-body .ant-table-cell-row-hover{background-color:#0d0f12 !important}.ant-pagination .ant-pagination-prev{margin-right:10px !important}.ant-pagination .ant-pagination-prev,.ant-pagination .ant-pagination-next{width:30px !important;height:30px !important;border-radius:50%;background:#20242C}.ant-pagination .ant-pagination-prev .anticon,.ant-pagination .ant-pagination-next .anticon{color:#808080}.ant-pagination .ant-pagination-item{width:30px !important;height:30px !important;line-height:30px !important;border-radius:50%;background:#20242C !important;margin-right:10px !important}.ant-pagination .ant-pagination-item:hover{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item:hover a{color:black !important}.ant-pagination .ant-pagination-item-active{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item-active a{color:black !important}.ant-popover:not(.ant-popconfirm) .ant-popover-arrow::before{background-color:#07090B !important}.ant-popover:not(.ant-popconfirm) .ant-popover-content .ant-popover-inner{background-color:#07090B}.ant-modal-mask{background-color:rgba(0,0,0,0.25) !important}.ant-modal .ant-modal-content{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header .ant-modal-title{text-align:center;color:#EEEEEE;font-weight:bold}.ant-modal .ant-modal-content .ant-modal-body{max-height:70vh;overflow-y:auto} .ant-input{background-color:#28282C !important;border:1px solid #404145;color:white;box-sizing:border-box}.ant-input::placeholder{color:#E6E6E6}.ant-input-affix-wrapper{background-color:#28282C !important;border:1px solid #404145;box-sizing:border-box}.ant-input-affix-wrapper .ant-input{color:white !important}.ant-input-affix-wrapper .ant-input-password-icon{color:white !important}.m-ant-btn.ant-btn{background-color:#3F51B5;box-shadow:none}.m-ant-btn.ant-btn:hover{background-color:#606fc7 !important}.m-ant-btn.ant-btn:active{background-color:#32408f !important}.m-border-ant-button.ant-btn{border:1px solid #5575F2 !important;color:#5575F2 !important;background-color:#1E1E1F !important}.ant-checkbox-wrapper{color:#848484}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner{background-color:#28282C !important;border:1px solid #404145}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner::after{background-color:#3F51B5 !important}.ant-checkbox-wrapper .ant-checkbox-checked .ant-checkbox-inner{background-color:#3F51B5 !important;border:1px solid #404145}.ant-table{background-color:#1B1E24 !important;border-radius:0px !important}.ant-table .ant-table-header .ant-table-cell{background-color:#1B1E24;color:#808080;box-shadow:none;border-bottom:1px solid transparent}.ant-table .ant-table-header .ant-table-cell::before{visibility:hidden}.ant-table .ant-table-body .ant-table-row{background-color:#16191e;color:white}.ant-table .ant-table-body .ant-table-row .ant-table-cell{border-bottom:1px solid #292F3A}.ant-table .ant-table-body .ant-table-row-selected .ant-table-cell{background-color:#0d0f12 !important;color:white}.ant-table .ant-table-body .ant-table-cell-row-hover{background-color:#0d0f12 !important}.ant-pagination .ant-pagination-prev{margin-right:10px !important}.ant-pagination .ant-pagination-prev,.ant-pagination .ant-pagination-next{width:30px !important;height:30px !important;border-radius:50%;background:#20242C}.ant-pagination .ant-pagination-prev .anticon,.ant-pagination .ant-pagination-next .anticon{color:#808080}.ant-pagination .ant-pagination-item{width:30px !important;height:30px !important;line-height:30px !important;border-radius:50%;background:#20242C !important;margin-right:10px !important}.ant-pagination .ant-pagination-item:hover{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item:hover a{color:black !important}.ant-pagination .ant-pagination-item-active{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item-active a{color:black !important}.ant-popover:not(.ant-popconfirm) .ant-popover-arrow::before{background-color:#07090B !important}.ant-popover:not(.ant-popconfirm) .ant-popover-content .ant-popover-inner{background-color:#07090B}.ant-modal-mask{background-color:rgba(0,0,0,0.25) !important}.ant-modal .ant-modal-content{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header .ant-modal-title{text-align:center;color:#EEEEEE;font-weight:bold}.ant-modal .ant-modal-content .ant-modal-body{max-height:70vh;overflow-y:auto}.ant-slider:hover .ant-slider-rail{background-color:#fff}.ant-slider .ant-slider-rail{background-color:#D9D9D9}.ant-slider .ant-slider-track{background-color:#3672E9}.ant-slider .ant-slider-handle::after{background-color:#3672E9;box-shadow:0 0 0 2px #3672E9}

View File

@ -206,3 +206,27 @@ $pagination-hover-background-color: #5575F2;
} }
} }
} }
// Slider
.ant-slider {
&:hover {
.ant-slider-rail {
background-color: lighten(#D9D9D9, 100%);
}
}
.ant-slider-rail {
background-color: #D9D9D9;
}
.ant-slider-track {
background-color: #3672E9;
}
.ant-slider-handle {
&::after {
background-color: #3672E9;
box-shadow: 0 0 0 2px #3672E9;
}
}
}