Compare commits

..

5 Commits

Author SHA1 Message Date
yangqiang 7f1c7722ec Merge pull request 'yangjie' (#10) from yangjie into master
Reviewed-on: #10
2024-09-24 16:17:34 +08:00
yj ef932fd3a8 添加加入房间钱的loading 2024-09-24 15:40:34 +08:00
yj a913c6520b 开发环境可关闭更新弹窗 2024-09-24 15:24:47 +08:00
yj 5c7d0d7649 强制更新 2024-09-24 15:22:08 +08:00
yj a5d755ffc8 网络显示优化 2024-09-24 15:15:24 +08:00
8 changed files with 233 additions and 57 deletions

View File

@ -68,7 +68,11 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
await GetCheckoutRoomNum(roomNum).then(res => { await GetCheckoutRoomNum(roomNum).then(res => {
if (res.code === 200) { if (res.code === 200) {
callBack(res.data) callBack(res.data)
} else {
storage.setItem('loading', false)
} }
}).catch(() => {
storage.setItem('loading', false)
}) })
} }
const getRoomRtcToken = async (roomNum: string, callBack: Function): Promise<void> => { const getRoomRtcToken = async (roomNum: string, callBack: Function): Promise<void> => {
@ -78,7 +82,11 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
token: res[0].data, token: res[0].data,
tokenA: res[1].data, tokenA: res[1].data,
}) })
} else {
storage.setItem('loading', false)
} }
}).catch(() => {
storage.setItem('loading', false)
}) })
} }
const postRefresh = async (callBack: Function): Promise<void> => { const postRefresh = async (callBack: Function): Promise<void> => {
@ -87,7 +95,11 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
storage.setItem('user', JSON.stringify(res.data)) storage.setItem('user', JSON.stringify(res.data))
storage.setItem('userLogin', true) storage.setItem('userLogin', true)
callBack(res.data) callBack(res.data)
} else {
storage.setItem('loading', false)
} }
}).catch(() => {
storage.setItem('loading', false)
}) })
} }
return ( return (
@ -172,6 +184,7 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
message.error('请输入会议号!') message.error('请输入会议号!')
return return
} }
storage.setItem('loading', true)
isGetCheckoutRoomNum(roomNumber, (bool: boolean) => { isGetCheckoutRoomNum(roomNumber, (bool: boolean) => {
if (bool) { if (bool) {
getRoomRtcToken(roomNumber, (options: any) => { getRoomRtcToken(roomNumber, (options: any) => {
@ -194,6 +207,8 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
} }
}) })
} }
}).finally(() => {
storage.setItem('loading', false)
}) })
}) })
} }

View File

