import { useEffect, useRef, useState } from "react"; import '@/utils/styles/App.scss' import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import Home from '@/page/Home/index' import Index from '@/page/Home/Index/index' import User from '@/page/Home/User/index' import Login from '@/page/Login/index' import Meeting from '@/page/Meeting/index' import NotFound from '@/page/NotFound/index' import { storage } from '@/utils' import { message, Spin } from "antd"; import { onOtherSignalr, onReconnected, onStart, startSignalr } from "@/utils/package/signalr"; import JoinMeetingModal from "@/components/JoinMeetingModal"; import UpdateModal from "@/components/UpdateModal"; import * as CryptoJS from 'crypto-js'; import { PostLogin } from "@/api/Login"; import agora from "@/utils/package/agora"; import QuitTips from "@/components/QuitTips"; import { GetLeave } from "@/api/Meeting"; const fs = require('fs').promises; const { exec } = require('child_process'); const App: React.FC = () => { const navigate = useNavigate(); const { state } = useLocation(); const joinMeetingModalRef = useRef(); const updateModalRef = useRef(); const quitTipsRef = useRef(); const [_windowSize, setWindowSize] = useState({ width: window.innerWidth, height: window.innerHeight, }); const [spinning, setSpinning] = useState(false); const [isState, setIsState] = useState(true); useEffect(() => { let userInfo = JSON.parse(storage.getItem('user') as string) let loginInfo = JSON.parse(storage.getItem('login') as string) if (userInfo) { if (loginInfo && loginInfo.isAutoLogin) { PostLogin({ account: loginInfo.account, pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex) }).then(res => { if (res.code === 200) { storage.setItem('user', JSON.stringify(res.data)) startSignalr() } else { toSrc('/login') } }) } else { toSrc('/login') } } else { toSrc('/login') } if (import.meta.env.VITE_ENV !== 'development') { document.addEventListener('keydown', (event) => { if ((event.ctrlKey || event.metaKey) && event.key === 'r') { event.preventDefault(); } if (event.key === 'F11') { event.preventDefault(); } }); } window.addEventListener('resize', handleResize); window.addEventListener('online', handleNetworkChange); window.addEventListener('offline', handleNetworkChange); const originalSetItem = window.localStorage.setItem; window.localStorage.setItem = function (key, value) { originalSetItem.call(this, key, value); const event = new Event('customStorageChange') as any; event.key = key event.value = value window.dispatchEvent(event); }; window.addEventListener('customStorageChange', handleCustomStorageChange); return () => { window.removeEventListener('resize', handleResize); window.removeEventListener('customStorageChange', handleCustomStorageChange); window.removeEventListener('online', handleNetworkChange); window.removeEventListener('offline', handleNetworkChange); }; }, []); useEffect(() => { window.electron.downFile(async (_e: any, data: any) => { const response = await fetch(data.filePath); const arrayBuffer = await response.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); fs.writeFile(`${data.downFilePaths}${data.fileName}`, buffer, {}); message.success(`下载成功!文件已保存至:${data.downFilePaths}`) await fs.access(data.downFilePaths, fs.constants.F_OK); if (process.platform === 'win32') { exec(`explorer "${data.downFilePaths}"`); } else if (process.platform === 'darwin') { exec(`open "${data.downFilePaths}"`); } }) window.electron.onFilePath(async (_e: any, filePath: string, key: string) => { const setting = await JSON.parse(storage.getItem('setting') as string) if (key === 'recordingFilesPath') { setting.recordingFilesPath = filePath } else { setting.shareFilesPath = filePath } storage.setItem('setting', JSON.stringify(setting)) }) window.electron.quitAndInstall(async (_e: any) => { leaveChannel() }) }, []) useEffect(() => { onOtherSignalr(async (item: any) => { switch (item.key) { case 'Invitation': window.electron.joinNotification({ body: item.roomName, name: item.InviterName, }) joinMeetingModalRef.current.changeModal(item) break; case 'ForceLogout': message.error(item.msg) await leaveChannel() toSrc('/login') break; } }) }, []) useEffect(() => { try { if (location.hash.indexOf('/login') !== -1) { window.electron.setMainWindowSize({ width: 752, height: 520, key: 'login' }) } else { window.electron.setMainWindowSize({ width: 1200, height: 800, }) } } catch { } }, [location.hash]) useEffect(() => { onReconnected(async () => { storage.setItem('reconnect', true) }) window.electron.onUpdate((_e: any, data: any) => { if (location.hash.indexOf('/meeting') === -1) { updateModalRef.current.changeModal(data) } }) if (!storage.getItem('setting')) { storage.setItem('setting', JSON.stringify({ videoDeviceId: '', //摄像头id ecordingDeviceId: "", //输入设备id playBackDeviceId: "", //输出设备id ecordingVolume: '', //输入音量 playBackVolume: '', //输出音量 autoEcordingVolume: true, //是否自动调整麦克风音量 recordingFilesPath: '', //本地录制保存路径 shareFilesPath: '', //共享文件保存路径 isShareSavePath: true, //是否下载钱询问每个文件保存的位置 closeSetting: 'hide', //关闭按钮设置 })) } }, []) useEffect(() => { if (isState) { setIsState(false) window.electron.onQuit(async () => { if (location.hash.indexOf('/login') === 1) { window.electron.quit() } else { if (storage.getItem('isTips') === 'true') { const setting = JSON.parse(storage.getItem('setting') as string) if (setting.closeSetting === 'hide') { window.electron.setViewStatus(setting.closeSetting) } else { window.electron.quit() } } else { quitTipsRef.current.changeModal() } } }) } storage.setItem('stateInfo', JSON.stringify(state)) }, [state]) const handleResize = (): void => { setWindowSize({ width: window.innerWidth, height: window.innerHeight, }); try { window.electron.getIsMaximized().then((res: boolean) => { const dom = document.getElementById('root') as HTMLElement; dom.style.borderRadius = res ? '0px' : '10px' }) } catch { } }; const toSrc = (path: string): void => { switch (path) { case '/login': storage.removeItem('user') navigate('/login') break; case '/home': navigate('/home') break; } }; const leaveChannel = async (): Promise => { if (location.hash.indexOf('/meeting') === 1) { const data = JSON.parse(localStorage.stateInfo); await GetLeave({ roomNum: data.channelId, }) await agora.leaveChannel() } }; const handleCustomStorageChange = (e: any): void => { if (e.key === 'loading') { setSpinning(Boolean(e.value)) } }; const handleNetworkChange = (): void => { if (location.hash.indexOf('/meeting') === -1) { if (navigator.onLine) { message.success('网络已恢复。') setTimeout(async () => { await onStart() }, 1000) } else { message.error('网络已断开!') } } } return ( <> } /> }> } /> } /> } /> } /> } /> } /> ) } export default App