Compare commits
15 Commits
4cd47addfe
...
8f2f93d0a4
| Author | SHA1 | Date |
|---|---|---|
|
|
8f2f93d0a4 | |
|
|
f710ae42c8 | |
|
|
5381a47293 | |
|
|
c7d6f90174 | |
|
|
ffe669d901 | |
|
|
d3420c98ce | |
|
|
4026b79deb | |
|
|
61558b0d90 | |
|
|
e96528870c | |
|
|
6e85e5e3e7 | |
|
|
8ce430ac4d | |
|
|
55e0bbec39 | |
|
|
d12620a945 | |
|
|
39968c3a70 | |
|
|
269bdd023c |
25
main.js
25
main.js
|
|
@ -17,6 +17,7 @@ const { autoUpdater, CancellationToken } = require('electron-updater');
|
||||||
const cancellationToken = new CancellationToken()
|
const cancellationToken = new CancellationToken()
|
||||||
app.allowRendererProcessReuse = false;
|
app.allowRendererProcessReuse = false;
|
||||||
let mainWindow = null;
|
let mainWindow = null;
|
||||||
|
let childWindow = {}
|
||||||
let isMaximized = false;
|
let isMaximized = false;
|
||||||
let env;
|
let env;
|
||||||
let regKey;
|
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事件触发后的操作自行编写
|
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
||||||
|
|
|
||||||
|
|
@ -73,4 +73,8 @@ window.electron = {
|
||||||
setRegistry: (uuid) => {
|
setRegistry: (uuid) => {
|
||||||
ipcRenderer.invoke('setRegistry', uuid)
|
ipcRenderer.invoke('setRegistry', uuid)
|
||||||
},
|
},
|
||||||
|
// 创建子窗口
|
||||||
|
createChildWindow: (config) => {
|
||||||
|
ipcRenderer.invoke('createChildWindow', config)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
226
src/App.tsx
226
src/App.tsx
|
|
@ -18,6 +18,7 @@ import { agora } from "@/utils/package/agora";
|
||||||
import QuitTips from "@/components/QuitTips";
|
import QuitTips from "@/components/QuitTips";
|
||||||
import { GetLeave } from "@/api/Meeting";
|
import { GetLeave } from "@/api/Meeting";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import ShareScreenWindow from "./page/ShareScreenWindow";
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
@ -32,122 +33,124 @@ const App: React.FC = () => {
|
||||||
});
|
});
|
||||||
const [spinning, setSpinning] = useState(false);
|
const [spinning, setSpinning] = useState(false);
|
||||||
const [isState, setIsState] = useState(true);
|
const [isState, setIsState] = useState(true);
|
||||||
useEffect(() => {
|
if (location.hash.indexOf('shareScreenWindow') == -1) {
|
||||||
let userInfo = JSON.parse(storage.getItem('user') as string)
|
useEffect(() => {
|
||||||
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
if (userInfo && Number(userInfo.perms)) {
|
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
||||||
if (loginInfo && loginInfo.isAutoLogin) {
|
if (userInfo && !userInfo.isAnonymous) {
|
||||||
PostLogin({
|
if (loginInfo && loginInfo.isAutoLogin) {
|
||||||
account: loginInfo.account,
|
PostLogin({
|
||||||
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
account: loginInfo.account,
|
||||||
}).then(async (res) => {
|
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
||||||
if (res.code === 200) {
|
}).then(async (res) => {
|
||||||
storage.setItem('user', JSON.stringify(res.data))
|
if (res.code === 200) {
|
||||||
storage.setItem('userLogin', true)
|
storage.setItem('user', JSON.stringify(res.data))
|
||||||
toSrc('/home')
|
storage.setItem('userLogin', true)
|
||||||
await startSignalr()
|
toSrc('/home')
|
||||||
} else {
|
await startSignalr()
|
||||||
toSrc('/login')
|
} else {
|
||||||
}
|
toSrc('/login')
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
toSrc('/login')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
toSrc('/login')
|
toSrc('/login')
|
||||||
}
|
}
|
||||||
} else {
|
window.addEventListener('resize', handleResize);
|
||||||
toSrc('/login')
|
const originalSetItem = window.localStorage.setItem;
|
||||||
}
|
window.localStorage.setItem = function (key, value) {
|
||||||
window.addEventListener('resize', handleResize);
|
originalSetItem.call(this, key, value);
|
||||||
const originalSetItem = window.localStorage.setItem;
|
const event = new Event('customStorageChange') as any;
|
||||||
window.localStorage.setItem = function (key, value) {
|
event.key = key
|
||||||
originalSetItem.call(this, key, value);
|
event.value = value
|
||||||
const event = new Event('customStorageChange') as any;
|
window.dispatchEvent(event);
|
||||||
event.key = key
|
};
|
||||||
event.value = value
|
window.addEventListener('customStorageChange', handleCustomStorageChange);
|
||||||
window.dispatchEvent(event);
|
return () => {
|
||||||
};
|
window.removeEventListener('resize', handleResize);
|
||||||
window.addEventListener('customStorageChange', handleCustomStorageChange);
|
window.removeEventListener('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);
|
||||||
useEffect(() => {
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
window.electron.downFile(async (_e: any, data: any) => {
|
const buffer = Buffer.from(arrayBuffer);
|
||||||
const response = await fetch(data.filePath);
|
fs.writeFile(`${data.downFilePaths}${data.fileName}`, buffer, {});
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
message.success(`下载成功!文件已保存至:${data.downFilePaths}`)
|
||||||
const buffer = Buffer.from(arrayBuffer);
|
await fs.access(data.downFilePaths, fs.constants.F_OK);
|
||||||
fs.writeFile(`${data.downFilePaths}${data.fileName}`, buffer, {});
|
if (process.platform === 'win32') {
|
||||||
message.success(`下载成功!文件已保存至:${data.downFilePaths}`)
|
exec(`explorer "${data.downFilePaths}"`);
|
||||||
await fs.access(data.downFilePaths, fs.constants.F_OK);
|
} else if (process.platform === 'darwin') {
|
||||||
if (process.platform === 'win32') {
|
exec(`open "${data.downFilePaths}"`);
|
||||||
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.electron.onFilePath(async (_e: any, filePath: string, key: string) => {
|
||||||
storage.setItem('stateInfo', JSON.stringify(state))
|
const setting = await JSON.parse(storage.getItem('setting') as string)
|
||||||
}, [state])
|
if (key === 'recordingFilesPath') {
|
||||||
useEffect(() => {
|
setting.recordingFilesPath = filePath
|
||||||
if (location.href.indexOf('/login') !== -1) {
|
} else {
|
||||||
onStop()
|
setting.shareFilesPath = filePath
|
||||||
}
|
}
|
||||||
}, [navigate])
|
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(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('keydown', (event) => {
|
document.addEventListener('keydown', (event) => {
|
||||||
if (event.key === 'F11') {
|
if (event.key === 'F11') {
|
||||||
|
|
@ -239,6 +242,7 @@ const App: React.FC = () => {
|
||||||
</Route>
|
</Route>
|
||||||
<Route path='/login' element={<Login />} />
|
<Route path='/login' element={<Login />} />
|
||||||
<Route path='/meeting' element={<Meeting />} />
|
<Route path='/meeting' element={<Meeting />} />
|
||||||
|
<Route path='/shareScreenWindow' element={<ShareScreenWindow />} />
|
||||||
<Route path='*' element={<NotFound />} />
|
<Route path='*' element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
<Spin spinning={spinning} fullscreen />
|
<Spin spinning={spinning} fullscreen />
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@ export const PostRoom = (data: any) =>
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
|
export const PostRoomInfo = (data: any) =>
|
||||||
|
request({
|
||||||
|
url: `/home/room-info`,
|
||||||
|
method: 'put',
|
||||||
|
data,
|
||||||
|
})
|
||||||
export const DeleteRoom = (roomId: string) =>
|
export const DeleteRoom = (roomId: string) =>
|
||||||
request({
|
request({
|
||||||
url: `/home/room?roomId=${roomId}`,
|
url: `/home/room?roomId=${roomId}`,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,13 @@ export const PutUser = (data: any) =>
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const PutUserBth = (data: any) =>
|
||||||
|
request({
|
||||||
|
url: `/user/bth`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
export const DeleteUser = (data: any) =>
|
export const DeleteUser = (data: any) =>
|
||||||
request({
|
request({
|
||||||
url: `/user`,
|
url: `/user`,
|
||||||
|
|
@ -33,6 +40,12 @@ export const PutUserPwd = (data: { id: string, pwd: string }) =>
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const GetSubDpList = () =>
|
||||||
|
request({
|
||||||
|
url: `/pub/sub-dp-list`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
|
||||||
export const GetRoleDpList = () =>
|
export const GetRoleDpList = () =>
|
||||||
request({
|
request({
|
||||||
url: `/pub/role-dp-list`,
|
url: `/pub/role-dp-list`,
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => {
|
||||||
</div>
|
</div>
|
||||||
</div>) : <span style={{ display: 'block', textAlign: 'center', color: 'white', padding: '30px 0' }}>暂无数据</span>}
|
</div>) : <span style={{ display: 'block', textAlign: 'center', color: 'white', padding: '30px 0' }}>暂无数据</span>}
|
||||||
</div>
|
</div>
|
||||||
<Pagination size="small" total={list.total} style={{ flexShrink: 0, margin: '10px 0 0' }} onChange={(e) => {
|
<Pagination size="small" total={list.total} showSizeChanger={false} style={{ flexShrink: 0, margin: '10px 0 0' }} onChange={(e) => {
|
||||||
setList({
|
setList({
|
||||||
...list,
|
...list,
|
||||||
pageIndex: e
|
pageIndex: e
|
||||||
|
|
|
||||||
|
|
@ -341,7 +341,7 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
...fileList,
|
...fileList,
|
||||||
pageIndex: e
|
pageIndex: e
|
||||||
})
|
})
|
||||||
}} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} />
|
}} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} showSizeChanger={false}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import App from './App.tsx'
|
||||||
import '@/utils/styles/main.css'
|
import '@/utils/styles/main.css'
|
||||||
import { HashRouter } from 'react-router-dom';
|
import { HashRouter } from 'react-router-dom';
|
||||||
import { ConfigProvider } from 'antd';
|
import { ConfigProvider } from 'antd';
|
||||||
import zhCN from 'antd/locale/zh_CN';
|
import zhCN from 'antd/es/locale/zh_CN';
|
||||||
import 'animate.css';
|
import 'animate.css';
|
||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import styles from '@/page/Home/Index/index.module.scss'
|
import styles from '@/page/Home/Index/index.module.scss'
|
||||||
import { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import Operation from '@/components/Operation';
|
import Operation from '@/components/Operation';
|
||||||
import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker } from "antd";
|
import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker, Select } from "antd";
|
||||||
import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord } from '@/api/Home/Index';
|
import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord, PostRoomInfo } from '@/api/Home/Index';
|
||||||
import ImageUrl from '@/utils/package/imageUrl'
|
import ImageUrl from '@/utils/package/imageUrl'
|
||||||
import { ExclamationCircleFilled, ReloadOutlined } from '@ant-design/icons';
|
import { ExclamationCircleFilled, ReloadOutlined } from '@ant-design/icons';
|
||||||
import JoinSetting from '@/components/JoinSetting';
|
import JoinSetting from '@/components/JoinSetting';
|
||||||
|
|
@ -12,6 +12,7 @@ import { useNavigate } from 'react-router-dom';
|
||||||
import { role } from '@/config/role';
|
import { role } from '@/config/role';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import StupWizard from '@/components/StupWizard';
|
import StupWizard from '@/components/StupWizard';
|
||||||
|
import { GetSubDpList } from '@/api/Home/User';
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
|
|
@ -26,15 +27,20 @@ const Index: React.FC = () => {
|
||||||
})
|
})
|
||||||
const [createRoomModal, setCreateRoomModal] = useState(false)
|
const [createRoomModal, setCreateRoomModal] = useState(false)
|
||||||
const [timeSelectModal, setTimeSelectModal] = 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: "",
|
roomName: "",
|
||||||
roomNum: ""
|
roomNum: "",
|
||||||
|
subject: "",
|
||||||
|
year: ""
|
||||||
})
|
})
|
||||||
const joinSettingRef = useRef<any>();
|
const joinSettingRef = useRef<any>();
|
||||||
const stupWizardRef = useRef<any>();
|
const stupWizardRef = useRef<any>();
|
||||||
const [user, setUser] = useState<any>({});
|
const [user, setUser] = useState<any>({});
|
||||||
const [currentRoomInfo, setCurrentRoomInfo] = useState<any>({});
|
const [currentRoomInfo, setCurrentRoomInfo] = useState<any>({});
|
||||||
|
const [subjectList, setSubjectList] = useState<any>([]);
|
||||||
const [timeData, setTimeData] = useState<any>([]);
|
const [timeData, setTimeData] = useState<any>([]);
|
||||||
|
const [isCreateRoom, setIsCreateRoom] = useState<boolean>(false);
|
||||||
const userInfo = JSON.parse(storage.getItem('user') as string)
|
const userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUser(userInfo)
|
setUser(userInfo)
|
||||||
|
|
@ -62,7 +68,12 @@ const Index: React.FC = () => {
|
||||||
setList({
|
setList({
|
||||||
...list,
|
...list,
|
||||||
total: res.data.total,
|
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<void> => {
|
||||||
|
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<void> => {
|
const getRoomRtcToken = async (roomNum: string, callBack: Function): Promise<void> => {
|
||||||
Promise.all([GetRoomRtcToken(roomNum), GetRoomRtcToken(roomNum + 'a')]).then(res => {
|
Promise.all([GetRoomRtcToken(roomNum), GetRoomRtcToken(roomNum + 'a')]).then(res => {
|
||||||
if (res[0].code === 200 && res[1].code === 200) {
|
if (res[0].code === 200 && res[1].code === 200) {
|
||||||
|
|
@ -166,8 +184,13 @@ const Index: React.FC = () => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCreateRoomFrom({
|
setCreateRoomFrom({
|
||||||
roomName: "",
|
roomName: "",
|
||||||
roomNum: ""
|
roomNum: "",
|
||||||
|
subject: "",
|
||||||
|
year: "",
|
||||||
|
id: "",
|
||||||
})
|
})
|
||||||
|
getSubDpList()
|
||||||
|
setIsCreateRoom(true)
|
||||||
setCreateRoomModal(true)
|
setCreateRoomModal(true)
|
||||||
}}
|
}}
|
||||||
style={{ marginRight: '22px' }}
|
style={{ marginRight: '22px' }}
|
||||||
|
|
@ -234,13 +257,26 @@ const Index: React.FC = () => {
|
||||||
okText="确定"
|
okText="确定"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
>
|
>
|
||||||
<div>删除会议室</div>
|
<div className='meetingContentFooterPopoverDel'>删除会议室</div>
|
||||||
</Popconfirm> : null}
|
</Popconfirm> : null}
|
||||||
<div onClick={() => {
|
<div className='meetingContentFooterPopoverDefault' onClick={() => {
|
||||||
changeOpen(index, false)
|
changeOpen(index, false)
|
||||||
setTimeSelectModal(true)
|
setTimeSelectModal(true)
|
||||||
}}>导出参会记录</div>
|
}}>导出参会记录</div>
|
||||||
<div onClick={() => {
|
<div className='meetingContentFooterPopoverDefault' onClick={() => {
|
||||||
|
changeOpen(index, false)
|
||||||
|
setCreateRoomFrom({
|
||||||
|
roomName: item.roomName,
|
||||||
|
roomNum: item.roomNum,
|
||||||
|
subject: item.subject,
|
||||||
|
year: item.year,
|
||||||
|
id: item.id,
|
||||||
|
})
|
||||||
|
getSubDpList()
|
||||||
|
setIsCreateRoom(false)
|
||||||
|
setCreateRoomModal(true)
|
||||||
|
}}>修改设置</div>
|
||||||
|
<div className='meetingContentFooterPopoverCancel' onClick={() => {
|
||||||
changeOpen(index, false)
|
changeOpen(index, false)
|
||||||
}}>取消</div>
|
}}>取消</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -298,19 +334,19 @@ const Index: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className={styles.indexContentPagination}>
|
<div className={styles.indexContentPagination}>
|
||||||
<Pagination size="small" total={list.total} onChange={(e) => {
|
<Pagination size="small" total={list.total} onChange={(e: number) => {
|
||||||
setList({
|
setList({
|
||||||
...list,
|
...list,
|
||||||
pageIndex: e
|
pageIndex: e
|
||||||
})
|
})
|
||||||
}} pageSize={list.pageSize} />
|
}} pageSize={list.pageSize} showSizeChanger={false} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal title="新建会议室" open={createRoomModal} footer={null} closable={false} centered width={'400px'}>
|
<Modal title={isCreateRoom ? '新建会议室' : '修改会议信息'} open={createRoomModal} footer={null} closable={false} centered width={'400px'}>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<Input
|
{isCreateRoom ? <Input
|
||||||
placeholder="请输入房间号"
|
placeholder="请输入房间号"
|
||||||
style={{ marginBottom: '14px' }}
|
style={{ marginBottom: '14px' }}
|
||||||
className={styles.letterSpacing}
|
className={styles.letterSpacing}
|
||||||
|
|
@ -344,7 +380,7 @@ const Index: React.FC = () => {
|
||||||
>获取随机房间号
|
>获取随机房间号
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/> : null}
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
placeholder="请输入房间名字"
|
placeholder="请输入房间名字"
|
||||||
style={{ marginBottom: '14px' }}
|
style={{ marginBottom: '14px' }}
|
||||||
|
|
@ -358,6 +394,30 @@ const Index: React.FC = () => {
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
autoSize />
|
autoSize />
|
||||||
|
<Input
|
||||||
|
placeholder="请输入届"
|
||||||
|
style={{ marginBottom: '14px' }}
|
||||||
|
value={createRoomFrom.year}
|
||||||
|
onChange={(e) => {
|
||||||
|
const regex = /^[0-9]*$/;
|
||||||
|
if (regex.test(e.target.value)) {
|
||||||
|
setCreateRoomFrom({
|
||||||
|
...createRoomFrom,
|
||||||
|
year: e.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
placeholder='请选择学科'
|
||||||
|
style={{ width: '100%', marginBottom: '14px' }}
|
||||||
|
options={subjectList}
|
||||||
|
value={createRoomFrom.subject === "" ? null : createRoomFrom.subject} onChange={(e) => {
|
||||||
|
setCreateRoomFrom({
|
||||||
|
...createRoomFrom,
|
||||||
|
subject: e
|
||||||
|
})
|
||||||
|
}} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex', justifyContent: 'center'
|
display: 'flex', justifyContent: 'center'
|
||||||
|
|
@ -370,20 +430,36 @@ const Index: React.FC = () => {
|
||||||
if (!createRoomFrom.roomNum) {
|
if (!createRoomFrom.roomNum) {
|
||||||
return message.error('请输入房间号!')
|
return message.error('请输入房间号!')
|
||||||
}
|
}
|
||||||
isGetCheckoutRoomNum(createRoomFrom.roomNum, (bool: boolean) => {
|
if (!createRoomFrom.year) {
|
||||||
if (bool) {
|
return message.error('请输入届!')
|
||||||
message.error('房间号已存在!')
|
}
|
||||||
} else {
|
if (createRoomFrom.subject === "") {
|
||||||
PostRoom(createRoomFrom).then(res => {
|
return message.error('请选择学科!')
|
||||||
if (res.code === 200) {
|
}
|
||||||
message.success('创建成功!')
|
if (isCreateRoom) {
|
||||||
setCreateRoomModal(false)
|
isGetCheckoutRoomNum(createRoomFrom.roomNum, (bool: boolean) => {
|
||||||
getRoomList()
|
if (bool) {
|
||||||
}
|
message.error('房间号已存在!')
|
||||||
})
|
} else {
|
||||||
}
|
PostRoom(createRoomFrom).then(res => {
|
||||||
})
|
if (res.code === 200) {
|
||||||
}}>创建</Button>
|
message.success('创建成功!')
|
||||||
|
setCreateRoomModal(false)
|
||||||
|
getRoomList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
PostRoomInfo(createRoomFrom).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
message.success('更新成功!')
|
||||||
|
setCreateRoomModal(false)
|
||||||
|
getRoomList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}}>{isCreateRoom ? '创建' : '更新'}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useEffect, useState, useRef } from "react";
|
||||||
import Operation from '@/components/Operation';
|
import Operation from '@/components/Operation';
|
||||||
import { Button, Input, Table, Pagination, Modal, message, Select } from "antd";
|
import { Button, Input, Table, Pagination, Modal, message, Select } from "antd";
|
||||||
import { ExclamationCircleFilled, SearchOutlined } from '@ant-design/icons';
|
import { ExclamationCircleFilled, SearchOutlined } from '@ant-design/icons';
|
||||||
import { GetUserList, PostUser, PutUser, DeleteUser, PutUserPwd, GetRoleDpList, PostUserImport } from '@/api/Home/User';
|
import { GetUserList, PostUser, PutUser, DeleteUser, PutUserPwd, GetRoleDpList, PostUserImport, GetSubDpList, PutUserBth } from '@/api/Home/User';
|
||||||
import * as CryptoJS from 'crypto-js';
|
import * as CryptoJS from 'crypto-js';
|
||||||
import ImageUrl from '@/utils/package/imageUrl';
|
import ImageUrl from '@/utils/package/imageUrl';
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
|
|
@ -15,7 +15,7 @@ const fs = require('fs').promises;
|
||||||
const User: React.FC = () => {
|
const User: React.FC = () => {
|
||||||
const stupWizardRef = useRef<any>();
|
const stupWizardRef = useRef<any>();
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
const [isCreateUser, setIsCreateUser] = useState(false);
|
const [isCreateUser, setIsCreateUser] = useState<'add' | 'batch' | 'edit'>();
|
||||||
const [list, setList] = useState({
|
const [list, setList] = useState({
|
||||||
data: [],
|
data: [],
|
||||||
searchKeywod: '',
|
searchKeywod: '',
|
||||||
|
|
@ -30,7 +30,9 @@ const User: React.FC = () => {
|
||||||
Account: "",
|
Account: "",
|
||||||
RoleId: null,
|
RoleId: null,
|
||||||
Pwd: "",
|
Pwd: "",
|
||||||
UserName: ""
|
UserName: "",
|
||||||
|
subject: null,
|
||||||
|
year: "",
|
||||||
})
|
})
|
||||||
const [changeUserPawModal, setChangeUserPawModal] = useState(false)
|
const [changeUserPawModal, setChangeUserPawModal] = useState(false)
|
||||||
const [changeImportModal, setChangeImportModal] = useState(false)
|
const [changeImportModal, setChangeImportModal] = useState(false)
|
||||||
|
|
@ -39,10 +41,14 @@ const User: React.FC = () => {
|
||||||
newPwd: '',
|
newPwd: '',
|
||||||
})
|
})
|
||||||
const [deleteUserPawModal, setDeleteUserPawModal] = useState(false)
|
const [deleteUserPawModal, setDeleteUserPawModal] = useState(false)
|
||||||
|
const [subjectList, setSubjectList] = useState<any>([]);
|
||||||
|
useEffect(() => {
|
||||||
|
getSubDpList()
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getUserList()
|
getUserList()
|
||||||
}, [list.pageIndex]);
|
}, [list.pageIndex, list.pageSize]);
|
||||||
|
|
||||||
const getUserList = async (): Promise<void> => {
|
const getUserList = async (): Promise<void> => {
|
||||||
await GetUserList({
|
await GetUserList({
|
||||||
|
|
@ -61,6 +67,7 @@ const User: React.FC = () => {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
setSelectedRowKeys([])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +125,13 @@ const User: React.FC = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const getSubDpList = async (): Promise<void> => {
|
||||||
|
await GetSubDpList().then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
setSubjectList(res.data.map((item: any) => { return { value: item.value, label: item.name } }))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={styles.user}>
|
<div className={styles.user}>
|
||||||
|
|
@ -131,13 +144,15 @@ const User: React.FC = () => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
getRoleDpList((bool: boolean) => {
|
getRoleDpList((bool: boolean) => {
|
||||||
if (bool) {
|
if (bool) {
|
||||||
setIsCreateUser(true)
|
setIsCreateUser('add')
|
||||||
setAddUserFrom({
|
setAddUserFrom({
|
||||||
Id: "",
|
Id: "",
|
||||||
Account: "",
|
Account: "",
|
||||||
RoleId: null,
|
RoleId: null,
|
||||||
Pwd: "",
|
Pwd: "",
|
||||||
UserName: "",
|
UserName: "",
|
||||||
|
subject: null,
|
||||||
|
year: "",
|
||||||
})
|
})
|
||||||
setAddUserModal(true)
|
setAddUserModal(true)
|
||||||
}
|
}
|
||||||
|
|
@ -154,6 +169,31 @@ const User: React.FC = () => {
|
||||||
className='m-ant-btn'>
|
className='m-ant-btn'>
|
||||||
批量导入用户
|
批量导入用户
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
if (selectedRowKeys.length) {
|
||||||
|
getRoleDpList((bool: boolean) => {
|
||||||
|
if (bool) {
|
||||||
|
setIsCreateUser('batch')
|
||||||
|
setAddUserFrom({
|
||||||
|
Id: "",
|
||||||
|
Account: "",
|
||||||
|
RoleId: null,
|
||||||
|
Pwd: "",
|
||||||
|
UserName: "",
|
||||||
|
subject: null,
|
||||||
|
year: "",
|
||||||
|
})
|
||||||
|
setAddUserModal(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
message.error('请选择需要修改的用户!')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className='m-ant-btn'>
|
||||||
|
批量修改用户信息
|
||||||
|
</Button>
|
||||||
<Button type="primary"
|
<Button type="primary"
|
||||||
icon={<img src={ImageUrl.icon21} alt="" />}
|
icon={<img src={ImageUrl.icon21} alt="" />}
|
||||||
className={styles.userBtnsDel}
|
className={styles.userBtnsDel}
|
||||||
|
|
@ -161,7 +201,7 @@ const User: React.FC = () => {
|
||||||
if (selectedRowKeys.length) {
|
if (selectedRowKeys.length) {
|
||||||
setDeleteUserPawModal(true)
|
setDeleteUserPawModal(true)
|
||||||
} else {
|
} else {
|
||||||
message.error('请选择要删除的用户')
|
message.error('请选择需要删除的用户!')
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -214,7 +254,13 @@ const User: React.FC = () => {
|
||||||
<div style={{ color: item.isOnline ? '#02B188' : 'rgb(221 11 11)' }}>{item.isOnline ? '在线' : '离线'}</div>
|
<div style={{ color: item.isOnline ? '#02B188' : 'rgb(221 11 11)' }}>{item.isOnline ? '在线' : '离线'}</div>
|
||||||
</>
|
</>
|
||||||
)} />
|
)} />
|
||||||
<Column title="操作" render={(item) => (
|
<Column title="届" dataIndex="year" key="year" />
|
||||||
|
<Column title="学科" render={(item) => (
|
||||||
|
<>
|
||||||
|
<div>{subjectList.find((subject: any) => subject.value === item.subject)?.label}</div>
|
||||||
|
</>
|
||||||
|
)} />
|
||||||
|
<Column title="操作" width={200} render={(item) => (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|
@ -223,13 +269,15 @@ const User: React.FC = () => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
getRoleDpList((bool: boolean) => {
|
getRoleDpList((bool: boolean) => {
|
||||||
if (bool) {
|
if (bool) {
|
||||||
setIsCreateUser(false)
|
setIsCreateUser('edit')
|
||||||
setAddUserFrom({
|
setAddUserFrom({
|
||||||
...addUserFrom,
|
...addUserFrom,
|
||||||
Id: item.id,
|
Id: item.id,
|
||||||
Account: item.account,
|
Account: item.account,
|
||||||
RoleId: item.roleId,
|
RoleId: item.roleId,
|
||||||
UserName: item.userName,
|
UserName: item.userName,
|
||||||
|
subject: item.subject,
|
||||||
|
year: item.year,
|
||||||
})
|
})
|
||||||
setAddUserModal(true)
|
setAddUserModal(true)
|
||||||
}
|
}
|
||||||
|
|
@ -258,19 +306,20 @@ const User: React.FC = () => {
|
||||||
</Table>
|
</Table>
|
||||||
<div className={styles.userContentPagination}>
|
<div className={styles.userContentPagination}>
|
||||||
<span>共{list.total}项数据</span>
|
<span>共{list.total}项数据</span>
|
||||||
<Pagination size="small" total={list.total} onChange={(e) => {
|
<Pagination size="small" total={list.total} onChange={(page, pageSize) => {
|
||||||
setList({
|
setList({
|
||||||
...list,
|
...list,
|
||||||
pageIndex: e
|
pageIndex: page,
|
||||||
|
pageSize: pageSize
|
||||||
})
|
})
|
||||||
}} pageSize={list.pageSize} current={list.pageIndex} hideOnSinglePage={true} />
|
}} showSizeChanger pageSizeOptions={[10, 14, 20, 30, 40, 50, 100]} pageSize={list.pageSize} current={list.pageIndex} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal title={isCreateUser ? '添加用户' : '编辑用户'} open={addUserModal} footer={null} closable={false} centered width={'500px'}>
|
<Modal title={isCreateUser === 'add' ? '添加用户' : isCreateUser === 'edit' ? '编辑用户' : '批量修改用户信息'} open={addUserModal} footer={null} closable={false} centered width={'500px'}>
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.addUserModal}>
|
<div className={styles.addUserModal}>
|
||||||
<div>
|
{isCreateUser !== 'batch' ? <div>
|
||||||
<span>账号:</span>
|
<span>账号:</span>
|
||||||
<Input
|
<Input
|
||||||
style={{ flexGrow: 1 }}
|
style={{ flexGrow: 1 }}
|
||||||
|
|
@ -285,7 +334,7 @@ const User: React.FC = () => {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> : null}
|
||||||
<div>
|
<div>
|
||||||
<span>角色:</span>
|
<span>角色:</span>
|
||||||
<Select
|
<Select
|
||||||
|
|
@ -299,7 +348,7 @@ const User: React.FC = () => {
|
||||||
});
|
});
|
||||||
}} />;
|
}} />;
|
||||||
</div>
|
</div>
|
||||||
{isCreateUser ? <div>
|
{isCreateUser === 'add' ? <div>
|
||||||
<span>密码:</span>
|
<span>密码:</span>
|
||||||
<Input.Password
|
<Input.Password
|
||||||
placeholder="请输入密码"
|
placeholder="请输入密码"
|
||||||
|
|
@ -313,7 +362,7 @@ const User: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div> : null}
|
</div> : null}
|
||||||
<div>
|
{isCreateUser !== 'batch' ? <div>
|
||||||
<span>用户名称:</span>
|
<span>用户名称:</span>
|
||||||
<Input
|
<Input
|
||||||
placeholder="请输入用户名称"
|
placeholder="请输入用户名称"
|
||||||
|
|
@ -326,6 +375,35 @@ const User: React.FC = () => {
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div> : null}
|
||||||
|
<div>
|
||||||
|
<span>届:</span>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入届"
|
||||||
|
value={addUserFrom.year}
|
||||||
|
onChange={(e) => {
|
||||||
|
const regex = /^[0-9]*$/;
|
||||||
|
if (regex.test(e.target.value)) {
|
||||||
|
setAddUserFrom({
|
||||||
|
...addUserFrom,
|
||||||
|
year: e.target.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>学科:</span>
|
||||||
|
<Select
|
||||||
|
placeholder='请选择学科'
|
||||||
|
style={{ flexGrow: 1 }}
|
||||||
|
options={subjectList}
|
||||||
|
value={addUserFrom.subject} onChange={(e) => {
|
||||||
|
setAddUserFrom({
|
||||||
|
...addUserFrom,
|
||||||
|
subject: e
|
||||||
|
});
|
||||||
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
|
|
@ -333,43 +411,66 @@ const User: React.FC = () => {
|
||||||
}}>
|
}}>
|
||||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setAddUserModal(false)}>取消</Button>
|
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setAddUserModal(false)}>取消</Button>
|
||||||
<Button type="primary" className='m-ant-btn' onClick={async () => {
|
<Button type="primary" className='m-ant-btn' onClick={async () => {
|
||||||
if (!addUserFrom.Account) {
|
if (!addUserFrom.Account && isCreateUser !== 'batch') {
|
||||||
return message.error('请输入账号!')
|
return message.error('请输入账号!')
|
||||||
}
|
}
|
||||||
if (!addUserFrom.RoleId) {
|
if (!addUserFrom.RoleId) {
|
||||||
return message.error('请选择角色!')
|
return message.error('请选择角色!')
|
||||||
}
|
}
|
||||||
if (!addUserFrom.Pwd && isCreateUser) {
|
if (!addUserFrom.Pwd && isCreateUser === 'add') {
|
||||||
return message.error('请输入密码!')
|
return message.error('请输入密码!')
|
||||||
}
|
}
|
||||||
if (!addUserFrom.UserName) {
|
if (!addUserFrom.UserName && isCreateUser !== 'batch') {
|
||||||
return message.error('请输入用户名称!')
|
return message.error('请输入用户名称!')
|
||||||
}
|
}
|
||||||
if (isCreateUser) {
|
if (!addUserFrom.year) {
|
||||||
|
return message.error('请输入届!')
|
||||||
|
}
|
||||||
|
if (addUserFrom.subject === null) {
|
||||||
|
return message.error('请选择学科!')
|
||||||
|
}
|
||||||
|
if (isCreateUser === 'add') {
|
||||||
await PostUser({
|
await PostUser({
|
||||||
...addUserFrom,
|
...addUserFrom,
|
||||||
Pwd: CryptoJS.MD5(addUserFrom.Pwd).toString(CryptoJS.enc.Hex)
|
Pwd: CryptoJS.MD5(addUserFrom.Pwd).toString(CryptoJS.enc.Hex)
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
setAddUserModal(false)
|
setAddUserModal(false)
|
||||||
message.success('添加成功!')
|
res.data ? message.success('添加成功!') : message.error('添加失败!')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else if (isCreateUser === 'edit') {
|
||||||
await PutUser({
|
await PutUser({
|
||||||
Id: addUserFrom.Id,
|
Id: addUserFrom.Id,
|
||||||
Account: addUserFrom.Account,
|
Account: addUserFrom.Account,
|
||||||
RoleId: addUserFrom.RoleId,
|
RoleId: addUserFrom.RoleId,
|
||||||
UserName: addUserFrom.UserName
|
UserName: addUserFrom.UserName,
|
||||||
|
subject: addUserFrom.subject,
|
||||||
|
year: addUserFrom.year,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
setAddUserModal(false)
|
setAddUserModal(false)
|
||||||
message.success('修改成功!')
|
res.data ? message.success('修改成功!') : message.error('修改失败!')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const param = selectedRowKeys.map((item: any) => {
|
||||||
|
return {
|
||||||
|
id: item,
|
||||||
|
subject: addUserFrom.subject,
|
||||||
|
year: addUserFrom.year,
|
||||||
|
RoleId: addUserFrom.RoleId,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await PutUserBth(param).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
setAddUserModal(false)
|
||||||
|
res.data ? message.success('修改成功!') : message.error('修改失败!')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
await getUserList()
|
await getUserList()
|
||||||
}}>{isCreateUser ? '添加' : '修改'}</Button>
|
}}>{isCreateUser === 'add' ? '添加' : '修改'}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
@ -442,7 +543,6 @@ const User: React.FC = () => {
|
||||||
DeleteUser(selectedRowKeys).then(res => {
|
DeleteUser(selectedRowKeys).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
setDeleteUserPawModal(false)
|
setDeleteUserPawModal(false)
|
||||||
setSelectedRowKeys([])
|
|
||||||
message.success('删除成功!')
|
message.success('删除成功!')
|
||||||
getUserList()
|
getUserList()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -811,7 +811,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
>div:nth-child(1) {
|
.meetingContentFooterPopoverDel {
|
||||||
background-color: #FF5219;
|
background-color: #FF5219;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
@ -823,7 +823,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
>div:nth-child(2) {
|
.meetingContentFooterPopoverDefault {
|
||||||
background-color: #31353A;
|
background-color: #31353A;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
@ -835,7 +835,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
>div:nth-child(3) {
|
.meetingContentFooterPopoverCancel {
|
||||||
background-color: #101418;
|
background-color: #101418;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,7 @@ const Meeting: React.FC = () => {
|
||||||
const [noViewChatList, setNoViewChatList] = useState(0)
|
const [noViewChatList, setNoViewChatList] = useState(0)
|
||||||
const [currentLookUserAccount, setCurrentLookUserAccount] = useState<any>('')
|
const [currentLookUserAccount, setCurrentLookUserAccount] = useState<any>('')
|
||||||
const [recorder, setRecorder] = useState<any>('')
|
const [recorder, setRecorder] = useState<any>('')
|
||||||
|
const [_currentRequestSpeakType, setCurrentRequestSpeakType] = useState<'video' | 'audio' | ''>('')
|
||||||
const [_mediaStream, setMediaStream] = useState<any>('')
|
const [_mediaStream, setMediaStream] = useState<any>('')
|
||||||
const [isShare, setIsShare] = useState<any>(null)
|
const [isShare, setIsShare] = useState<any>(null)
|
||||||
const [isSharePopConfirm, setIsSharePopConfirm] = useState<any>(false)
|
const [isSharePopConfirm, setIsSharePopConfirm] = useState<any>(false)
|
||||||
|
|
@ -413,13 +414,23 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (item.user.uid === userInfo.uid) {
|
if (item.user.uid === userInfo.uid) {
|
||||||
if (!item.user.isRoomManage) {
|
if (!item.user.isRoomManager) {
|
||||||
await agora.allLeaveChannelEx()
|
await agora.allLeaveChannelEx()
|
||||||
}
|
}
|
||||||
message.success(`管理员${item.user.isRoomManager ? '设置' : '取消'}您为发言人`)
|
message.success(`管理员${item.user.isRoomManager ? '设置' : '取消'}您为发言人`)
|
||||||
await agora.updateChannelMediaOptions(item.user.isRoomManager)
|
await agora.updateChannelMediaOptions(item.user.isRoomManager)
|
||||||
await postOpenMicrApi(item.user.isRoomManager, userInfo.uid, false)
|
setCurrentRequestSpeakType(res => {
|
||||||
await postOpenCameraApi(item.user.isRoomManager, userInfo.uid)
|
if (res === 'video') {
|
||||||
|
postOpenCameraApi(item.user.isRoomManager, userInfo.uid)
|
||||||
|
} else if (res === 'audio') {
|
||||||
|
postOpenMicrApi(item.user.isRoomManager, userInfo.uid, false)
|
||||||
|
} else {
|
||||||
|
postOpenMicrApi(item.user.isRoomManager, userInfo.uid, false)
|
||||||
|
postOpenCameraApi(item.user.isRoomManager, userInfo.uid)
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
})
|
||||||
|
|
||||||
await stopScreenCapture()
|
await stopScreenCapture()
|
||||||
} else {
|
} else {
|
||||||
message.success(`管理员${item.user.isRoomManager ? '设置' : '取消'}${item.user.userName}为发言人`)
|
message.success(`管理员${item.user.isRoomManager ? '设置' : '取消'}${item.user.userName}为发言人`)
|
||||||
|
|
@ -602,6 +613,7 @@ const Meeting: React.FC = () => {
|
||||||
if (isClicked) {
|
if (isClicked) {
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
setIsClicked(false);
|
setIsClicked(false);
|
||||||
|
setCurrentRequestSpeakType('')
|
||||||
}, 10000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -999,6 +1011,25 @@ const Meeting: React.FC = () => {
|
||||||
}
|
}
|
||||||
// 操作按钮
|
// 操作按钮
|
||||||
const changeStatusList = async (row: any, itemIndex: number, rowIndex: number): Promise<void> => {
|
const changeStatusList = async (row: any, itemIndex: number, rowIndex: number): Promise<void> => {
|
||||||
|
function requestSpeak() {
|
||||||
|
confirm({
|
||||||
|
title: '提示',
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
content: `该操作需向管理员申请权限`,
|
||||||
|
centered: true,
|
||||||
|
okText: '申请',
|
||||||
|
cancelText: '取消',
|
||||||
|
async onOk() {
|
||||||
|
GetApplySpeak(state.channelId).then(res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
message.success('申请发言成功')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const footerListTemplate = [...footerList]
|
const footerListTemplate = [...footerList]
|
||||||
setFooterListIndex({
|
setFooterListIndex({
|
||||||
itemIndex,
|
itemIndex,
|
||||||
|
|
@ -1046,13 +1077,37 @@ const Meeting: React.FC = () => {
|
||||||
await postOpenMicr(false, user.uid)
|
await postOpenMicr(false, user.uid)
|
||||||
break;
|
break;
|
||||||
case '解除静音':
|
case '解除静音':
|
||||||
await postOpenMicr(true, user.uid)
|
await getUserRoomInfo().then(async (res) => {
|
||||||
|
if (res) {
|
||||||
|
await postOpenMicr(true, user.uid)
|
||||||
|
} else {
|
||||||
|
if (!isClicked) {
|
||||||
|
setCurrentRequestSpeakType('audio')
|
||||||
|
setIsClicked(true);
|
||||||
|
requestSpeak()
|
||||||
|
} else {
|
||||||
|
message.error('申请太频繁了,请稍后重试!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
break;
|
break;
|
||||||
case '关闭视频':
|
case '关闭视频':
|
||||||
await postOpenCamera(false, user.uid)
|
await postOpenCamera(false, user.uid)
|
||||||
break;
|
break;
|
||||||
case '开启视频':
|
case '开启视频':
|
||||||
await postOpenCamera(true, user.uid)
|
await getUserRoomInfo().then(async (res) => {
|
||||||
|
if (res) {
|
||||||
|
await postOpenCamera(true, user.uid)
|
||||||
|
} else {
|
||||||
|
if (!isClicked) {
|
||||||
|
setCurrentRequestSpeakType('video')
|
||||||
|
setIsClicked(true);
|
||||||
|
requestSpeak()
|
||||||
|
} else {
|
||||||
|
message.error('申请太频繁了,请稍后重试!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
break;
|
break;
|
||||||
case '设置':
|
case '设置':
|
||||||
stupWizardRef.current.changeModal()
|
stupWizardRef.current.changeModal()
|
||||||
|
|
@ -1141,11 +1196,7 @@ const Meeting: React.FC = () => {
|
||||||
case '申请发言':
|
case '申请发言':
|
||||||
if (!isClicked) {
|
if (!isClicked) {
|
||||||
setIsClicked(true);
|
setIsClicked(true);
|
||||||
GetApplySpeak(state.channelId).then(res => {
|
requestSpeak()
|
||||||
if (res.code === 200) {
|
|
||||||
message.success('申请发言成功')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
message.error('申请太频繁了,请稍后重试!');
|
message.error('申请太频繁了,请稍后重试!');
|
||||||
}
|
}
|
||||||
|
|
@ -2177,11 +2228,11 @@ const Meeting: React.FC = () => {
|
||||||
okText="结束"
|
okText="结束"
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
>
|
>
|
||||||
<div>全员结束会议</div>
|
<div className='meetingContentFooterPopoverDel'>全员结束会议</div>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
: null}
|
: null}
|
||||||
<div onClick={() => leaveChannel()}>仅自己离开</div>
|
<div className='meetingContentFooterPopoverDefault' onClick={() => leaveChannel()}>仅自己离开</div>
|
||||||
<div onClick={() => { setOpen(false) }}>取消</div>
|
<div className='meetingContentFooterPopoverCancel' onClick={() => { setOpen(false) }}>取消</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
title=""
|
title=""
|
||||||
|
|
@ -2200,12 +2251,12 @@ const Meeting: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</Popover>
|
</Popover>
|
||||||
case '申请发言':
|
case '申请发言':
|
||||||
if (!role.ID.includes(user.roleId)) {
|
// if (!role.ID.includes(user.roleId)) {
|
||||||
return <div className='drag' onClick={() => changeStatusList(row, itemIndex, rowIndex)} key={rowIndex}>
|
// return <div className='drag' onClick={() => changeStatusList(row, itemIndex, rowIndex)} key={rowIndex}>
|
||||||
<img src={row.active ? row.iconActive : row.icon} alt="" />
|
// <img src={row.active ? row.iconActive : row.icon} alt="" />
|
||||||
<span>{row.title}</span>
|
// <span>{row.title}</span>
|
||||||
</div>
|
// </div>
|
||||||
}
|
// }
|
||||||
return null
|
return null
|
||||||
case '结束发言':
|
case '结束发言':
|
||||||
if (!role.ID.includes(user.roleId)) {
|
if (!role.ID.includes(user.roleId)) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
.shareScreenWindow {
|
||||||
|
background-color: red;
|
||||||
|
color: black;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import styles from '@/page/ShareScreenWindow/index.module.scss'
|
||||||
|
import { useEffect } from "react";
|
||||||
|
const ShareScreenWindow: React.FC = () => {
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
// window.electron.createChildWindow({
|
||||||
|
// url: location.origin + `/#/shareScreenWindow`,
|
||||||
|
// width: 600,
|
||||||
|
// height: 40,
|
||||||
|
// key: 'shareScreenWindow',
|
||||||
|
// })
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.shareScreenWindow}>
|
||||||
|
2222
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ShareScreenWindow
|
||||||
|
|
@ -18,6 +18,7 @@ export interface IElectronAPI {
|
||||||
getVersion: () => Promise<string>;
|
getVersion: () => Promise<string>;
|
||||||
setRegistry: (uuid: string) => any;
|
setRegistry: (uuid: string) => any;
|
||||||
getRegistry: () => any;
|
getRegistry: () => any;
|
||||||
|
createChildWindow: (config: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|
|
||||||
|
|
@ -115,15 +115,15 @@ export const agora = {
|
||||||
rtcEngine.registerEventHandler({
|
rtcEngine.registerEventHandler({
|
||||||
// 监听本地用户加入频道事件
|
// 监听本地用户加入频道事件
|
||||||
onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
|
onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
|
||||||
await onJoinChannelSuccess(connection, elapsed)
|
await onJoinChannelSuccess?.(connection, elapsed)
|
||||||
},
|
},
|
||||||
// 监听远端用户加入频道事件
|
// 监听远端用户加入频道事件
|
||||||
onUserJoined: async (connection: RtcConnection, remoteUid: number, elapsed: number) => {
|
onUserJoined: async (connection: RtcConnection, remoteUid: number, elapsed: number) => {
|
||||||
await onUserJoined(connection, remoteUid, elapsed)
|
await onUserJoined?.(connection, remoteUid, elapsed)
|
||||||
},
|
},
|
||||||
// 监听用户离开频道事件
|
// 监听用户离开频道事件
|
||||||
onUserOffline: async (connection: RtcConnection, remoteUid: number, reason: UserOfflineReasonType) => {
|
onUserOffline: async (connection: RtcConnection, remoteUid: number, reason: UserOfflineReasonType) => {
|
||||||
await onUserOffline(connection, remoteUid, reason)
|
await onUserOffline?.(connection, remoteUid, reason)
|
||||||
},
|
},
|
||||||
// // 视频发布状态改变回调
|
// // 视频发布状态改变回调
|
||||||
// onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
// onVideoPublishStateChanged: (source: any, channel: any, oldState: any, newState: any, elapseSinceLastState: any) => {
|
||||||
|
|
@ -139,19 +139,19 @@ export const agora = {
|
||||||
// },
|
// },
|
||||||
// // 用户音量提示回调。
|
// // 用户音量提示回调。
|
||||||
onAudioVolumeIndication: async (_connection: RtcConnection, speakers: AudioVolumeInfo[], _speakerNumber: number, _totalVolume: number) => {
|
onAudioVolumeIndication: async (_connection: RtcConnection, speakers: AudioVolumeInfo[], _speakerNumber: number, _totalVolume: number) => {
|
||||||
await onAudioVolumeIndication(speakers)
|
await onAudioVolumeIndication?.(speakers)
|
||||||
},
|
},
|
||||||
//通话中每个用户的网络上下行 last mile 质量报告回调。
|
//通话中每个用户的网络上下行 last mile 质量报告回调。
|
||||||
onNetworkQuality: async (connection: RtcConnection, remoteUid: number, txQuality: QualityType, rxQuality: QualityType) => {
|
onNetworkQuality: async (connection: RtcConnection, remoteUid: number, txQuality: QualityType, rxQuality: QualityType) => {
|
||||||
await onNetworkQuality(connection, remoteUid, txQuality, rxQuality)
|
await onNetworkQuality?.(connection, remoteUid, txQuality, rxQuality)
|
||||||
},
|
},
|
||||||
//当前通话相关的统计信息回调。
|
//当前通话相关的统计信息回调。
|
||||||
onRtcStats: async (_connection: RtcConnection, stats: RtcStats) => {
|
onRtcStats: async (_connection: RtcConnection, stats: RtcStats) => {
|
||||||
await onRtcStats(stats)
|
await onRtcStats?.(stats)
|
||||||
},
|
},
|
||||||
// 网络连接状态已改变回调。
|
// 网络连接状态已改变回调。
|
||||||
onConnectionStateChanged: async (connection: RtcConnection, state: ConnectionStateType, reason: ConnectionChangedReasonType) => {
|
onConnectionStateChanged: async (connection: RtcConnection, state: ConnectionStateType, reason: ConnectionChangedReasonType) => {
|
||||||
await onConnectionStateChanged(connection, state, reason)
|
await onConnectionStateChanged?.(connection, state, reason)
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,6 @@ $pagination-hover-background-color: #5575F2;
|
||||||
|
|
||||||
.ant-pagination-prev,
|
.ant-pagination-prev,
|
||||||
.ant-pagination-next {
|
.ant-pagination-next {
|
||||||
width: 30px !important;
|
|
||||||
height: 30px !important;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: $pagination-background-color;
|
background: $pagination-background-color;
|
||||||
|
|
||||||
|
|
@ -200,9 +198,6 @@ $pagination-hover-background-color: #5575F2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-pagination-item {
|
.ant-pagination-item {
|
||||||
width: 30px !important;
|
|
||||||
height: 30px !important;
|
|
||||||
line-height: 30px !important;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: $pagination-background-color !important;
|
background: $pagination-background-color !important;
|
||||||
margin-right: 10px !important;
|
margin-right: 10px !important;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ body {
|
||||||
|
|
||||||
img {
|
img {
|
||||||
display: block;
|
display: block;
|
||||||
|
-webkit-user-drag: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue