diff --git a/main.js b/main.js index 4609203..0f04457 100644 --- a/main.js +++ b/main.js @@ -17,6 +17,7 @@ const { autoUpdater, CancellationToken } = require('electron-updater'); const cancellationToken = new CancellationToken() app.allowRendererProcessReuse = false; let mainWindow = null; +let childWindow = {} let isMaximized = false; let env; let regKey; @@ -299,6 +300,30 @@ app.on('ready', () => { }) }); }); + // 创建子窗口 + ipcMain.handle('createChildWindow', (event, config) => { + const child = new BrowserWindow({ + parent: mainWindow, + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + enableRemoteModule: true, + nodeIntegrationInWorker: true, + allowMediaDevices: true, + preload: path.join(__dirname, 'preload.js') + }, + show: false, + frame: false, + backgroundColor: '#00000000', + transparent: true, + }) + child.loadURL(config.url) + childWindow[config.key] = child + child.once('ready-to-show', () => { + child.show() + child.setSize(config.width, config.height) + }) + }); } }); // 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写 diff --git a/preload.js b/preload.js index 51c897d..adecf8a 100644 --- a/preload.js +++ b/preload.js @@ -73,4 +73,8 @@ window.electron = { setRegistry: (uuid) => { ipcRenderer.invoke('setRegistry', uuid) }, + // 创建子窗口 + createChildWindow: (config) => { + ipcRenderer.invoke('createChildWindow', config) + }, } diff --git a/src/App.tsx b/src/App.tsx index 3c752f3..c6d6195 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,6 +18,7 @@ import { agora } from "@/utils/package/agora"; import QuitTips from "@/components/QuitTips"; import { GetLeave } from "@/api/Meeting"; import path from "path"; +import ShareScreenWindow from "./page/ShareScreenWindow"; const fs = require('fs').promises; const { exec } = require('child_process'); const App: React.FC = () => { @@ -32,122 +33,124 @@ const App: React.FC = () => { }); 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 && Number(userInfo.perms)) { - if (loginInfo && loginInfo.isAutoLogin) { - PostLogin({ - account: loginInfo.account, - pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex) - }).then(async (res) => { - if (res.code === 200) { - storage.setItem('user', JSON.stringify(res.data)) - storage.setItem('userLogin', true) - toSrc('/home') - await startSignalr() - } else { - toSrc('/login') - } - }) + if (location.hash.indexOf('shareScreenWindow') == -1) { + useEffect(() => { + let userInfo = JSON.parse(storage.getItem('user') as string) + let loginInfo = JSON.parse(storage.getItem('login') as string) + if (userInfo && !userInfo.isAnonymous) { + if (loginInfo && loginInfo.isAutoLogin) { + PostLogin({ + account: loginInfo.account, + pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex) + }).then(async (res) => { + if (res.code === 200) { + storage.setItem('user', JSON.stringify(res.data)) + storage.setItem('userLogin', true) + toSrc('/home') + await startSignalr() + } else { + toSrc('/login') + } + }) + } else { + toSrc('/login') + } } else { toSrc('/login') } - } else { - toSrc('/login') - } - window.addEventListener('resize', handleResize); - 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); - }; - }, []); - 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(() => { - 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: path.resolve(__dirname, '../../Downloads') + '\\', //本地录制保存路径 - shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径 - isShareSavePath: true, //是否下载钱询问每个文件保存的位置 - closeSetting: 'hide', //关闭按钮设置 - isAINoiseReduction: true, //是否开启ai降噪 - aINoiseReduction: 1, // 降噪模式 - })) - } - }, []) - 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() - } + window.addEventListener('resize', handleResize); + 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); + }; + }, []); + 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}"`); } }) - } - storage.setItem('stateInfo', JSON.stringify(state)) - }, [state]) - useEffect(() => { - if (location.href.indexOf('/login') !== -1) { - onStop() - } - }, [navigate]) + 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(() => { + 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: path.resolve(__dirname, '../../Downloads') + '\\', //本地录制保存路径 + shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径 + isShareSavePath: true, //是否下载钱询问每个文件保存的位置 + closeSetting: 'hide', //关闭按钮设置 + isAINoiseReduction: true, //是否开启ai降噪 + aINoiseReduction: 1, // 降噪模式 + })) + } + }, []) + 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]) + useEffect(() => { + if (location.href.indexOf('/login') !== -1) { + onStop() + } + }, [navigate]) + } useEffect(() => { document.addEventListener('keydown', (event) => { if (event.key === 'F11') { @@ -239,6 +242,7 @@ const App: React.FC = () => { } /> } /> + } /> } /> diff --git a/src/api/Home/Index/index.ts b/src/api/Home/Index/index.ts index 4316481..bcb47e7 100644 --- a/src/api/Home/Index/index.ts +++ b/src/api/Home/Index/index.ts @@ -11,6 +11,12 @@ export const PostRoom = (data: any) => method: 'post', data, }) +export const PostRoomInfo = (data: any) => + request({ + url: `/home/room-info`, + method: 'put', + data, + }) export const DeleteRoom = (roomId: string) => request({ url: `/home/room?roomId=${roomId}`, diff --git a/src/api/Home/User/index.ts b/src/api/Home/User/index.ts index a2d9028..0a3b33c 100644 --- a/src/api/Home/User/index.ts +++ b/src/api/Home/User/index.ts @@ -19,6 +19,13 @@ export const PutUser = (data: any) => method: 'put', data }) + +export const PutUserBth = (data: any) => + request({ + url: `/user/bth`, + method: 'put', + data + }) export const DeleteUser = (data: any) => request({ url: `/user`, @@ -33,6 +40,12 @@ export const PutUserPwd = (data: { id: string, pwd: string }) => data }) +export const GetSubDpList = () => + request({ + url: `/pub/sub-dp-list`, + method: 'get', + }) + export const GetRoleDpList = () => request({ url: `/pub/role-dp-list`, diff --git a/src/components/InvitingPersonnelModal/index.tsx b/src/components/InvitingPersonnelModal/index.tsx index 8e55c81..ee8b83f 100644 --- a/src/components/InvitingPersonnelModal/index.tsx +++ b/src/components/InvitingPersonnelModal/index.tsx @@ -158,7 +158,7 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { ) : 暂无数据} - { + { setList({ ...list, pageIndex: e diff --git a/src/components/SharedFilesModel/index.tsx b/src/components/SharedFilesModel/index.tsx index 7288ff1..4ce71d2 100644 --- a/src/components/SharedFilesModel/index.tsx +++ b/src/components/SharedFilesModel/index.tsx @@ -341,7 +341,7 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => { ...fileList, pageIndex: e }) - }} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} /> + }} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} showSizeChanger={false}/> diff --git a/src/main.tsx b/src/main.tsx index 2931b2a..9d1d257 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -3,7 +3,7 @@ import App from './App.tsx' import '@/utils/styles/main.css' import { HashRouter } from 'react-router-dom'; import { ConfigProvider } from 'antd'; -import zhCN from 'antd/locale/zh_CN'; +import zhCN from 'antd/es/locale/zh_CN'; import 'animate.css'; ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/src/page/Home/Index/index.tsx b/src/page/Home/Index/index.tsx index 349390b..38a0415 100644 --- a/src/page/Home/Index/index.tsx +++ b/src/page/Home/Index/index.tsx @@ -1,8 +1,8 @@ import styles from '@/page/Home/Index/index.module.scss' import { useEffect, useState, useRef } from "react"; import Operation from '@/components/Operation'; -import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker } from "antd"; -import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord } from '@/api/Home/Index'; +import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker, Select } from "antd"; +import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord, PostRoomInfo } from '@/api/Home/Index'; import ImageUrl from '@/utils/package/imageUrl' import { ExclamationCircleFilled, ReloadOutlined } from '@ant-design/icons'; import JoinSetting from '@/components/JoinSetting'; @@ -12,6 +12,7 @@ import { useNavigate } from 'react-router-dom'; import { role } from '@/config/role'; import dayjs from 'dayjs'; import StupWizard from '@/components/StupWizard'; +import { GetSubDpList } from '@/api/Home/User'; const fs = require('fs').promises; const { exec } = require('child_process'); const { RangePicker } = DatePicker; @@ -26,15 +27,20 @@ const Index: React.FC = () => { }) const [createRoomModal, setCreateRoomModal] = useState(false) const [timeSelectModal, setTimeSelectModal] = useState(false) - const [createRoomFrom, setCreateRoomFrom] = useState<{ roomName: string, roomNum: string }>({ + const [createRoomFrom, setCreateRoomFrom] = useState<{ id: string, roomName: string, roomNum: string, subject: string, year: string }>({ + id: "", roomName: "", - roomNum: "" + roomNum: "", + subject: "", + year: "" }) const joinSettingRef = useRef(); const stupWizardRef = useRef(); const [user, setUser] = useState({}); const [currentRoomInfo, setCurrentRoomInfo] = useState({}); + const [subjectList, setSubjectList] = useState([]); const [timeData, setTimeData] = useState([]); + const [isCreateRoom, setIsCreateRoom] = useState(false); const userInfo = JSON.parse(storage.getItem('user') as string) useEffect(() => { setUser(userInfo) @@ -62,7 +68,12 @@ const Index: React.FC = () => { setList({ ...list, total: res.data.total, - data: res.data.items, + data: res.data.items.map((item: any) => { + return { + ...item, + open: false + } + }), }) } }) @@ -80,6 +91,13 @@ const Index: React.FC = () => { } }) } + const getSubDpList = async (): Promise => { + await GetSubDpList().then(res => { + if (res.code === 200) { + setSubjectList(res.data.map((item: any) => { return { value: item.value, label: item.name } })) + } + }) + } const getRoomRtcToken = async (roomNum: string, callBack: Function): Promise => { Promise.all([GetRoomRtcToken(roomNum), GetRoomRtcToken(roomNum + 'a')]).then(res => { if (res[0].code === 200 && res[1].code === 200) { @@ -166,8 +184,13 @@ const Index: React.FC = () => { onClick={() => { setCreateRoomFrom({ roomName: "", - roomNum: "" + roomNum: "", + subject: "", + year: "", + id: "", }) + getSubDpList() + setIsCreateRoom(true) setCreateRoomModal(true) }} style={{ marginRight: '22px' }} @@ -234,13 +257,26 @@ const Index: React.FC = () => { okText="确定" cancelText="取消" > -
删除会议室
+
删除会议室
: null} -
{ +
{ changeOpen(index, false) setTimeSelectModal(true) }}>导出参会记录
-
{ +
{ + changeOpen(index, false) + setCreateRoomFrom({ + roomName: item.roomName, + roomNum: item.roomNum, + subject: item.subject, + year: item.year, + id: item.id, + }) + getSubDpList() + setIsCreateRoom(false) + setCreateRoomModal(true) + }}>修改设置
+
{ changeOpen(index, false) }}>取消
@@ -298,19 +334,19 @@ const Index: React.FC = () => {
}
- { + { setList({ ...list, pageIndex: e }) - }} pageSize={list.pageSize} /> + }} pageSize={list.pageSize} showSizeChanger={false} />
- +
- { >获取随机房间号 } - /> + /> : null} { }) }} autoSize /> + { + const regex = /^[0-9]*$/; + if (regex.test(e.target.value)) { + setCreateRoomFrom({ + ...createRoomFrom, + year: e.target.value + }) + } + }} + /> + { }); }} /> -
+
: null}
角色: { }); }} /> +
: null} +
+ 届: + { + const regex = /^[0-9]*$/; + if (regex.test(e.target.value)) { + setAddUserFrom({ + ...addUserFrom, + year: e.target.value + }); + } + }} + /> +
+
+ 学科: +