模式切换
This commit is contained in:
parent
2dac39f63c
commit
950076b8f5
|
|
@ -0,0 +1,137 @@
|
||||||
|
.speakerModeModal {
|
||||||
|
max-height: 40vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
align-content: flex-start;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
cursor: pointer;
|
||||||
|
width: calc(100% / 3);
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
height: 94px;
|
||||||
|
width: 144px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>span {
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.freedomMode {
|
||||||
|
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
width: calc(100% / 4);
|
||||||
|
height: calc(100% / 4);
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.standardMode {
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
>div:nth-child(1) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 25%;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
height: 100%;
|
||||||
|
width: calc(100% / 4);
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>div:nth-child(2) {
|
||||||
|
height: 75%;
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.speakerMode {
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
>div:nth-child(1) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 25%;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% / 4);
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>div:nth-child(2) {
|
||||||
|
width: 75%;
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.singleScreenMode {
|
||||||
|
>div {
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dualScreenMode {
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fourScreenMode {
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
border: 1px white solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #101317;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
import styles from '@/components/SpeakerModeModal/index.module.scss'
|
||||||
|
import { Button, message, Modal, Select, Slider } from 'antd';
|
||||||
|
import { useState, useImperativeHandle, forwardRef } from "react";
|
||||||
|
import { storage } from '@/utils';
|
||||||
|
interface Props {
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
const SpeakerModeModal = forwardRef((props: any, ref: any) => {
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
changeSpeakerMode: () => {
|
||||||
|
setIsSpeakerModeModal(true)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
const [isSpeakerModeModal, setIsSpeakerModeModal] = useState(false);
|
||||||
|
const setMode = (mode: string): void => {
|
||||||
|
storage.setItem('meetingMode', mode)
|
||||||
|
setIsSpeakerModeModal(false)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal
|
||||||
|
title="演讲者模式"
|
||||||
|
open={isSpeakerModeModal}
|
||||||
|
footer={null}
|
||||||
|
onCancel={() => setIsSpeakerModeModal(false)}
|
||||||
|
centered
|
||||||
|
width={'30vw'}
|
||||||
|
>
|
||||||
|
<div className={styles.speakerModeModal}>
|
||||||
|
<FreedomMode onClick={() => setMode('FreedomMode')} />
|
||||||
|
<StandardMode onClick={() => setMode('StandardMode')} />
|
||||||
|
<SpeakerMode onClick={() => setMode('SpeakerMode')} />
|
||||||
|
<SingleScreenMode onClick={() => setMode('SingleScreenMode')} />
|
||||||
|
<DualScreenMode onClick={() => setMode('DualScreenMode')} />
|
||||||
|
<FourScreenMode onClick={() => setMode('FourScreenMode')} />
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const FreedomMode: React.FC<Props> = ({ onClick }) => {
|
||||||
|
// 自由者模式
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.freedomMode} onClick={onClick}>
|
||||||
|
<div>
|
||||||
|
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16].map(item => <div key={item}></div>)}
|
||||||
|
</div>
|
||||||
|
<span>自由者模式</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const StandardMode: React.FC<Props> = ({ onClick }) => {
|
||||||
|
// 标准模式
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.standardMode} onClick={onClick}>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<span>标准模式</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const SpeakerMode: React.FC<Props> = ({ onClick }) => {
|
||||||
|
// 演讲者模式
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.speakerMode} onClick={onClick}>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<span>演讲者模式</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const SingleScreenMode: React.FC<Props> = ({ onClick }) => {
|
||||||
|
// 单画面模式
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.singleScreenMode} onClick={onClick}>
|
||||||
|
<div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<span>单画面模式</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const DualScreenMode: React.FC<Props> = ({ onClick }) => {
|
||||||
|
// 二分屏模式
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.dualScreenMode} onClick={onClick}>
|
||||||
|
<div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<span>二分屏模式</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const FourScreenMode: React.FC<Props> = ({ onClick }) => {
|
||||||
|
// 四分屏模式
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.fourScreenMode} onClick={onClick}>
|
||||||
|
<div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<span>四分屏模式</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SpeakerModeModal
|
||||||
|
|
@ -1,3 +1,63 @@
|
||||||
|
@mixin meetingContent () {
|
||||||
|
.meetingContentUser {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.meetingContentUserRole {
|
||||||
|
background: #FDC229;
|
||||||
|
border-radius: 6px;
|
||||||
|
width: 44px;
|
||||||
|
height: 34px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.meetingContentUserName {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #0000009E;
|
||||||
|
border-radius: 6px;
|
||||||
|
height: 34px;
|
||||||
|
padding: 0 4px;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
width: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>span {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #EEEEEE;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.meetingContentError {
|
||||||
|
position: absolute;
|
||||||
|
justify-content: center;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.meeting {
|
.meeting {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -84,129 +144,132 @@
|
||||||
|
|
||||||
.meetingContentBody {
|
.meetingContentBody {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
.meetingContentBodyLeft {
|
.meetingContentBodyLeft {
|
||||||
height: 100%;
|
|
||||||
width: 0px;
|
width: 0px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
height: 100%;
|
||||||
flex-direction: column;
|
|
||||||
padding-bottom: 18px;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
.meetingContentSwiper {
|
// 自由者模式
|
||||||
margin: 20px 0 12px;
|
.meetingContentBodyLeftFreedomMode {
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
overflow-x: scroll;
|
|
||||||
padding: 0 20px;
|
|
||||||
|
|
||||||
.meetingContentSwiperCard {
|
|
||||||
height: 196px;
|
|
||||||
width: 280px;
|
|
||||||
border-radius: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-right: 20px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
.meetingContentSwiperCardVdeio {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: black;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.meetingContentSwiperCardVdeioLoading {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.active {
|
|
||||||
border: 1px white solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meetingContentVideo {
|
|
||||||
flex-grow: 1;
|
|
||||||
position: relative;
|
|
||||||
width: 1378px;
|
|
||||||
margin: 0 auto;
|
|
||||||
height: 0px;
|
|
||||||
|
|
||||||
.meetingContentVideoDom {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meetingContentUser {
|
|
||||||
position: absolute;
|
|
||||||
left: 10px;
|
|
||||||
bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 2;
|
|
||||||
|
|
||||||
.meetingContentUserRole {
|
|
||||||
background: #FDC229;
|
|
||||||
border-radius: 6px;
|
|
||||||
width: 44px;
|
|
||||||
height: 34px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 6px;
|
|
||||||
|
|
||||||
>img {
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meetingContentUserName {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background-color: #0000009E;
|
|
||||||
border-radius: 6px;
|
|
||||||
height: 34px;
|
|
||||||
padding: 0 4px;
|
|
||||||
|
|
||||||
>img {
|
|
||||||
width: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
>span {
|
|
||||||
color: #EEEEEE;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.meetingContentError {
|
|
||||||
position: absolute;
|
|
||||||
justify-content: center;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 1;
|
display: flex;
|
||||||
background-color: black;
|
flex-wrap: wrap;
|
||||||
color: white;
|
overflow-y: auto;
|
||||||
font-size: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 标准模式
|
||||||
|
.meetingContentBodyLeftStandardMode {
|
||||||
|
display: flex;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 演讲者模式
|
||||||
|
.meetingContentBodyLeftSpeakerMode {
|
||||||
|
width: 25%;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.meetingContentSwiperCard {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单画面模式
|
||||||
|
.meetingContentBodyLeftSingleScreenMode {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.meetingContentSwiperCard {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 二分屏模式
|
||||||
|
.meetingContentBodyLeftDualScreenMode {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.meetingContentSwiperCard {
|
||||||
|
width: 50% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 四分屏模式
|
||||||
|
.meetingContentBodyLeftFourScreenMode {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.meetingContentSwiperCard {
|
||||||
|
width: 50% !important;
|
||||||
|
height: 50% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标准模式视频
|
||||||
|
.meetingContentSwiperCardStandardMode {
|
||||||
|
position: absolute !important;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: calc(100% - 300px) !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 演讲者模式视频
|
||||||
|
.meetingContentSwiperCardSpeakerMode {
|
||||||
|
position: absolute !important;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 100% !important;
|
||||||
|
width: calc(100% - 25%) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meetingContentSwiperCard {
|
||||||
|
height: 300px;
|
||||||
|
width: calc(100% / 4);
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.meetingContentSwiperCardVdeio {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
background: black;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.meetingContentSwiperCardVdeioLoading {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 26px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include meetingContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
.meetingContentBodyRight {
|
.meetingContentBodyRight {
|
||||||
|
|
@ -231,7 +294,7 @@
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
color: #EEEEEE;
|
color: #EEEEEE;
|
||||||
font-size: 20px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
>img {
|
>img {
|
||||||
|
|
@ -256,14 +319,14 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
font-size: 14px;
|
font-size: 20px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
width: 36px;
|
width: 40px;
|
||||||
height: 36px;
|
height: 40px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
|
|
@ -280,7 +343,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
>img {
|
>img {
|
||||||
width: 17px;
|
width: 28px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -331,7 +394,7 @@
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
color: #EEEEEE;
|
color: #EEEEEE;
|
||||||
font-size: 20px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
>img {
|
>img {
|
||||||
|
|
@ -357,14 +420,14 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
font-size: 14px;
|
font-size: 20px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
width: 36px;
|
width: 40px;
|
||||||
height: 36px;
|
height: 40px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
|
|
@ -384,6 +447,7 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 0 25px 25px 25px;
|
border-radius: 0 25px 25px 25px;
|
||||||
margin: 10px 0 10px 40px;
|
margin: 10px 0 10px 40px;
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,14 +462,14 @@
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
|
|
||||||
>span {
|
>span {
|
||||||
font-size: 14px;
|
font-size: 20px;
|
||||||
color: #F3F3F5;
|
color: #F3F3F5;
|
||||||
}
|
}
|
||||||
|
|
||||||
>div {
|
>div {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
width: 36px;
|
width: 40px;
|
||||||
height: 36px;
|
height: 40px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
|
|
@ -425,6 +489,7 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 25px 0 25px 25px;
|
border-radius: 25px 0 25px 25px;
|
||||||
margin: 10px 40px 10px 0;
|
margin: 10px 40px 10px 0;
|
||||||
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import styles from '@/page/Meeting/index.module.scss'
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import Operation from '@/components/Operation';
|
import Operation from '@/components/Operation';
|
||||||
import { Button, Input, Popover, Modal, Checkbox, message, Table, Pagination } from "antd";
|
import { Button, Input, Popover, Modal, Checkbox, message, Table, Pagination } from "antd";
|
||||||
import { DeleteOutlined, LoadingOutlined, 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';
|
||||||
|
|
@ -11,6 +11,7 @@ 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 StupWizard from '@/components/StupWizard';
|
||||||
|
import SpeakerModeModal from '@/components/SpeakerModeModal';
|
||||||
import { onInvoke, onSignalr } from '@/utils/package/signalr';
|
import { onInvoke, onSignalr } from '@/utils/package/signalr';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import durationPlugin from 'dayjs/plugin/duration';
|
import durationPlugin from 'dayjs/plugin/duration';
|
||||||
|
|
@ -21,6 +22,7 @@ const Meeting: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { state } = useLocation();
|
const { state } = useLocation();
|
||||||
const stupWizardRef = useRef<any>();
|
const stupWizardRef = useRef<any>();
|
||||||
|
const speakerModeModalRef = useRef<any>();
|
||||||
const [statusList, setStatusList] = useState({
|
const [statusList, setStatusList] = useState({
|
||||||
userList: false,
|
userList: false,
|
||||||
userChatList: false,
|
userChatList: false,
|
||||||
|
|
@ -112,10 +114,13 @@ const Meeting: React.FC = () => {
|
||||||
let [currentSeconds, setCurrentSeconds] = useState(0)
|
let [currentSeconds, setCurrentSeconds] = useState(0)
|
||||||
const [currentEffective, setCurrentEffective] = useState(0)
|
const [currentEffective, setCurrentEffective] = useState(0)
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
const [meetingMode, setMeetingMode] = useState('')
|
||||||
|
const [list] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let time = null as any;
|
let time = null as any;
|
||||||
if (isInit) {
|
if (isInit) {
|
||||||
let userInfo = JSON.parse(storage.getItem('user') as string)
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
|
setMeetingMode(storage.getItem('meetingMode') as string || 'FreedomMode');
|
||||||
agora.init()
|
agora.init()
|
||||||
agora.setCameraCapture(VideoSourceType.VideoSourceCameraPrimary)
|
agora.setCameraCapture(VideoSourceType.VideoSourceCameraPrimary)
|
||||||
agora.setJoinChannel({
|
agora.setJoinChannel({
|
||||||
|
|
@ -309,7 +314,6 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取共享文件列表
|
// 获取共享文件列表
|
||||||
const getRoomFile = async (): Promise<void> => {
|
const getRoomFile = async (): Promise<void> => {
|
||||||
await GetRoomFile({
|
await GetRoomFile({
|
||||||
|
|
@ -332,7 +336,6 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取房间用户
|
// 获取房间用户
|
||||||
const getRoomUser = async (): Promise<void> => {
|
const getRoomUser = async (): Promise<void> => {
|
||||||
await GetRoomUser(state.channelId).then(res => {
|
await GetRoomUser(state.channelId).then(res => {
|
||||||
|
|
@ -341,25 +344,30 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCustomStorageChange = async (e: any): Promise<void> => {
|
const handleCustomStorageChange = async (e: any): Promise<void> => {
|
||||||
if (e.key === 'isJoin') {
|
switch (e.key) {
|
||||||
if (e.value) {
|
case 'isJoin':
|
||||||
await onInvoke('joinChannel', {
|
if (e.value) {
|
||||||
roomNum: state.channelId,
|
await onInvoke('joinChannel', {
|
||||||
enableMicr: true,
|
roomNum: state.channelId,
|
||||||
enableCamera: true
|
enableMicr: true,
|
||||||
})
|
enableCamera: true
|
||||||
getRoomUser()
|
})
|
||||||
} else {
|
getRoomUser()
|
||||||
onInvoke('levelChannel', {
|
} else {
|
||||||
roomNum: state.channelId
|
onInvoke('levelChannel', {
|
||||||
})
|
roomNum: state.channelId
|
||||||
}
|
})
|
||||||
} else if (e.key === 'isRemotJoin') {
|
}
|
||||||
setTimeout(() => {
|
break;
|
||||||
getRoomUser()
|
case 'isRemotJoin':
|
||||||
}, 1000)
|
setTimeout(() => {
|
||||||
|
getRoomUser()
|
||||||
|
}, 1000)
|
||||||
|
break;
|
||||||
|
case 'meetingMode':
|
||||||
|
setMeetingMode(e.value)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// 聊天发送
|
// 聊天发送
|
||||||
|
|
@ -379,7 +387,6 @@ const Meeting: React.FC = () => {
|
||||||
message.success('请输入内容!')
|
message.success('请输入内容!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开关麦克风
|
// 开关麦克风
|
||||||
const postOpenMicr = async (enableMicr: boolean, isAll?: boolean): Promise<void> => {
|
const postOpenMicr = async (enableMicr: boolean, isAll?: boolean): Promise<void> => {
|
||||||
await PostOpenMicr({
|
await PostOpenMicr({
|
||||||
|
|
@ -397,6 +404,58 @@ const Meeting: React.FC = () => {
|
||||||
enableCamera
|
enableCamera
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 演讲者模式
|
||||||
|
const changeSpeakerMode = (): void => {
|
||||||
|
speakerModeModalRef.current.changeSpeakerMode()
|
||||||
|
}
|
||||||
|
// 获取当前模式样式
|
||||||
|
const getMeetingContentBodyLeftModeClass = (): string => {
|
||||||
|
switch (meetingMode) {
|
||||||
|
case 'FreedomMode':
|
||||||
|
return styles.meetingContentBodyLeftFreedomMode
|
||||||
|
case 'StandardMode':
|
||||||
|
return styles.meetingContentBodyLeftStandardMode
|
||||||
|
case 'SpeakerMode':
|
||||||
|
return styles.meetingContentBodyLeftSpeakerMode
|
||||||
|
case 'SingleScreenMode':
|
||||||
|
return styles.meetingContentBodyLeftSingleScreenMode
|
||||||
|
case 'DualScreenMode':
|
||||||
|
return styles.meetingContentBodyLeftDualScreenMode
|
||||||
|
case 'FourScreenMode':
|
||||||
|
return styles.meetingContentBodyLeftFourScreenMode
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
// 获取当前模式文字
|
||||||
|
const getMeetingContentBodyLeftModeText = (): string => {
|
||||||
|
switch (meetingMode) {
|
||||||
|
case 'FreedomMode':
|
||||||
|
return '自由者模式'
|
||||||
|
case 'StandardMode':
|
||||||
|
return '标准模式'
|
||||||
|
case 'SpeakerMode':
|
||||||
|
return '演讲者模式'
|
||||||
|
case 'SingleScreenMode':
|
||||||
|
return '单画面模式'
|
||||||
|
case 'DualScreenMode':
|
||||||
|
return '二分屏模式'
|
||||||
|
case 'FourScreenMode':
|
||||||
|
return '四分屏模式'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
// 设置单个视频样式
|
||||||
|
const setMeetingContentSwiperCardClass = (account: string): string => {
|
||||||
|
if (currentVideoId === account && (meetingMode === 'StandardMode' || meetingMode === 'SpeakerMode')) {
|
||||||
|
switch (meetingMode) {
|
||||||
|
case 'StandardMode':
|
||||||
|
return styles.meetingContentSwiperCardStandardMode
|
||||||
|
case 'SpeakerMode':
|
||||||
|
return styles.meetingContentSwiperCardSpeakerMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.meeting}>
|
<div className={styles.meeting}>
|
||||||
|
|
@ -412,17 +471,17 @@ const Meeting: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
<div>会议号:{state.channelId}</div>
|
<div>会议号:{state.channelId}</div>
|
||||||
<div className='drag'>
|
<div className='drag'>
|
||||||
<div className={styles.meetingGrayButton}>演讲者模式</div>
|
<div className={styles.meetingGrayButton} onClick={changeSpeakerMode}>{getMeetingContentBodyLeftModeText()}</div>
|
||||||
<Operation></Operation>
|
<Operation></Operation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.meetingContent}>
|
<div className={styles.meetingContent}>
|
||||||
<div className={styles.meetingContentBody}>
|
<div className={styles.meetingContentBody}>
|
||||||
<div className={styles.meetingContentBodyLeft}>
|
<div className={`${styles.meetingContentBodyLeft} drag`}>
|
||||||
<div className={`${styles.meetingContentSwiper} drag`}>
|
<div className={getMeetingContentBodyLeftModeClass()} >
|
||||||
{roomUserList.map((item: any, index: number) =>
|
{roomUserList.map((item: any, index: number) =>
|
||||||
<div
|
<div
|
||||||
className={`${styles.meetingContentSwiperCard} ${item.account === currentVideoId ? styles.active : ''}`}
|
className={`${styles.meetingContentSwiperCard} ${setMeetingContentSwiperCardClass(item.account)}`}
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentVideoId(item.account)
|
setCurrentVideoId(item.account)
|
||||||
|
|
@ -430,17 +489,22 @@ const Meeting: React.FC = () => {
|
||||||
>
|
>
|
||||||
<div className={styles.meetingContentSwiperCardVdeio} id={`video-${item.account}`}>
|
<div className={styles.meetingContentSwiperCardVdeio} id={`video-${item.account}`}>
|
||||||
<div className={styles.meetingContentSwiperCardVdeioLoading}>
|
<div className={styles.meetingContentSwiperCardVdeioLoading}>
|
||||||
<LoadingOutlined style={{ color: 'white', fontSize: '30px' }} />
|
暂无视频
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{meetingContentUser(item)}
|
{meetingContentUser(item)}
|
||||||
{item.enableCamera ? null : meetingContentError()}
|
{item.enableCamera ? null : meetingContentError()}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
{list.map(item =>
|
||||||
<div className={`${styles.meetingContentVideo} drag`}>
|
<div className={styles.meetingContentSwiperCard} key={item}>
|
||||||
<div className={styles.meetingContentVideoDom}></div>
|
<div className={styles.meetingContentSwiperCardVdeio}>
|
||||||
{/* {meetingContentUser()} */}
|
<div className={styles.meetingContentSwiperCardVdeioLoading}>
|
||||||
|
暂无视频
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
|
|
@ -748,6 +812,7 @@ const Meeting: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<SpeakerModeModal ref={speakerModeModalRef} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,6 @@ const agora = {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 停止录制音视频
|
// 停止录制音视频
|
||||||
stopRecording: () => {
|
stopRecording: () => {
|
||||||
iMediaRecorder.stopRecording()
|
iMediaRecorder.stopRecording()
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ img {
|
||||||
|
|
||||||
/* 修改垂直滚动条 */
|
/* 修改垂直滚动条 */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue