From 1674f227a3c6cae14a56cb5b54f664abf032f2fb Mon Sep 17 00:00:00 2001 From: yj <1336058017@qq.com> Date: Fri, 12 Jul 2024 15:31:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.js | 16 +- preload.js | 4 - src/api/Login/index.ts | 4 +- src/api/Meeting/index.ts | 6 + src/assets/icon36.png | Bin 0 -> 754 bytes src/components/StupWizard/index.module.scss | 85 +++++++ src/components/StupWizard/index.tsx | 197 ++++++++++++++++ src/page/Meeting/index.module.scss | 87 ------- src/page/Meeting/index.tsx | 243 +++++++------------- src/render.d.ts | 21 -- src/utils/package/agora.ts | 215 ++++++++++------- src/utils/package/imageUrl.ts | 2 + src/utils/package/signalr.ts | 9 +- 13 files changed, 504 insertions(+), 385 deletions(-) create mode 100644 src/assets/icon36.png create mode 100644 src/components/StupWizard/index.module.scss create mode 100644 src/components/StupWizard/index.tsx diff --git a/main.js b/main.js index 0625a47..6989ce7 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, screen, Tray, nativeImage, Menu, ipcMain, clipboard, dialog } = require('electron'); +const { app, BrowserWindow, screen, Tray, nativeImage, Menu, ipcMain, clipboard, dialog, webFrame } = require('electron'); const path = require('node:path') app.allowRendererProcessReuse = false; let mainWindow = null; @@ -136,20 +136,6 @@ app.on('ready', () => { break; } }); - // 下载文件并放置选择的文件夹 - ipcMain.handle('dwFile', (event, url) => { - dialog.showOpenDialog(mainWindow, { - properties: ['openDirectory'] - }).then(result => { - if (!result.canceled) { - const selectedPath = result.filePaths[0]; - console.log('Selected download folder:', selectedPath); - console.log(url); - } - }).catch(err => { - - }); - }); // 导出是否全屏 ipcMain.handle('getIsMaximized', () => { return mainWindow.isMaximized(); diff --git a/preload.js b/preload.js index da07739..5538ed9 100644 --- a/preload.js +++ b/preload.js @@ -16,9 +16,5 @@ window.electron = { // 复制文字 setWriteText: (text) => { return ipcRenderer.invoke('setWriteText', text) - }, - // 下载文件并放置选择的文件夹 - dwFile: (url) => { - ipcRenderer.invoke('dwFile', url) } } \ No newline at end of file diff --git a/src/api/Login/index.ts b/src/api/Login/index.ts index 91f3900..04a955b 100644 --- a/src/api/Login/index.ts +++ b/src/api/Login/index.ts @@ -1,7 +1,7 @@ import { request } from '@/utils' -export const GetCheckUser = (userName: string) => +export const GetCheckUser = (account: string) => request({ - url: `/auth/check-user?userName=${userName}`, + url: `/auth/check-user?account=${account}`, method: 'get' }) diff --git a/src/api/Meeting/index.ts b/src/api/Meeting/index.ts index 544ffb4..e62bd80 100644 --- a/src/api/Meeting/index.ts +++ b/src/api/Meeting/index.ts @@ -32,3 +32,9 @@ export const GetRoomFileDwUrl = (fileUrl: string, fileId: string) => method: 'get' }) + +export const GetRoomUser = (roomNum: string) => + request({ + url: `/room/user?roomNum=${roomNum}`, + method: 'get' + }) diff --git a/src/assets/icon36.png b/src/assets/icon36.png new file mode 100644 index 0000000000000000000000000000000000000000..5c2701df0cd0dc761eb28b5a92891c6b4f5b2cd8 GIT binary patch literal 754 zcmV9s=7=J$5{soU*tT=ozy zi>K3RrCcg45<-UWd0qt^k(>0#Z1yM+7h3BeJ%9XN80q&YdfIFKO0PZ?0Cmnd8jbwh zo138q=zs%E+@%~M;_5yOpO5Y0+>f`Ow*bTrI6?{0q5tm4*}*J|7VP}Hq$d)_2^#T@ z2Ak0}a(;f6G%I0T&}y|-f8)4{TCXiJ<;Bq2O`Y-tk^C=o!~h&X3DzZ&*HgBnrhh?_ zfOOsUFbtO}8joxA(I+zaD42x9LXK><+iktwZm&tXo@r-uN;-LuhNY7@yay?z&tV~w zig$h8=Q%pr3k@r?0I|kNRVXRPl7^+(Ux=Q~TD{-@OqLi0E0oj_0NA?pZ_4Gs%ptB1 zcDjkeN#i(P9|)8Rc*NaqonBKoDM?&#*jxxxt6Iv#9G!GiIH@R=Mm%zja(VE(6ymeB zBi%%yq^x9CRCY;hxr}J2Sw~tA4=bUrt~leIns634dnu8=(euR$Mp>zzbwmrXs(zTw2XAtkbo9P0wRWYYQi} kpg8w!X0s5m!hj?G0Ys=Bs+t644*&oF07*qoM6N<$f*`a^_y7O^ literal 0 HcmV?d00001 diff --git a/src/components/StupWizard/index.module.scss b/src/components/StupWizard/index.module.scss new file mode 100644 index 0000000..f773921 --- /dev/null +++ b/src/components/StupWizard/index.module.scss @@ -0,0 +1,85 @@ +// 设置向导 +.stupWizard { + display: flex; + flex-direction: column; + + >div:nth-child(1) { + padding: 20px 0 0; + overflow-x: hidden; + max-height: 60vh; + overflow-y: auto; + + >div:nth-child(1) { + color: #EEEEEE; + font-weight: bold; + font-size: 20px; + } + + >div:nth-child(2) { + >div { + display: flex; + align-items: center; + margin-top: 22px; + + >span { + flex-shrink: 0; + color: #828282; + font-size: 18px; + width: 130px; + } + } + } + + >div:nth-child(3) { + margin-top: 34px; + + >span { + color: #828282; + font-size: 18px; + } + + >div { + display: flex; + align-items: center; + margin-top: 20px; + + >img { + flex-shrink: 0; + width: 36px; + margin-right: 20px; + } + + >div { + flex-grow: 1; + height: 40px; + position: relative; + + >img { + height: 100%; + } + + >div { + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 0%; + overflow: hidden; + + >img { + height: 100%; + } + } + } + } + } + } + + >div:nth-child(2) { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: flex-end; + margin-top: 20px; + } +} \ No newline at end of file diff --git a/src/components/StupWizard/index.tsx b/src/components/StupWizard/index.tsx new file mode 100644 index 0000000..9ac4b59 --- /dev/null +++ b/src/components/StupWizard/index.tsx @@ -0,0 +1,197 @@ +import styles from '@/components/StupWizard/index.module.scss' +import ImageUrl from '@/utils/package/imageUrl'; +import { Button, message, Modal, Select, Slider } from 'antd'; +import { useState, useImperativeHandle, forwardRef } from "react"; +import agora from '@/utils/package/agora' +const StupWizard = forwardRef((props: any, ref: any) => { + useImperativeHandle(ref, () => ({ + changeIsStupWizard: () => { + setIsStupWizard(true) + getAudioMediaList(true) + agora.startPlaybackDeviceTest() + agora.setPlaybackDeviceVolume(100) + } + })) + const [isStupWizard, setIsStupWizard] = useState(false); + const [stepsStatus, setStepsStatus] = useState(1); + const [isVideoLoad, setIsVideoLoad] = useState(false); + const [audioDeviceManager, setAudioDeviceManager] = useState({ + currentDevices: [], + currentDevice: {}, + currentVolume: 0, + }); + // agora.startRecordingDeviceTest(200) + const getAudioMediaList = (bool: boolean): void => { + const { currentDevices, currentVolume, currentDevice } = agora.getAudioMediaList(bool); + setAudioDeviceManager({ + currentDevices: currentDevices.map((row: any) => { + return { + value: row.deviceId, + label: row.deviceName + } + }), + currentDevice: currentDevice.deviceId, + currentVolume, + }) + } + // 音频设置向导 + // 视频测试 + return ( + <> + +
+
+
音频设置向导
+
+
+ 音频输出设备: + { + setAudioDeviceManager({ + ...audioDeviceManager, + currentDevice: e + }) + agora.setRecordingDevice(e); + getAudioMediaList() + }} />; + +
+ {stepsStatus ?
+ 调节声音大小: + { + setAudioDeviceManager({ + ...audioDeviceManager, + currentVolume: e + }) + agora.setRecordingDeviceVolume(e) + }} style={{ flexGrow: 1 }} /> +
: +
+ 视频预览: + +
+ } +
+
+ 您可以对着麦克风说话,试听表克风的输入质量 +
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+
+ + +
+ +
+
*/} +
+ + ) +}) +export default StupWizard \ No newline at end of file diff --git a/src/page/Meeting/index.module.scss b/src/page/Meeting/index.module.scss index 3f213c1..177811e 100644 --- a/src/page/Meeting/index.module.scss +++ b/src/page/Meeting/index.module.scss @@ -577,93 +577,6 @@ margin-top: 20px; } } - -// 设置向导 -.stupWizard { - display: flex; - flex-direction: column; - - >div:nth-child(1) { - padding: 20px 0 0; - overflow-x: hidden; - max-height: 60vh; - overflow-y: auto; - - >div:nth-child(1) { - color: #EEEEEE; - font-weight: bold; - font-size: 20px; - } - - >div:nth-child(2) { - >div { - display: flex; - align-items: center; - margin-top: 22px; - - >span { - flex-shrink: 0; - color: #828282; - font-size: 18px; - width: 130px; - } - } - } - - >div:nth-child(3) { - margin-top: 34px; - - >span { - color: #828282; - font-size: 18px; - } - - >div { - display: flex; - align-items: center; - margin-top: 20px; - - >img { - flex-shrink: 0; - width: 36px; - margin-right: 20px; - } - - >div { - flex-grow: 1; - height: 40px; - position: relative; - - >img { - height: 100%; - } - - >div { - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 0%; - overflow: hidden; - - >img { - height: 100%; - } - } - } - } - } - } - - >div:nth-child(2) { - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: flex-end; - margin-top: 20px; - } -} - // 共享文件 .sharedFilesModel { >div:nth-child(1) { diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index 0b16456..43e1e44 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -1,24 +1,27 @@ import styles from '@/page/Meeting/index.module.scss' -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import Operation from '@/components/Operation'; import { Navigation, Pagination } from 'swiper/modules'; import { Swiper, SwiperSlide } from 'swiper/react'; import 'swiper/css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; -import { Button, Input, Popover, Modal, Checkbox, message, Select, Slider, Table, Pagination as AntdPagination } from "antd"; -import { DeleteOutlined, FolderOutlined, ProfileOutlined, ReloadOutlined, SearchOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons'; +import { Button, Input, Popover, Modal, Checkbox, message, Table, Pagination as AntdPagination } from "antd"; +import { DeleteOutlined, ProfileOutlined, ReloadOutlined, SearchOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons'; import { useLocation, useNavigate } from 'react-router-dom'; import { thumbImageBufferToBase64 } from '@/utils/package/base64' import { storage } from '@/utils'; -import { GetRoomFile, PostRoomFile, DeleteRoomFile, GetRoomUpFileurl, GetRoomFileDwUrl } from '@/api/Meeting'; +import { GetRoomFile, PostRoomFile, DeleteRoomFile, GetRoomUpFileurl, GetRoomFileDwUrl, GetRoomUser } from '@/api/Meeting'; import axios from 'axios'; import ImageUrl from '@/utils/package/imageUrl' import agora from '@/utils/package/agora' +import StupWizard from '@/components/StupWizard'; +import { onInvoke } from '@/utils/package/signalr'; const { Column } = Table const Meeting: React.FC = () => { const navigate = useNavigate(); const { state } = useLocation(); + const stupWizardRef = useRef(); const [statusList, setStatusList] = useState({ userList: false, userChatList: false, @@ -27,7 +30,6 @@ const Meeting: React.FC = () => { const [isSharedScreenModal, setIsSharedScreenModal] = useState(false); const [isInit, setIsInit] = useState(true); const [user, setUser] = useState({}); - const [isStupWizard, setIsStupWizard] = useState(false); const [showRowSelection, setShowRowSelection] = useState(false); const [isSharedFilesModel, setIsSharedFilesModel] = useState(false); const [sharedScreenList, setSharedScreenList] = useState([]); @@ -97,11 +99,6 @@ const Meeting: React.FC = () => { itemIndex: 0, rowIndex: 0, }); - const [audioDeviceManager, setAudioDeviceManager] = useState({ - currentDevices: [], - currentDevice: {}, - currentVolume: 0, - }); const [fileList, setFileList] = useState({ data: [], keyword: '', @@ -109,27 +106,31 @@ const Meeting: React.FC = () => { pageIndex: 1, pageSize: 10, }) + const [roomUserList, setRoomUserList] = useState([]) - const [stepsStatus, setStepsStatus] = useState(true); - const [isVideoLoad, setIsVideoLoad] = useState(false); const [list] = useState([1, 2, 3, 4, 5, 6, 7]) const [open, setOpen] = useState(false) - const [videoID, setVideoID] = useState('') - useEffect(() => { if (isInit) { - setUser(JSON.parse(storage.getItem('user') as string)) - // agora.setJoinChannel({ - // channelId: state.channelId, - // userid: user.userName, - // token: state.token, - // }) + let userInfo = JSON.parse(storage.getItem('user') as string) + agora.init() + agora.setJoinChannel({ + channelId: state.channelId, + userid: userInfo.account, + token: state.token, + }) + setUser(userInfo) setIsInit(false) + window.addEventListener('customStorageChange', handleCustomStorageChange); } else { getRoomFile() } + return () => { + window.removeEventListener('customStorageChange', handleCustomStorageChange); + }; }, [fileList.pageIndex]); + // 操作按钮 const changeStatusList = async (row: any, itemIndex: number, rowIndex: number): Promise => { const footerListTemplate = [...footerList] setFooterListIndex({ @@ -182,9 +183,7 @@ const Meeting: React.FC = () => { agora.muteLocalVideoStream(false) break; case '设置向导': - getAudioMediaList() - agora.startRecordingDeviceTest(200) - setIsStupWizard(true) + stupWizardRef.current.changeIsStupWizard() break; case '录制': footerListTemplate[itemIndex][rowIndex].title = '录制中' @@ -205,23 +204,19 @@ const Meeting: React.FC = () => { } } - const changeVdeio = async (bool: boolean): Promise => { - if (bool) { - + // 分享屏幕 + const clickSharedScreen = async (): Promise => { + let data = sharedScreenList.find((item: any) => item.sourceId === sharedScreenItem.sourceId) + if (data) { + const footerListTemplate = [...footerList] + footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享' + setIsSharedScreenModal(false) + agora.setDesktopCapturerVideo(sharedScreenItem) } else { - let data = sharedScreenList.find((item: any) => item.sourceId === sharedScreenItem.sourceId) - if (data) { - const footerListTemplate = [...footerList] - footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享' - setIsSharedScreenModal(false) - agora.setDesktopCapturerVideo(sharedScreenItem) - setVideoID(agora.getVideoId()) - } else { - message.error('请选择应用!') - } + message.error('请选择应用!') } } - + // 获取桌面可共享屏幕的引用 const getDesktopCapturerVideo = (): void => { agora.getDesktopCapturerVideo().then((res: any) => { if (sharedScreenList.length !== res.length) { @@ -238,20 +233,7 @@ const Meeting: React.FC = () => { }) }; - const getAudioMediaList = (): void => { - const { currentDevices, currentDevice, currentVolume } = agora.getAudioMediaList(); - setAudioDeviceManager({ - currentDevices: currentDevices.map((row: any) => { - return { - value: row.deviceId, - label: row.deviceName - } - }), - currentDevice: currentDevice.deviceId, - currentVolume, - }) - } - + // 获取共享文件列表 const getRoomFile = async (): Promise => { await GetRoomFile({ pageIndex: fileList.pageIndex, @@ -274,6 +256,33 @@ const Meeting: React.FC = () => { }) } + // 获取房间用户 + const getRoomUser = async (): Promise => { + await GetRoomUser(state.channelId).then(res => { + if (res.code === 200) { + setRoomUserList(res.data) + setTimeout(() => { + res.data.forEach((item: any) => { + agora.setVideo(Number(item.account), document.getElementById(`video-${item.account}`), state.channelId) + }) + }, 1000) + } + }) + } + const handleCustomStorageChange = (e: any): void => { + if (e.key === 'isJoin') { + if (e.value) { + onInvoke('joinChannel', { + roomNum: state.channelId + }) + getRoomUser() + } else { + onInvoke('levelChannel', { + roomNum: state.channelId + }) + } + } + }; return ( <>
@@ -287,7 +296,7 @@ const Meeting: React.FC = () => {
00:13:45
-
会议号:2323235
+
会议号:{state.channelId}
演讲者模式
@@ -313,11 +322,11 @@ const Meeting: React.FC = () => { }} onSlideChange={() => { }} > - {list.map((item, index) => - + {roomUserList.map((item: any, index: number) => +
-
- {meetingContentUser()} +
+ {meetingContentUser(item)}
)} @@ -325,7 +334,7 @@ const Meeting: React.FC = () => {
- {meetingContentUser()} + {/* {meetingContentUser()} */}
{ @@ -463,114 +472,12 @@ const Meeting: React.FC = () => { }}>共享电脑音频
- +
- -
-
-
{stepsStatus ? '音频设置向导' : '视频测试'}
-
-
- 音频输出设备: -