diff --git a/src/assets/icon57.png b/src/assets/icon57.png new file mode 100644 index 0000000..71452a1 Binary files /dev/null and b/src/assets/icon57.png differ diff --git a/src/components/SpeakerModeModal/index.tsx b/src/components/SpeakerModeModal/index.tsx index 73e5351..848aad9 100644 --- a/src/components/SpeakerModeModal/index.tsx +++ b/src/components/SpeakerModeModal/index.tsx @@ -53,14 +53,14 @@ const SpeakerModeModal = forwardRef((props: any, ref: any) => { }) const FreedomMode: React.FC = ({ onClick, meetingMode }) => { - // 自由者模式 + // 宫格模式 return ( <>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16].map(item =>
)}
- 自由者模式 + 宫格模式
) diff --git a/src/page/Meeting/index.module.scss b/src/page/Meeting/index.module.scss index 8c623a0..9c9a575 100644 --- a/src/page/Meeting/index.module.scss +++ b/src/page/Meeting/index.module.scss @@ -10,7 +10,7 @@ .meetingContentUserName { display: flex; align-items: center; - background-color: #0000009E; + background-color: rgba(0, 0, 0, 0.62); border-radius: 6px; height: 24px; padding: 0 4px; @@ -285,14 +285,126 @@ } } + // 宫格模式 + // 1 + .meetingContentBodyLeftFreedomModeOne { + width: 100%; + height: 100%; - // 自由者模式 - .meetingContentBodyLeftFreedomMode { + .meetingContentSwiperCard { + width: 100%; + height: 100%; + } + } + + // 2 + .meetingContentBodyLeftFreedomModeTwo { + width: 100%; + height: 100%; + display: flex; + + .meetingContentSwiperCard { + width: 50%; + height: 100%; + } + } + + // 3 4 + .meetingContentBodyLeftFreedomModeThree { width: 100%; height: 100%; display: flex; flex-wrap: wrap; - overflow-y: auto; + justify-content: center; + + .meetingContentSwiperCard { + width: 50%; + height: 50%; + } + } + + //5 6 + .meetingContentBodyLeftFreedomModeFour { + width: 100%; + height: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .meetingContentSwiperCard { + width: calc(100% / 3); + height: 50%; + } + } + + // 7 + .meetingContentBodyLeftFreedomModeFive { + width: 100%; + height: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .meetingContentSwiperCard { + width: calc(100% / 4); + height: 50%; + } + } + + //8 9 + .meetingContentBodyLeftFreedomModeSix { + width: 100%; + height: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .meetingContentSwiperCard { + width: calc(100% / 3); + height: calc(100% / 3); + } + } + + // 10 11 12 + .meetingContentBodyLeftFreedomModeSeven { + width: 100%; + height: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .meetingContentSwiperCard { + width: calc(100% / 4); + height: calc(100% / 3); + } + } + + // 13 14 15 16 + .meetingContentBodyLeftFreedomModeEight { + width: 100%; + height: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .meetingContentSwiperCard { + width: calc(100% / 4); + height: calc(100% / 4); + } + } + + // 17 18 19 20 + .meetingContentBodyLeftFreedomModeNine { + width: 100%; + height: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .meetingContentSwiperCard { + width: calc(100% / 5); + height: calc(100% / 4); + } } // 标准模式 @@ -309,9 +421,6 @@ .meetingContentSwiperCard { width: 100%; - } - - .meetingContentSwiperCard { height: 160px; } } @@ -888,40 +997,72 @@ } .modePopover { + display: flex; + flex-direction: column; + align-items: center; + >div { - width: 140px; - height: 30px; - line-height: 30px; - border-radius: 5px; - margin-bottom: 8px; - cursor: pointer; display: flex; align-items: center; - justify-content: center; - >span { - color: #EEEEEE; + >div { + width: 100px; + padding: 10px 0; + line-height: 30px; + border-radius: 5px; + cursor: pointer; + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + margin-right: 20px; + + >span { + color: #EEEEEE; + } + + >img { + height: 30px; + margin-bottom: 4px; + } } - >img { - height: 16px; - margin-right: 10px; + >div { + background-color: #101418; + + &:hover { + background-color: lighten(#101418, 4%); + } + + &:active { + background-color: darken(#101418, 4%); + } } - &:last-child { - margin: 0; + .active { + background-color: lighten(#101418, 8%); + cursor: not-allowed; + + &:hover { + background-color: lighten(#101418, 8%); + } + + &:active { + background-color: lighten(#101418, 8%); + } + } + + :last-child { + margin-right: 0px; } } - >div { - background-color: #101418; + >span { + margin-top: 4px; + color: white; - &:hover { - background-color: lighten(#101418, 4%); - } - - &:active { - background-color: darken(#101418, 4%); + >span { + margin-left: 4px; } } } diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index 8e8b294..530e70e 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -183,7 +183,7 @@ const Meeting: React.FC = () => { const [isClickLock, setIsClickLock] = useState(false) const [open, setOpen] = useState(false) const [modeOpen, setModeOpen] = useState(false) - const [meetingMode, setMeetingMode] = useState('') + const [meetingMode, setMeetingMode] = useState('FreedomMode') const [userSearchValue, setUserSearchValue] = useState('') const [noViewChatList, setNoViewChatList] = useState(0) const [currentLookUserAccount, setCurrentLookUserAccount] = useState('') @@ -216,6 +216,7 @@ const Meeting: React.FC = () => { } }); const [isVideoFullScreen, setIsVideoFullScreen] = useState(false) + const [_freedomModeStatus, setFreedomModeStatus] = useState(false) const [observer, setObserver] = useState() const [_activeSpeaker, setActiveSpeaker] = useState('') let userInfo = JSON.parse(storage.getItem('user') as string) @@ -234,7 +235,6 @@ const Meeting: React.FC = () => { } }) setKeyOpenChildWindow('shareScreenWindow', false) - setMeetingMode('StandardMode'); agoraInit() storage.setItem('noViewChatList', 0) window.addEventListener('customStorageChange', handleCustomStorageChange); @@ -638,18 +638,36 @@ const Meeting: React.FC = () => { if (isShare) { const item = roomUserList.find((item: any) => item.screenShareId === String(isShare)) setIsShareUser(item || null) + setMeetingMode('StandardMode') } }, [isShare, roomUserList]); + useEffect(() => { + setFreedomModeStatus((res: boolean) => { + if (meetingMode === 'FreedomMode') { + return true + } else { + if (res) { + getShowUser(true) + } + return false + } + }) + }, [meetingMode]); + useEffect(() => { roomUserList.forEach(async (item: any) => { - if (item.uid === currentVideoId) { + if (meetingMode === "FreedomMode") { await agora.setRemoteVideoStreamType(item.uid, VideoStreamType.VideoStreamHigh, true) } else { - await agora.setRemoteVideoStreamType(item.uid, VideoStreamType.VideoStreamLow, true) + if (item.uid === currentVideoId) { + await agora.setRemoteVideoStreamType(item.uid, VideoStreamType.VideoStreamHigh, true) + } else { + await agora.setRemoteVideoStreamType(item.uid, VideoStreamType.VideoStreamLow, true) + } } }); - }, [currentVideoId, roomUserList]); + }, [currentVideoId, roomUserList, meetingMode]); useEffect(() => { let item = roomUserList.find((item: any) => currentVideoId == item.uid) @@ -722,7 +740,13 @@ const Meeting: React.FC = () => { break; // 扩展操作 case 'Operation': - switch (item.contentString) { + try { + const temp = JSON.parse(item.contentString) + if (temp.type === 'mode') { + temp.msg ? message.success(`管理员已将会议室显示模式更新为${getMeetingContentBodyLeftModeText(temp.mode)}`) : null; + setMeetingMode(temp.mode) + } + } catch (error) { } break; @@ -738,7 +762,7 @@ const Meeting: React.FC = () => { break; // 更新视图模式 case 'RefreshView': - setMeetingMode(item.type) + break; // 全员看他 case 'ShowUser': @@ -987,7 +1011,7 @@ const Meeting: React.FC = () => { uid: temp.uid, enableMicr: temp.enableMicr }) - } else { + } else if (temp.type === 'video') { await PostOpenCamera({ roomNum: temp.roomNum, uid: temp.uid, @@ -1583,7 +1607,11 @@ const Meeting: React.FC = () => { item.isShow = true; } }); - setIsAdmin(res.filter((item: any) => (role.ID.includes(item.roleId) || item.isRoomManager) && item.isRoom).length) + const peoPleLength = res.filter((item: any) => (role.ID.includes(item.roleId) || item.isRoomManager) && item.isRoom).length + setIsAdmin(peoPleLength) + if (peoPleLength > 6) { + setMeetingMode('StandardMode') + } return res }) } @@ -1715,16 +1743,18 @@ const Meeting: React.FC = () => { }) } // 渲染视频 - const renderVideo = async (uid: string = ''): Promise => { - if (isClickLock) { - return - } - if (uid) { - if (currentVideoId === uid || currentVideoUid === uid) { + const renderVideo = async (uid: string = '', bool: boolean = false): Promise => { + if (!bool) { + if (isClickLock) { return } - } else { - uid = userInfo.uid + if (uid) { + if (currentVideoId === uid || currentVideoUid === uid) { + return + } + } else { + uid = userInfo.uid + } } await agora.destroyRendererByView(`video-source-camera-primary`) await agora.destroyRendererByView(`video-source-screen`) @@ -1762,11 +1792,11 @@ const Meeting: React.FC = () => { }, 500); } // 全员观看 - const getShowUser = async (): Promise => { + const getShowUser = async (bool: boolean = false): Promise => { if (location.href.indexOf('/meeting') !== -1) { await GetShowUser(state.channelId).then(async (res) => { if (res.code === 200 && res.data) { - renderVideo(res.data) + renderVideo(res.data, bool) } }) } @@ -2142,6 +2172,14 @@ const Meeting: React.FC = () => { await PostStopSharedScreen(state.channelId) } else { await PostShowUser(state.channelId, uid, name) + await window.electron.onInvoke('sendOper', { + roomNum: state.channelId, + contentString: JSON.stringify({ + mode: 'StandardMode', + type: 'mode', + msg: false + }) + }) } } // 设置发言人 @@ -2454,10 +2492,37 @@ const Meeting: React.FC = () => { }) } // 获取当前模式样式 - const getMeetingContentBodyLeftModeClass = (): string => { + const getMeetingContentBodyLeftModeClass = (people: Number): string => { switch (meetingMode) { case 'FreedomMode': - return styles.meetingContentBodyLeftFreedomMode + switch (people) { + case 1: + return styles.meetingContentBodyLeftFreedomModeOne; + case 2: + return styles.meetingContentBodyLeftFreedomModeTwo; + case 3: + case 4: + return styles.meetingContentBodyLeftFreedomModeThree; + case 5: + case 6: + return styles.meetingContentBodyLeftFreedomModeFour; + case 7: + return styles.meetingContentBodyLeftFreedomModeFive; + case 8: + case 9: + return styles.meetingContentBodyLeftFreedomModeSix; + case 10: + case 11: + case 12: + return styles.meetingContentBodyLeftFreedomModeSeven; + case 13: + case 14: + case 15: + case 16: + return styles.meetingContentBodyLeftFreedomModeEight; + default: + return styles.meetingContentBodyLeftFreedomModeNine; + } case 'StandardMode': return styles.meetingContentBodyLeftStandardMode case 'SpeakerMode': @@ -2472,10 +2537,10 @@ const Meeting: React.FC = () => { return '' } // 获取当前模式文字 - const getMeetingContentBodyLeftModeText = (): string => { - switch (meetingMode) { + const getMeetingContentBodyLeftModeText = (mode?: string): string => { + switch (mode || meetingMode) { case 'FreedomMode': - return '自由者模式' + return '宫格模式' case 'StandardMode': return '标准模式' case 'SpeakerMode': @@ -2573,6 +2638,31 @@ const Meeting: React.FC = () => { } message.success('操作成功') } + // 设置模式 + const setSyncView = (mode: string) => { + if (meetingMode === mode) { + setModeOpen(false) + return message.error(`${getMeetingContentBodyLeftModeText(mode)}已开启,请勿重复操作!`) + } + if (isAdmin > 6 && mode === 'FreedomMode') { + setModeOpen(false) + return message.error('发言人数超过6人,无法使用宫格模式!') + } + if (isShare && mode === 'FreedomMode') { + setModeOpen(false) + return message.error('共享中,无法切换模式') + } + window.electron.onInvoke('sendOper', { + roomNum: state.channelId, + contentString: JSON.stringify({ + mode, + type: 'mode', + msg: true, + }) + }) + setModeOpen(false) + storage.setItem('meetingMode', mode) + } // 判断是否出现滚动条 const hasScrollbar = () => { let element = document.getElementById('videoView') as HTMLDivElement @@ -2602,6 +2692,9 @@ const Meeting: React.FC = () => { <>
{ setContextMenu('') + if (modeOpen) { + setModeOpen(false) + } setIsNetworkQuality(false) }}> {isScreenCapture ?
@@ -2771,28 +2864,33 @@ const Meeting: React.FC = () => {
- -
{ - setModeOpen(false) - storage.setItem('meetingMode', 'StandardMode') - }}> - - 标准模式 -
-
{ - setModeOpen(false) - storage.setItem('meetingMode', 'SpeakerMode') - }}> - - 演讲模式 -
-
{ - setModeOpen(false) - }}> - 取消 +
+
{ + setSyncView('FreedomMode') + }}> + + 宫格模式 +
+
{ + setSyncView('StandardMode') + }}> + + 标准模式 +
+
{ + setSyncView('SpeakerMode') + }}> + + 演讲模式 +
+ + + 改变布局将对所有成员生效 +
} title="" @@ -2801,10 +2899,14 @@ const Meeting: React.FC = () => { onOpenChange={() => setModeOpen(true)} >
- {meetingMode === 'StandardMode' ? : } + {meetingMode === 'StandardMode' ? + : + meetingMode === 'FreedomMode' ? + : + } {getMeetingContentBodyLeftModeText()}
-
+ : null}
@@ -2812,7 +2914,7 @@ const Meeting: React.FC = () => {
{isAdmin && currentLookUserAccount ? getSettingIcon() : null} -
+
{roomUserList.map((item: any, index: number) => { return (item.isRoom && item.isAdmin ?
{
: null) } )} - {hasScrollbar() ?
+ {/*
+
+
+
+
+
*/} + {meetingMode !== "FreedomMode" && hasScrollbar() ?
{meetingMode === "StandardMode" ?
{ const container = document.getElementById('videoView') as HTMLElement; container.scrollLeft -= 100 @@ -2961,7 +3069,7 @@ const Meeting: React.FC = () => {
}
: null} - {currentLookUserStatus === 0 ? + {meetingMode !== "FreedomMode" && currentLookUserStatus === 0 ?
{
@@ -2972,7 +3080,7 @@ const Meeting: React.FC = () => { setIsVideoFullScreen(true)} />} {meetingContentUser(currentLookUserAccount, true)}
: null} - {currentLookUserStatus === 1 ? + {meetingMode !== "FreedomMode" && currentLookUserStatus === 1 ?
{
@@ -2984,7 +3092,7 @@ const Meeting: React.FC = () => { {meetingContentUser(currentLookUserAccount, true)} {currentLookUserAccount.enableCamera ? null : meetingContentError(currentLookUserAccount)}
: null} - {currentLookUserStatus === 2 ? + {meetingMode !== "FreedomMode" && currentLookUserStatus === 2 ?
@@ -2995,7 +3103,7 @@ const Meeting: React.FC = () => { setIsVideoFullScreen(true)} />} {meetingContentUser(currentLookUserAccount, true)}
: null} - {currentLookUserStatus === 3 ? + {meetingMode !== "FreedomMode" && currentLookUserStatus === 3 ?
@@ -3006,7 +3114,7 @@ const Meeting: React.FC = () => { setIsVideoFullScreen(true)} />} {meetingContentUser(currentLookUserAccount, true)}
: null} - {currentLookUserStatus === 4 ? + {meetingMode !== "FreedomMode" && currentLookUserStatus === 4 ?
diff --git a/src/utils/package/imageUrl.ts b/src/utils/package/imageUrl.ts index 2c349a4..7cbd15c 100644 --- a/src/utils/package/imageUrl.ts +++ b/src/utils/package/imageUrl.ts @@ -86,6 +86,7 @@ import icon54 from '@/assets/icon54.png' import icon55 from '@/assets/icon55.png' import icon56 from '@/assets/icon56.png' import icon56Active from '@/assets/icon56-active.png' +import icon57 from '@/assets/icon57.png' export default { loading, icon, @@ -174,5 +175,6 @@ export default { icon54, icon55, icon56, - icon56Active + icon56Active, + icon57, } \ No newline at end of file