@ -48,11 +48,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={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 }}>
@ -62,10 +63,10 @@ const UpdateModal = forwardRef((props: any, ref: any) => {
<div className={styles.buttons}> <div className={styles.buttons}>
<Button type="primary" <Button type="primary"
onClick={() => window.electron.onDownload('1')} onClick={() => window.electron.onDownload('1')}
style={{ width: '100%', height: '40px' }} style={{ width: '100%', height: '40px', marginBottom: '10px' }}
className={`m-ant-btn`} className={`m-ant-btn`}
></Button> ></Button>
<div className={styles.button2} onClick={() => setIsUpdateModal(false)}></div> {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}%

View File

@ -87,6 +87,8 @@ const Index: React.FC = () => {
tokenA: res[1].data, tokenA: res[1].data,
}) })
} }
}).finally(() => {
storage.setItem('loading', false)
}) })
} }
const postRefresh = async (callBack: Function): Promise<void> => { const postRefresh = async (callBack: Function): Promise<void> => {
@ -95,7 +97,11 @@ const Index: React.FC = () => {
storage.setItem('user', JSON.stringify(res.data)) storage.setItem('user', JSON.stringify(res.data))
storage.setItem('userLogin', true) storage.setItem('userLogin', true)
callBack(res.data) callBack(res.data)
} else {
storage.setItem('loading', false)
} }
}).catch(() => {
storage.setItem('loading', false)
}) })
} }
@ -206,7 +212,7 @@ const Index: React.FC = () => {
<img src={ImageUrl.icon10} alt="" /> <img src={ImageUrl.icon10} alt="" />
</div> </div>
<div> <div>
{role.ID.includes(userInfo.roleId) ? <Popover {role.ID.includes(userInfo.roleId) ? <Popover
content={ content={
<div className='meetingContentFooterPopover'> <div className='meetingContentFooterPopover'>
{userInfo.roleId === '1' ? <Popconfirm {userInfo.roleId === '1' ? <Popconfirm
@ -254,6 +260,7 @@ const Index: React.FC = () => {
if (role.ID.includes(userInfo.roleId)) { if (role.ID.includes(userInfo.roleId)) {
joinSettingRef.current.changeModal(item.roomNum) joinSettingRef.current.changeModal(item.roomNum)
} else { } else {
storage.setItem('loading', true)
postRefresh(() => { postRefresh(() => {
getRoomRtcToken(item.roomNum, (options: any) => { getRoomRtcToken(item.roomNum, (options: any) => {
if (options) { if (options) {

View File

@ -111,6 +111,14 @@
>div:nth-child(1) { >div:nth-child(1) {
margin-right: 20px; margin-right: 20px;
display: flex; display: flex;
align-items: center;
cursor: pointer;
>span {
color: #1677ff;
font-size: 16px;
margin-left: 4px;
}
} }
>div:nth-child(2) { >div:nth-child(2) {

View File

@ -4,7 +4,7 @@ import Operation from '@/components/Operation';
import SpeakerModeModal from '@/components/SpeakerModeModal'; import SpeakerModeModal from '@/components/SpeakerModeModal';
import InvitingPersonnelModal from '@/components/InvitingPersonnelModal'; import InvitingPersonnelModal from '@/components/InvitingPersonnelModal';
import { Button, Input, Popover, Modal, Checkbox, message, Popconfirm, notification } from "antd"; import { Button, Input, Popover, Modal, Checkbox, message, Popconfirm, notification } from "antd";
import { SearchOutlined, EllipsisOutlined, ExclamationCircleFilled, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons'; import { SearchOutlined, EllipsisOutlined, ExclamationCircleFilled, FullscreenExitOutlined, FullscreenOutlined, QuestionCircleOutlined } 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';
@ -14,7 +14,7 @@ import { agora } from '@/utils/package/agora'
import { onInvoke, onSignalr, offSignalr, onStart } from '@/utils/package/signalr'; import { onInvoke, onSignalr, offSignalr, onStart } from '@/utils/package/signalr';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import durationPlugin from 'dayjs/plugin/duration'; import durationPlugin from 'dayjs/plugin/duration';
import { VideoSourceType, VideoStreamType } from 'agora-electron-sdk'; import { AudioVolumeInfo, QualityType, RtcConnection, RtcStats, UserOfflineReasonType, VideoSourceType, VideoStreamType } from 'agora-electron-sdk';
import Avatar from '@/components/Avatar'; import Avatar from '@/components/Avatar';
import SharedFilesModel from '@/components/SharedFilesModel'; import SharedFilesModel from '@/components/SharedFilesModel';
import StupWizard from '@/components/StupWizard'; import StupWizard from '@/components/StupWizard';
@ -146,7 +146,14 @@ const Meeting: React.FC = () => {
const [chatList, setChatList] = useState<any>([]) const [chatList, setChatList] = useState<any>([])
const [currentVideoId, setCurrentVideoId] = useState('') const [currentVideoId, setCurrentVideoId] = useState('')
let [currentSeconds, setCurrentSeconds] = useState(0) let [currentSeconds, setCurrentSeconds] = useState(0)
const [currentEffective, setCurrentEffective] = useState(0) const [currentEffective, setCurrentEffective] = useState(4)
const [currentNetworkInfo, setCurrentNetworkInfo] = useState({
networkQuality: {
level: '佳',
text: '网络质量极好。'
},
networkOther: {} as RtcStats
})
const [isComputerAudio, setIsComputerAudio] = useState(true) const [isComputerAudio, setIsComputerAudio] = useState(true)
const [isFluencyPriority, setIsFluencyPriority] = useState(false) const [isFluencyPriority, setIsFluencyPriority] = useState(false)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
@ -231,14 +238,54 @@ const Meeting: React.FC = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
const connection = (navigator as any).connection switch (currentEffective) {
if (connection.downlink === 0) { case 0:
setCurrentEffective(0) setCurrentNetworkInfo({
} else { ...currentNetworkInfo,
let effectiveTypeLength = ['slow-2g', '2g', '3g', '4g'].indexOf((navigator as any).connection.effectiveType) networkQuality: {
setCurrentEffective(effectiveTypeLength + 1) level: '断开连接',
text: '网络连接断开。'
}
})
break;
case 1:
setCurrentNetworkInfo({
...currentNetworkInfo,
networkQuality: {
level: '非常差',
text: '完全无法沟通。'
}
})
break;
case 2:
setCurrentNetworkInfo({
...currentNetworkInfo,
networkQuality: {
level: '差',
text: '勉强能沟通但不顺畅,网络质量非常差,基本不能沟通。'
}
})
break;
case 3:
setCurrentNetworkInfo({
...currentNetworkInfo,
networkQuality: {
level: '良好',
text: ' 用户主观感受有瑕疵但不影响沟通。'
}
})
break;
case 4:
setCurrentNetworkInfo({
...currentNetworkInfo,
networkQuality: {
level: '佳',
text: '网络质量极好。'
}
})
break;
} }
}, [(navigator as any).connection.effectiveType]); }, [currentEffective]);
useEffect(() => { useEffect(() => {
let currentVideoUserItem = roomUserList.find((item: any) => item.uid === currentVideoId || item.screenShareId === currentVideoId) let currentVideoUserItem = roomUserList.find((item: any) => item.uid === currentVideoId || item.screenShareId === currentVideoId)
@ -644,14 +691,14 @@ const Meeting: React.FC = () => {
await getJoin(state.enableMicr, state.enableCamera) await getJoin(state.enableMicr, state.enableCamera)
await agora.init(true) await agora.init(true)
agora.registerEventHandler({ agora.registerEventHandler({
onJoinChannelSuccess: async (info: any, _elapsed: any) => { onJoinChannelSuccess: async (connection: RtcConnection, _elapsed: number) => {
if (info.channelId === state.channelId) { if (connection.channelId === state.channelId) {
if (String(info.localUid).length !== 9) { if (String(connection.localUid).length !== 9) {
setTimeout(async () => { setTimeout(async () => {
await agora.setupLocalVideo({ await agora.setupLocalVideo({
uid: Number(info.localUid), uid: Number(connection.localUid),
view: document.getElementById(`video-${info.localUid}`), view: document.getElementById(`video-${connection.localUid}`),
channelId: info.channelId, channelId: connection.channelId,
sourceType: VideoSourceType.VideoSourceCameraPrimary, sourceType: VideoSourceType.VideoSourceCameraPrimary,
}) })
getShowUser(); getShowUser();
@ -659,8 +706,8 @@ const Meeting: React.FC = () => {
} }
} }
}, },
onUserJoined: async (info: any, remoteUid: any, _elapsed: any) => { onUserJoined: async (connection: RtcConnection, remoteUid: number, _elapsed: number) => {
if (info.channelId === state.channelId) { if (connection.channelId === state.channelId) {
if (String(remoteUid).length === 9) { if (String(remoteUid).length === 9) {
setIsShare(remoteUid) setIsShare(remoteUid)
} else { } else {
@ -668,21 +715,21 @@ const Meeting: React.FC = () => {
await agora.setupRemoteVideoJoin({ await agora.setupRemoteVideoJoin({
uid: Number(remoteUid), uid: Number(remoteUid),
view: document.getElementById(`video-${remoteUid}`), view: document.getElementById(`video-${remoteUid}`),
channelId: info.channelId, channelId: connection.channelId,
}) })
}, 1500); }, 1500);
} }
} }
}, },
onUserOffline: async (info: any, remoteUid: any, _reason: any) => { onUserOffline: async (connection: RtcConnection, remoteUid: number, _reason: UserOfflineReasonType) => {
if (info.channelId === state.channelId) { if (connection.channelId === state.channelId) {
if (String(remoteUid).length === 9) { if (String(remoteUid).length === 9) {
setIsShare(null) setIsShare(null)
} }
await agora.setupRemoteVideo({ await agora.setupRemoteVideo({
uid: Number(remoteUid), uid: Number(remoteUid),
view: null, view: null,
channelId: info.channelId, channelId: connection.channelId,
}); });
setCurrentVideoId((res: any) => { setCurrentVideoId((res: any) => {
if (Number(res) === remoteUid) { if (Number(res) === remoteUid) {
@ -692,7 +739,7 @@ const Meeting: React.FC = () => {
}) })
} }
}, },
onAudioVolumeIndication: async (speakers: any) => { onAudioVolumeIndication: async (speakers: AudioVolumeInfo[]) => {
speakers.forEach((item: any) => { speakers.forEach((item: any) => {
let domMe = document.getElementById(`micr-item-${userInfo.uid}`); let domMe = document.getElementById(`micr-item-${userInfo.uid}`);
let dom = document.getElementById(`micr-${item.uid ? item.uid : userInfo.uid}`); let dom = document.getElementById(`micr-${item.uid ? item.uid : userInfo.uid}`);
@ -705,6 +752,35 @@ const Meeting: React.FC = () => {
domMe.style.height = `${percentage}%` domMe.style.height = `${percentage}%`
} }
}); });
},
onNetworkQuality: async (_connection: RtcConnection, remoteUid: number, _txQuality: QualityType, rxQuality: QualityType) => {
if (remoteUid === 0) {
switch (rxQuality) {
case 1:
setCurrentEffective(4)
break;
case 2:
case 3:
setCurrentEffective(3)
break;
case 4:
case 5:
setCurrentEffective(2)
break;
case 6:
setCurrentEffective(1)
break;
default:
setCurrentEffective(navigator.onLine ? 4 : 0)
break;
}
}
},
onRtcStats: async (stats: RtcStats) => {
setCurrentNetworkInfo({
...currentNetworkInfo,
networkOther: stats
})
} }
}) })
if (state.enableCamera) { if (state.enableCamera) {
@ -1550,9 +1626,51 @@ const Meeting: React.FC = () => {
{contextHolder} {contextHolder}
<div className={styles.meetingHeader}> <div className={styles.meetingHeader}>
<div> <div>
<div> <Popover
{networkIcon(currentEffective)} content={
</div> <div style={{ color: 'white' }}>
<div>
<span></span>
<span>{currentNetworkInfo.networkQuality.level}</span>
<span>
<Popover
content={
<span
style={{ color: 'white' }}>
{currentNetworkInfo.networkQuality.text}
</span>
}
title=""
>
<QuestionCircleOutlined style={{
cursor: 'pointer',
marginLeft: '10px'
}} />
</Popover>
</span>
</div>
<div>
<span></span>
<span>{currentNetworkInfo.networkOther.txKBitRate}kbps {currentNetworkInfo.networkOther.rxKBitRate}kbps</span>
</div>
<div>
<span></span>
<span>{currentNetworkInfo.networkOther.txPacketLossRate}% {currentNetworkInfo.networkOther.rxPacketLossRate}%</span>
</div>
<div>
<span></span>
<span>{currentNetworkInfo.networkOther.lastmileDelay}ms</span>
</div>
</div>
}
title=""
trigger="hover"
>
<div className='drag'>
{networkIcon(currentEffective)}
<span></span>
</div>
</Popover>
<div>{changeCurrentSeconds()}</div> <div>{changeCurrentSeconds()}</div>
</div> </div>
<div>{state.channelId} {state.roomName}</div> <div>{state.channelId} {state.roomName}</div>
@ -2339,30 +2457,30 @@ const meetingContentError = (item: any) => {
const networkIcon = (network: number) => { const networkIcon = (network: number) => {
switch (network) { switch (network) {
case 0: case 0:
return <svg width="16" height="16" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg"> return <svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_5499_5160)"> <g clip-path="url(#clip0_5499_5160)">
<path d="M1.9 32.8398C0.85 32.8398 0 31.9898 0 30.9398V23.3398C0 22.2898 0.85 21.4398 1.9 21.4398C2.95 21.4398 3.8 22.2898 3.8 23.3398V30.9398C3.8 31.9898 2.95 32.8398 1.9 32.8398ZM11.3 32.8398C10.25 32.8398 9.4 31.9898 9.4 30.9398V16.1398C9.4 15.0898 10.25 14.2398 11.3 14.2398C12.35 14.2398 13.2 15.0898 13.2 16.1398V30.9398C13.2 31.9898 12.35 32.8398 11.3 32.8398ZM20.7 32.8398C19.65 32.8398 18.8 31.9898 18.8 30.9398V9.73984C18.8 8.68984 19.65 7.83984 20.7 7.83984C21.75 7.83984 22.6 8.68984 22.6 9.73984V30.9398C22.6 31.9898 21.75 32.8398 20.7 32.8398ZM30.1 32.8398C29.05 32.8398 28.2 31.9898 28.2 30.9398V2.73984C28.2 1.68984 29.05 0.839844 30.1 0.839844C31.15 0.839844 32 1.68984 32 2.73984V30.9398C32 31.9898 31.15 32.8398 30.1 32.8398Z" fill="#7C8280" /> <path d="M2.01914 32.4824C0.969141 32.4824 0.119141 31.6324 0.119141 30.5824V22.9824C0.119141 21.9324 0.969141 21.0824 2.01914 21.0824C3.06914 21.0824 3.91914 21.9324 3.91914 22.9824V30.5824C3.91914 31.6324 3.06914 32.4824 2.01914 32.4824ZM11.4191 32.4824C10.3691 32.4824 9.51914 31.6324 9.51914 30.5824V15.7824C9.51914 14.7324 10.3691 13.8824 11.4191 13.8824C12.4691 13.8824 13.3191 14.7324 13.3191 15.7824V30.5824C13.3191 31.6324 12.4691 32.4824 11.4191 32.4824ZM20.8191 32.4824C19.7691 32.4824 18.9191 31.6324 18.9191 30.5824V9.38242C18.9191 8.33242 19.7691 7.48242 20.8191 7.48242C21.8691 7.48242 22.7191 8.33242 22.7191 9.38242V30.5824C22.7191 31.6324 21.8691 32.4824 20.8191 32.4824ZM30.2191 32.4824C29.1691 32.4824 28.3191 31.6324 28.3191 30.5824V2.38242C28.3191 1.33242 29.1691 0.482422 30.2191 0.482422C31.2691 0.482422 32.1191 1.33242 32.1191 2.38242V30.5824C32.1191 31.6324 31.2691 32.4824 30.2191 32.4824Z" fill="#7C8280" />
<path d="M8.86265 3.02995L6.10877 5.78383L3.35489 3.02995C2.99725 2.67231 2.40713 2.67231 2.04948 3.02995C1.69184 3.3876 1.69184 3.97772 2.04948 4.33536L4.80336 7.08924L2.04948 9.84312C1.69184 10.2008 1.69184 10.7909 2.04948 11.1485C2.40713 11.5062 2.99725 11.5062 3.35489 11.1485L6.10877 8.39465L8.86265 11.1485C9.22029 11.5062 9.81041 11.5062 10.1681 11.1485C10.5257 10.7909 10.5257 10.2008 10.1681 9.84312L7.41418 7.08924L10.1681 4.33536C10.5257 3.97772 10.5257 3.3876 10.1681 3.02995C9.81041 2.67231 9.22029 2.67231 8.86265 3.02995Z" fill="#A5A5A5" /> <path d="M8.98179 2.67253L6.22791 5.42641L3.47403 2.67253C3.11639 2.31489 2.52627 2.31489 2.16863 2.67253C1.81098 3.03018 1.81098 3.62029 2.16863 3.97794L4.9225 6.73182L2.16863 9.48569C1.81098 9.84334 1.81098 10.4335 2.16863 10.7911C2.52627 11.1488 3.11639 11.1488 3.47403 10.7911L6.22791 8.03723L8.98179 10.7911C9.33943 11.1488 9.92955 11.1488 10.2872 10.7911C10.6448 10.4335 10.6448 9.84334 10.2872 9.48569L7.53332 6.73182L10.2872 3.97794C10.6448 3.62029 10.6448 3.03018 10.2872 2.67253C9.92955 2.31489 9.33943 2.31489 8.98179 2.67253Z" fill="#F90000" />
</g> </g>
<defs> <defs>
<clipPath id="clip0_5499_5160"> <clipPath id="clip0_5499_5160">
<rect width="32" height="32" fill="white" transform="translate(0 0.839844)" /> <rect width="32" height="32" fill="white" transform="translate(0.119141 0.482422)" />
</clipPath> </clipPath>
</defs> </defs>
</svg> </svg>
case 1: case 1:
return <svg width="16" height="16" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg"> return <svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.9 32.8385C0.85 32.8385 0 31.9885 0 30.9385V23.3385C0 22.2885 0.85 21.4385 1.9 21.4385C2.95 21.4385 3.8 22.2885 3.8 23.3385V30.9385C3.8 31.9885 2.95 32.8385 1.9 32.8385Z" fill="#02B188" /> <path d="M2.01914 32.482C0.969141 32.482 0.119141 31.632 0.119141 30.582V22.982C0.119141 21.932 0.969141 21.082 2.01914 21.082C3.06914 21.082 3.91914 21.932 3.91914 22.982V30.582C3.91914 31.632 3.06914 32.482 2.01914 32.482Z" fill="#FF800B" />
<path d="M28.1992 30.9389C28.1992 31.9889 29.0492 32.8389 30.0992 32.8389C31.1492 32.8389 31.9992 31.9889 31.9992 30.9389V2.73887C31.9992 1.68887 31.1492 0.838867 30.0992 0.838867C29.0492 0.838867 28.1992 1.68887 28.1992 2.73887V30.9389Z" fill="#7C8280" /> <path d="M28.3184 30.5824C28.3184 31.6324 29.1684 32.4824 30.2184 32.4824C31.2684 32.4824 32.1184 31.6324 32.1184 30.5824V2.38242C32.1184 1.33242 31.2684 0.482422 30.2184 0.482422C29.1684 0.482422 28.3184 1.33242 28.3184 2.38242V30.5824Z" fill="#7C8280" />
<path d="M18.8008 30.9389C18.8008 31.9889 19.6508 32.8389 20.7008 32.8389C21.7508 32.8389 22.6008 31.9889 22.6008 30.9389V9.73887C22.6008 8.68887 21.7508 7.83887 20.7008 7.83887C19.6508 7.83887 18.8008 8.68887 18.8008 9.73887V30.9389Z" fill="#7C8280" /> <path d="M18.9199 30.5824C18.9199 31.6324 19.7699 32.4824 20.8199 32.4824C21.8699 32.4824 22.7199 31.6324 22.7199 30.5824V9.38242C22.7199 8.33242 21.8699 7.48242 20.8199 7.48242C19.7699 7.48242 18.9199 8.33242 18.9199 9.38242V30.5824Z" fill="#7C8280" />
<path d="M9.40039 30.9393C9.40039 31.9893 10.2504 32.8393 11.3004 32.8393C12.3504 32.8393 13.2004 31.9893 13.2004 30.9393V16.1393C13.2004 15.0893 12.3504 14.2393 11.3004 14.2393C10.2504 14.2393 9.40039 15.0893 9.40039 16.1393V30.9393Z" fill="#7C8280" /> <path d="M9.51953 30.5828C9.51953 31.6328 10.3695 32.4828 11.4195 32.4828C12.4695 32.4828 13.3195 31.6328 13.3195 30.5828V15.7828C13.3195 14.7328 12.4695 13.8828 11.4195 13.8828C10.3695 13.8828 9.51953 14.7328 9.51953 15.7828V30.5828Z" fill="#7C8280" />
</svg> </svg>
case 2: case 2:
return <svg width="16" height="16" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg"> return <svg width="33" height="33" viewBox="0 0 33 33" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.9 32.8385C0.85 32.8385 0 31.9885 0 30.9385V23.3385C0 22.2885 0.85 21.4385 1.9 21.4385C2.95 21.4385 3.8 22.2885 3.8 23.3385V30.9385C3.8 31.9885 2.95 32.8385 1.9 32.8385Z" fill="#02B188" /> <path d="M2.01914 32.482C0.969141 32.482 0.119141 31.632 0.119141 30.582V22.982C0.119141 21.932 0.969141 21.082 2.01914 21.082C3.06914 21.082 3.91914 21.932 3.91914 22.982V30.582C3.91914 31.632 3.06914 32.482 2.01914 32.482Z" fill="#FF800B" />
<path d="M28.1992 30.9389C28.1992 31.9889 29.0492 32.8389 30.0992 32.8389C31.1492 32.8389 31.9992 31.9889 31.9992 30.9389V2.73887C31.9992 1.68887 31.1492 0.838867 30.0992 0.838867C29.0492 0.838867 28.1992 1.68887 28.1992 2.73887V30.9389Z" fill="#7C8280" /> <path d="M28.3184 30.5824C28.3184 31.6324 29.1684 32.4824 30.2184 32.4824C31.2684 32.4824 32.1184 31.6324 32.1184 30.5824V2.38242C32.1184 1.33242 31.2684 0.482422 30.2184 0.482422C29.1684 0.482422 28.3184 1.33242 28.3184 2.38242V30.5824Z" fill="#7C8280" />
<path d="M18.8008 30.9389C18.8008 31.9889 19.6508 32.8389 20.7008 32.8389C21.7508 32.8389 22.6008 31.9889 22.6008 30.9389V9.73887C22.6008 8.68887 21.7508 7.83887 20.7008 7.83887C19.6508 7.83887 18.8008 8.68887 18.8008 9.73887V30.9389Z" fill="#7C8280" /> <path d="M18.9199 30.5824C18.9199 31.6324 19.7699 32.4824 20.8199 32.4824C21.8699 32.4824 22.7199 31.6324 22.7199 30.5824V9.38242C22.7199 8.33242 21.8699 7.48242 20.8199 7.48242C19.7699 7.48242 18.9199 8.33242 18.9199 9.38242V30.5824Z" fill="#7C8280" />
<path d="M9.40039 30.9393C9.40039 31.9893 10.2504 32.8393 11.3004 32.8393C12.3504 32.8393 13.2004 31.9893 13.2004 30.9393V16.1393C13.2004 15.0893 12.3504 14.2393 11.3004 14.2393C10.2504 14.2393 9.40039 15.0893 9.40039 16.1393V30.9393Z" fill="#02B188" /> <path d="M9.51953 30.5828C9.51953 31.6328 10.3695 32.4828 11.4195 32.4828C12.4695 32.4828 13.3195 31.6328 13.3195 30.5828V15.7828C13.3195 14.7328 12.4695 13.8828 11.4195 13.8828C10.3695 13.8828 9.51953 14.7328 9.51953 15.7828V30.5828Z" fill="#FF800B" />
</svg> </svg>
case 3: case 3:
return <svg width="16" height="16" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg"> return <svg width="16" height="16" viewBox="0 0 32 33" fill="none" xmlns="http://www.w3.org/2000/svg">

View File

@ -8,7 +8,12 @@ import {
ChannelProfileType, ChannelProfileType,
AudioAinsMode, AudioAinsMode,
SimulcastStreamMode, SimulcastStreamMode,
VideoStreamType VideoStreamType,
QualityType,
RtcConnection,
RtcStats,
AudioVolumeInfo,
UserOfflineReasonType
} 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';
@ -104,19 +109,19 @@ export const agora = {
}, 1000); }, 1000);
}, },
// 事件回调 // 事件回调
registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication }: any) => { registerEventHandler: ({ onJoinChannelSuccess, onUserJoined, onUserOffline, onAudioVolumeIndication, onNetworkQuality, onRtcStats }: any) => {
rtcEngine.registerEventHandler({ rtcEngine.registerEventHandler({
// 监听本地用户加入频道事件 // 监听本地用户加入频道事件
onJoinChannelSuccess: async (info: any, elapsed: any) => { onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
await onJoinChannelSuccess(info, elapsed) await onJoinChannelSuccess(connection, elapsed)
}, },
// 监听远端用户加入频道事件 // 监听远端用户加入频道事件
onUserJoined: async (info: any, remoteUid: any, elapsed: any) => { onUserJoined: async (connection: RtcConnection, remoteUid: number, elapsed: number) => {
await onUserJoined(info, remoteUid, elapsed) await onUserJoined(connection, remoteUid, elapsed)
}, },
// 监听用户离开频道事件 // 监听用户离开频道事件
onUserOffline: async (info: any, remoteUid: any, reason: any) => { onUserOffline: async (connection: RtcConnection, remoteUid: number, reason: UserOfflineReasonType) => {
await onUserOffline(info, remoteUid, reason) await onUserOffline(connection, remoteUid, reason)
}, },
// // 视频发布状态改变回调 // // 视频发布状态改变回调
// onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => { // onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
@ -131,9 +136,17 @@ export const agora = {
// } // }
// }, // },
// // 用户音量提示回调。 // // 用户音量提示回调。
onAudioVolumeIndication: async (_connection: any, speakers: any, _speakerNumber: any, _totalVolume: any,) => { 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) => {
await onRtcStats(stats)
},
}); });
}, },
// 获取视图模式 // 获取视图模式

View File

@ -380,4 +380,8 @@ $pagination-hover-background-color: #5575F2;
// ant-message // ant-message
.ant-message { .ant-message {
-webkit-app-region: no-drag; -webkit-app-region: no-drag;
}
.ant-spin-fullscreen {
z-index: 10000;
} }

View File

@ -63,7 +63,12 @@ export default defineConfig({
VideoViewSetupMode, VideoViewSetupMode,
AudioAinsMode, AudioAinsMode,
SimulcastStreamMode, SimulcastStreamMode,
VideoStreamType VideoStreamType,
QualityType,
RtcConnection,
RtcStats,
AudioVolumeInfo,
UserOfflineReasonType
} = require("agora-electron-sdk") } = require("agora-electron-sdk")
export { export {
createAgoraRtcEngine, createAgoraRtcEngine,
@ -75,7 +80,12 @@ export default defineConfig({
VideoViewSetupMode, VideoViewSetupMode,
AudioAinsMode, AudioAinsMode,
SimulcastStreamMode, SimulcastStreamMode,
VideoStreamType VideoStreamType,
QualityType,
RtcConnection,
RtcStats,
AudioVolumeInfo,
UserOfflineReasonType
} }
`, `,
}) })