295 lines
14 KiB
TypeScript
295 lines
14 KiB
TypeScript
import { GetRoomUser } from '@/api/Meeting';
|
|
import { role } from '@/config/role';
|
|
import styles from '@/page/Meeting/ShareScreenWindow/index.module.scss'
|
|
import { storage } from '@/utils';
|
|
import ImageUrl from '@/utils/package/imageUrl';
|
|
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
|
|
import { RtcStats } from 'agora-electron-sdk';
|
|
import { Button } from 'antd';
|
|
import dayjs from 'dayjs';
|
|
import { useEffect, useState } from "react";
|
|
const { setInterval, clearInterval } = require('timers');
|
|
const ShareScreenWindow: React.FC = () => {
|
|
const [footerLists, setFooterLists] = useState<any>([
|
|
{
|
|
title: '静音',
|
|
icon: ImageUrl.icon22,
|
|
iconActive: ImageUrl.icon22Active,
|
|
active: false,
|
|
select: false,
|
|
},
|
|
{
|
|
title: '关闭视频',
|
|
icon: ImageUrl.icon23,
|
|
iconActive: ImageUrl.icon23Active,
|
|
active: false,
|
|
select: false,
|
|
},
|
|
{
|
|
title: '成员',
|
|
icon: ImageUrl.icon30,
|
|
iconSelect: ImageUrl.icon30Select,
|
|
active: false,
|
|
select: false,
|
|
},
|
|
{
|
|
title: '聊天',
|
|
icon: ImageUrl.icon31,
|
|
iconSelect: ImageUrl.icon31Select,
|
|
active: false,
|
|
select: false,
|
|
},
|
|
{
|
|
title: '录制',
|
|
icon: ImageUrl.icon27,
|
|
iconSelect: ImageUrl.icon27Select,
|
|
iconActive: ImageUrl.icon27Active,
|
|
active: false,
|
|
select: false,
|
|
},
|
|
])
|
|
const [timeStr, setTimeStr] = useState(0)
|
|
const [isExpand, setIsExpand] = useState(false)
|
|
const [roomUserLists, setRoomUserLists] = useState<any>([])
|
|
const [currentEffective, setCurrentEffective] = useState(3)
|
|
const [networkOther, setNetworkOther] = useState<RtcStats>({})
|
|
const [networkQuality, setNetworkQuality] = useState({
|
|
level: '佳',
|
|
text: '网络质量极好'
|
|
})
|
|
const channel = new BroadcastChannel('meeting_channel');
|
|
const userInfo = JSON.parse(storage.getItem('user') as string)
|
|
let timeout: NodeJS.Timeout;
|
|
useEffect(() => {
|
|
getRoomUser()
|
|
if (!role.ID.includes(userInfo.roleId)) {
|
|
setFooterLists((res: any) => {
|
|
return res.splice(4, 1)
|
|
})
|
|
}
|
|
channel.onmessage = function (event) {
|
|
let { type, time } = event.data;
|
|
switch (type) {
|
|
case 'time':
|
|
setTimeStr(time)
|
|
timeout = setInterval(() => {
|
|
setTimeStr(time++)
|
|
}, 1000)
|
|
break;
|
|
}
|
|
}
|
|
channel.postMessage({
|
|
type: 'shareScreenWindowGetTime'
|
|
});
|
|
window.electron.windowHandleMessageCallBack((_e: any, data: any) => {
|
|
switch (data.parmes.type) {
|
|
case 'currentSpeakUserMe':
|
|
let domMe = document.getElementById(`micr-item-${userInfo.uid}`) as HTMLDivElement;
|
|
if (domMe) {
|
|
domMe.style.height = `${data.parmes.currentSpeakUserMe}%`
|
|
}
|
|
break;
|
|
case 'footerList':
|
|
const footerListTemplate = [...footerLists];
|
|
footerListTemplate[0].title = data.parmes.footerList[0][0].active ? '解除静音' : '静音';
|
|
footerListTemplate[0].active = data.parmes.footerList[0][0].active;
|
|
footerListTemplate[1].title = data.parmes.footerList[0][1].active ? '开启视频' : '关闭视频';
|
|
footerListTemplate[1].active = data.parmes.footerList[0][1].active;
|
|
if (role.ID.includes(userInfo.roleId)) {
|
|
footerListTemplate[4].title = data.parmes.footerList[1][3].active ? '录制中' : '录制';
|
|
footerListTemplate[4].active = data.parmes.footerList[1][3].active;
|
|
}
|
|
setFooterLists(footerListTemplate)
|
|
break;
|
|
case 'roomUserList':
|
|
setRoomUserLists(data.parmes.roomUserList)
|
|
break;
|
|
case 'nnetworkStatus':
|
|
setCurrentEffective(data.parmes.currentEffective)
|
|
setNetworkQuality(data.parmes.networkQuality)
|
|
setNetworkOther(data.parmes.networkOther)
|
|
break;
|
|
}
|
|
})
|
|
return () => {
|
|
clearInterval(timeout)
|
|
channel.close();
|
|
};
|
|
}, []);
|
|
const changeCurrentSeconds = (time: number): string => {
|
|
const duration = dayjs.duration(time, 'seconds');
|
|
const hours = duration.hours(); // 整数小时
|
|
const minutes = duration.minutes(); // 整数分钟
|
|
const secondsRemaining = duration.seconds(); // 剩余的秒数
|
|
return `${hours > 9 ? hours : '0' + hours}:${minutes > 9 ? minutes : '0' + minutes}:${secondsRemaining > 9 ? secondsRemaining : '0' + secondsRemaining}`
|
|
}
|
|
// 获取房间用户
|
|
const getRoomUser = async (): Promise<void> => {
|
|
const data = JSON.parse(storage.getItem('stateInfo') as string)
|
|
await GetRoomUser(data.channelId).then(res => {
|
|
if (res.code === 200) {
|
|
res.data.forEach((item: any) => {
|
|
item.isShow = true;
|
|
item.isRoom = true;
|
|
item.isAdmin = role.ID.includes(item.roleId) || item.isRoomManager
|
|
})
|
|
setRoomUserLists(res.data)
|
|
channel.postMessage({
|
|
type: 'shareScreenWindowGetFooterLists',
|
|
});
|
|
}
|
|
})
|
|
}
|
|
// 底部按钮点击效果
|
|
const changeFooterListSelect = (item: any, index: number, bool: boolean): void => {
|
|
let arr = ['静音', '解除静音', '关闭视频', '开启视频']
|
|
if (arr.indexOf(item.title) === -1) {
|
|
const footerListTemplate = [...footerLists]
|
|
footerListTemplate[index].select = bool;
|
|
setFooterLists(footerListTemplate)
|
|
}
|
|
}
|
|
return (
|
|
<>
|
|
<div className={styles.shareScreenWindow} style={{ width: isExpand ? '100%' : '100%' }}>
|
|
<div className={styles.shareScreenWindowTitle}>
|
|
<span>{changeCurrentSeconds(timeStr)}
|
|
{networkIcon(currentEffective)}
|
|
<span style={{ color: 'white', marginLeft: '30px' }}>
|
|
{/* <span >网络质量:{networkQuality.level}</span> */}
|
|
<span style={{ marginRight: '6px' }}>延迟:{networkOther.lastmileDelay}ms</span>
|
|
</span>
|
|
</span>
|
|
{isExpand ? <span className='drag' style={{ flexShrink: 0 }} onClick={() => {
|
|
channel.postMessage({
|
|
type: 'shareScreenWindowClose',
|
|
shareScreenWindowClose: timeStr
|
|
});
|
|
}}>结束共享</span> : <span style={{ visibility: 'hidden', flexShrink: 0 }}>结束共享</span>}
|
|
</div>
|
|
{isExpand ? null : <div className={`${styles.shareScreenWindowContent} drag`}>
|
|
<div className={styles.shareScreenWindowContentList}>
|
|
{footerLists.map((item: any, index: number) => {
|
|
return (
|
|
<div
|
|
onMouseDown={() => changeFooterListSelect(item, index, true)}
|
|
onMouseUp={() => changeFooterListSelect(item, index, false)}
|
|
onMouseLeave={() => changeFooterListSelect(item, index, false)}
|
|
onClick={async () => {
|
|
switch (item.title) {
|
|
case '静音':
|
|
case '解除静音':
|
|
case '关闭视频':
|
|
case '开启视频':
|
|
case '录制':
|
|
case '录制中':
|
|
channel.postMessage({
|
|
type: 'shareScreenWindowfooterListsTitle',
|
|
shareScreenWindowfooterListsTitle: item.title
|
|
});
|
|
break;
|
|
case '聊天':
|
|
window.electron.setChildWindowShow({
|
|
key: 'chatBigWindow',
|
|
})
|
|
break;
|
|
case '成员':
|
|
window.electron.setChildWindowShow({
|
|
key: 'userListWindow',
|
|
})
|
|
break;
|
|
}
|
|
}}
|
|
key={index}>
|
|
<div>
|
|
{!item.active ? <div style={{ backgroundImage: `url(${ImageUrl.icon49})` }} id={`micr-item-${userInfo.uid}`}>
|
|
</div> : ''}
|
|
{item.select ? <img src={item.iconSelect} alt="" /> : <img src={item.active ? item.iconActive : item.icon} alt="" />}
|
|
</div>
|
|
<span>{item.title}{item.title === '成员' ? `(${roomUserLists.filter((item: any) => item.isRoom).length})` : ''}</span>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
<Button type="primary" style={{ backgroundColor: '#FF5219', marginRight: '14px' }} size={'small'} onClick={() => {
|
|
channel.postMessage({
|
|
type: 'shareScreenWindowClose',
|
|
shareScreenWindowClose: timeStr
|
|
});
|
|
}}>
|
|
结束共享
|
|
</Button>
|
|
</div>}
|
|
<div className={`${styles.shareScreenWindowExpand} drag`} onClick={() => {
|
|
setIsExpand(!isExpand)
|
|
window.electron.setChildWindow({
|
|
width: isExpand ? 440 : 440 / 1.6,
|
|
key: 'shareScreenWindow',
|
|
})
|
|
}}>
|
|
<span>{isExpand ? '展开' : '收起'}</span>
|
|
{isExpand ? <CaretDownOutlined /> : <CaretUpOutlined />}
|
|
</div>
|
|
</div >
|
|
</>
|
|
)
|
|
}
|
|
|
|
const networkIcon = (network: number) => {
|
|
switch (network) {
|
|
case 0:
|
|
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
<g clip-path="url(#clip0_21262_3609)">
|
|
<path d="M4.44094 32C3.03695 32 1.90039 31.15 1.90039 30.1V15.3C1.90039 14.25 3.03695 13.4 4.44094 13.4C5.84492 13.4 6.98149 14.25 6.98149 15.3V30.1C6.98149 31.15 5.84492 32 4.44094 32ZM17.01 32C15.606 32 14.4694 31.15 14.4694 30.1V8.9C14.4694 7.85 15.606 7 17.01 7C18.4139 7 19.5505 7.85 19.5505 8.9V30.1C19.5505 31.15 18.4139 32 17.01 32ZM29.579 32C28.175 32 27.0384 31.15 27.0384 30.1V1.9C27.0384 0.85 28.175 0 29.579 0C30.983 0 32.1195 0.85 32.1195 1.9V30.1C32.1195 31.15 30.983 32 29.579 32Z" fill="#7C8280" />
|
|
<path d="M7.00124 2.11509L5.01758 4.09875L3.03391 2.11509C2.77629 1.85747 2.35122 1.85747 2.0936 2.11509C1.83599 2.37271 1.83599 2.79778 2.0936 3.0554L4.07727 5.03906L2.0936 7.02273C1.83599 7.28035 1.83599 7.70542 2.0936 7.96304C2.35122 8.22065 2.77629 8.22065 3.03391 7.96304L5.01758 5.97937L7.00124 7.96304C7.25886 8.22065 7.68393 8.22065 7.94155 7.96304C8.19917 7.70542 8.19917 7.28035 7.94155 7.02273L5.95789 5.03906L7.94155 3.0554C8.19917 2.79778 8.19917 2.37271 7.94155 2.11509C7.68393 1.85747 7.25886 1.85747 7.00124 2.11509Z" fill="#F90000" />
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_21262_3609">
|
|
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
case 1:
|
|
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
<g clip-path="url(#clip0_21262_3615)">
|
|
<path d="M26.9316 30.1C26.9316 31.15 28.0918 32 29.5249 32C30.9581 32 32.1182 31.15 32.1182 30.1V1.9C32.1182 0.85 30.9581 0 29.5249 0C28.0918 0 26.9316 0.85 26.9316 1.9V30.1Z" fill="#7C8280" />
|
|
<path d="M14.1035 30.1C14.1035 31.15 15.2637 32 16.6968 32C18.1299 32 19.2901 31.15 19.2901 30.1V8.9C19.2901 7.85 18.1299 7 16.6968 7C15.2637 7 14.1035 7.85 14.1035 8.9V30.1Z" fill="#7C8280" />
|
|
<path d="M1.27344 30.1004C1.27344 31.1504 2.4336 32.0004 3.86673 32.0004C5.29986 32.0004 6.46002 31.1504 6.46002 30.1004V15.3004C6.46002 14.2504 5.29986 13.4004 3.86673 13.4004C2.4336 13.4004 1.27344 14.2504 1.27344 15.3004V30.1004Z" fill="#FF800B" />
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_21262_3615">
|
|
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
case 2:
|
|
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
<g clip-path="url(#clip0_21262_3621)">
|
|
<path d="M26.9316 30.1C26.9316 31.15 28.0918 32 29.5249 32C30.9581 32 32.1182 31.15 32.1182 30.1V1.9C32.1182 0.85 30.9581 0 29.5249 0C28.0918 0 26.9316 0.85 26.9316 1.9V30.1Z" fill="#7C8280" />
|
|
<path d="M14.1035 30.1C14.1035 31.15 15.2637 32 16.6968 32C18.1299 32 19.2901 31.15 19.2901 30.1V8.9C19.2901 7.85 18.1299 7 16.6968 7C15.2637 7 14.1035 7.85 14.1035 8.9V30.1Z" fill="#FF800B" />
|
|
<path d="M1.27344 30.1004C1.27344 31.1504 2.4336 32.0004 3.86673 32.0004C5.29986 32.0004 6.46002 31.1504 6.46002 30.1004V15.3004C6.46002 14.2504 5.29986 13.4004 3.86673 13.4004C2.4336 13.4004 1.27344 14.2504 1.27344 15.3004V30.1004Z" fill="#FF800B" />
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_21262_3621">
|
|
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
case 3:
|
|
return <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg" className='drag' style={{ transform: 'scale(0.5)', position: 'absolute', top: '-4px' }}>
|
|
<g clip-path="url(#clip0_21262_3625)">
|
|
<path d="M26.9316 30.1C26.9316 31.15 28.0918 32 29.5249 32C30.9581 32 32.1182 31.15 32.1182 30.1V1.9C32.1182 0.85 30.9581 0 29.5249 0C28.0918 0 26.9316 0.85 26.9316 1.9V30.1Z" fill="#02B188" />
|
|
<path d="M14.1035 30.1C14.1035 31.15 15.2637 32 16.6968 32C18.1299 32 19.2901 31.15 19.2901 30.1V8.9C19.2901 7.85 18.1299 7 16.6968 7C15.2637 7 14.1035 7.85 14.1035 8.9V30.1Z" fill="#02B188" />
|
|
<path d="M1.27344 30.1004C1.27344 31.1504 2.4336 32.0004 3.86673 32.0004C5.29986 32.0004 6.46002 31.1504 6.46002 30.1004V15.3004C6.46002 14.2504 5.29986 13.4004 3.86673 13.4004C2.4336 13.4004 1.27344 14.2504 1.27344 15.3004V30.1004Z" fill="#02B188" />
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_21262_3625">
|
|
<rect width="32" height="32" fill="white" transform="translate(0.119141)" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
}
|
|
}
|
|
|
|
export default ShareScreenWindow
|