This commit is contained in:
yj 2024-07-25 11:56:46 +08:00
parent 97075d90da
commit f5ba7b4284
14 changed files with 255 additions and 231 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

BIN
src/assets/icon39.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

BIN
src/assets/icon40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

BIN
src/assets/icon41.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

BIN
src/assets/icon42.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

View File

@ -1,85 +1,91 @@
// 设置向导
.stupWizard {
height: 70vh;
display: flex;
flex-direction: column;
>div:nth-child(1) {
padding: 20px 0 0;
overflow-x: hidden;
max-height: 60vh;
.stupWizardLeft {
background-color: #0C111A;
flex-shrink: 0;
width: 154px;
height: 100%;
overflow-y: auto;
>div:nth-child(1) {
>div {
display: flex;
align-items: center;
cursor: pointer;
padding: 12px 16px;
box-sizing: border-box;
>span {
color: #EEEEEE;
font-weight: bold;
font-size: 20px;
font-size: 16px;
margin-left: 10px;
}
>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 {
height: 20px;
}
}
.active {
background-color: #131924;
>span {
color: #5575F2;
}
}
}
.stupWizardRight {
flex-grow: 1;
height: 100%;
>div {
display: flex;
flex-direction: column;
height: 100%;
>span {
flex-shrink: 0;
width: 36px;
margin-right: 20px;
color: #FFFFFF;
font-size: 16px;
border-bottom: 1px solid #292E33;
padding: 10px 20px;
box-sizing: border-box;
}
>div {
flex-grow: 1;
height: 40px;
position: relative;
>img {
height: 100%;
overflow-y: auto;
padding: 20px;
box-sizing: border-box;
}
}
}
}
>div {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 0%;
.videoComponents {
>div:nth-child(1) {
width: 100%;
height: 296px;
border-radius: 10px;
overflow: hidden;
>img {
>video {
width: 100%;
height: 100%;
}
}
}
}
}
}
>div:nth-child(2) {
flex-shrink: 0;
width: 100%;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 20px;
>span {
color: white;
}
}
}

View File

@ -1,20 +1,45 @@
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 { Button, Empty, message, Modal, Select, Slider } from 'antd';
import { useState, useImperativeHandle, forwardRef, useEffect } from "react";
import agora from '@/utils/package/agora'
const StupWizard = forwardRef((props: any, ref: any) => {
useImperativeHandle(ref, () => ({
changeIsStupWizard: () => {
changeModal: () => {
agora.init()
setIsStupWizard(true)
getAudioMediaList(true)
agora.startPlaybackDeviceTest()
agora.setPlaybackDeviceVolume(100)
// getAudioMediaList(true)
// agora.startPlaybackDeviceTest()
// agora.setPlaybackDeviceVolume(100)
}
}))
const [list, setList] = useState([
{
title: '视频',
icon: ImageUrl.icon39,
iconActive: ImageUrl.icon39Active,
active: true,
},
{
title: '音频',
icon: ImageUrl.icon40,
iconActive: ImageUrl.icon40Active,
active: false,
},
{
title: '录制',
icon: ImageUrl.icon41,
iconActive: ImageUrl.icon41Active,
active: false,
},
{
title: '共享文件',
icon: ImageUrl.icon42,
iconActive: ImageUrl.icon42Active,
active: false,
}
])
const [isStupWizard, setIsStupWizard] = useState(false);
const [stepsStatus, setStepsStatus] = useState<number>(1);
const [isVideoLoad, setIsVideoLoad] = useState<boolean>(false);
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
currentDevices: [],
currentDevice: {},
@ -34,164 +59,122 @@ const StupWizard = forwardRef((props: any, ref: any) => {
currentVolume,
})
}
// 音频设置向导
// 视频测试
return (
<>
<Modal title="设置向导" open={isStupWizard} footer={null} closable={false} centered width={'40vw'}>
<Modal
title=""
open={isStupWizard}
footer={null}
closable={false}
centered
width={'70vw'}
className='modal-padding'>
<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 className={styles.stupWizardLeft}>
{list.map((row: any, index: number) => {
return (
<div key={index} className={`${row.active ? styles.active : ''}`} onClick={() => {
const newList = [...list]
newList.forEach(item => item.active = false)
newList[index].active = true;
setList(newList)
}}>
<img src={row.active ? row.iconActive : row.icon} alt="" />
<span>{row.title}</span>
</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 className={styles.stupWizardRight}>
{list[0].active ? <VideoComponents /> : null}
{list[1].active ? <AudioComponents /> : null}
{list[2].active ? <RecordingComponents /> : null}
{list[3].active ? <RecordingComponents /> : null}
</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>
</>
)
})
const VideoComponents = () => {
const [videoDeviceManager, setVideoDeviceManager] = useState<any>({
list: [],
item: null,
});
useEffect(() => {
getVideoDeviceList()
}, []);
const getVideoDeviceList = (): void => {
agora.getVideoDeviceManager().then(res => {
const { item, list } = res
setVideoDeviceManager({
list: list.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
item: item ? item : null,
})
agora.startPreview('videoPreview')
})
}
return (
<>
<div>
<span></span>
<div className={styles.videoComponents}>
{
videoDeviceManager.item ?
<div>
<video id='videoPreview' controls></video>
</div> :
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}><Empty description={'未检测到摄像头'} /></div>
}
<div>
<span></span>
<Select
placeholder={videoDeviceManager.list.length ? '请选择设备' : '未检测到摄像头'}
options={videoDeviceManager.list} style={{ flexGrow: 1 }}
value={videoDeviceManager.item} onChange={(e) => {
}} />;
</div>
</div>
</div>
</>
)
}
const AudioComponents = () => {
return (
<>
<div>
<span></span>
<div></div>
</div>
</>
)
}
const RecordingComponents = () => {
return (
<>
<div>
<span></span>
<div></div>
</div>
</>
)
}
const FileComponents = () => {
return (
<>
<div>
<span></span>
<div></div>
</div>
</>
)
}
export default StupWizard

View File

@ -1,5 +1,5 @@
import styles from '@/page/Home/index.module.scss'
import { useEffect, useState } from "react";
import { useEffect, useState, useRef } from "react";
import { Outlet, useNavigate } from 'react-router-dom';
import { Popconfirm } from 'antd';
import dayjs from 'dayjs';
@ -7,6 +7,7 @@ import 'dayjs/locale/zh-cn'
import { storage } from '@/utils';
import ImageUrl from '@/utils/package/ImageUrl'
import Avatar from '@/components/Avatar';
import StupWizard from '@/components/StupWizard';
dayjs.locale('zh-cn');
type navListType = {
title: string;
@ -19,6 +20,7 @@ type navListType = {
const Home: React.FC = () => {
const navigate = useNavigate();
const stupWizardRef = useRef<any>();
const [navList, setNavList] = useState<navListType[]>([
{
title: '首页',
@ -118,7 +120,9 @@ const Home: React.FC = () => {
})}
</div>
<div>
<div className='drag' title='设置'>
<div className='drag' title='设置' onClick={()=>{
stupWizardRef.current.changeModal()
}}>
<div></div>
<span></span>
</div>
@ -155,6 +159,7 @@ const Home: React.FC = () => {
<Outlet></Outlet>
</div>
</div>
<StupWizard ref={stupWizardRef} />
</>
)
}

View File

@ -263,28 +263,36 @@ const agora = {
maxDurationMs: 7200000, //maxDurationMs
})
},
// 获取系统中所有的视频设备列表。
getVideoDeviceManager: async (): Promise<any> => {
return {
list: rtcEngine.getVideoDeviceManager().enumerateVideoDevices(),
item: rtcEngine.getVideoDeviceManager().getDevice()
}
},
// 开启本地视频预览
startPreview: async (): Promise<boolean> => {
startPreview: async (id: string): Promise<boolean> => {
return new Promise((resolve, reject) => {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
}).then((stream) => {
let dom = document.getElementById('startPreview') as any;
let dom = document.getElementById(id) as any;
dom.srcObject = stream;
dom.play()
resolve(true)
}).catch((error) => {
console.log(error);
message.error('无法获取摄像头!');
resolve(true)
});
})
},
// 停止音频设备回路测试
stopAudioDeviceLoopbackTest: () => {
rtcEngine.getAudioDeviceManager().stopAudioDeviceLoopbackTest()

View File

@ -44,6 +44,14 @@ import icon35 from '@/assets/icon35.png'
import icon36 from '@/assets/icon36.png'
import icon37 from '@/assets/icon37.png'
import icon38 from '@/assets/icon38.png'
import icon39 from '@/assets/icon39.png'
import icon39Active from '@/assets/icon39-active.png'
import icon40 from '@/assets/icon40.png'
import icon40Active from '@/assets/icon40-active.png'
import icon41 from '@/assets/icon41.png'
import icon41Active from '@/assets/icon41-active.png'
import icon42 from '@/assets/icon42.png'
import icon42Active from '@/assets/icon42-active.png'
export default {
error,
icon,
@ -91,4 +99,12 @@ export default {
icon36,
icon37,
icon38,
icon39,
icon39Active,
icon40,
icon40Active,
icon41,
icon41Active,
icon42,
icon42Active,
}

View File

@ -288,6 +288,12 @@ $pagination-hover-background-color: #5575F2;
}
}
.modal-padding {
.ant-modal-content {
padding: 0;
}
}
// Slider
.ant-slider {
&:hover {