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()
|
||||
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事件触发后的操作自行编写
|
||||
|
|
|
|||
|
|
@ -73,4 +73,8 @@ window.electron = {
|
|||
setRegistry: (uuid) => {
|
||||
ipcRenderer.invoke('setRegistry', uuid)
|
||||
},
|
||||
// 创建子窗口
|
||||
createChildWindow: (config) => {
|
||||
ipcRenderer.invoke('createChildWindow', config)
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,10 +33,11 @@ const App: React.FC = () => {
|
|||
});
|
||||
const [spinning, setSpinning] = useState(false);
|
||||
const [isState, setIsState] = useState(true);
|
||||
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 && Number(userInfo.perms)) {
|
||||
if (userInfo && !userInfo.isAnonymous) {
|
||||
if (loginInfo && loginInfo.isAutoLogin) {
|
||||
PostLogin({
|
||||
account: loginInfo.account,
|
||||
|
|
@ -148,6 +150,7 @@ const App: React.FC = () => {
|
|||
onStop()
|
||||
}
|
||||
}, [navigate])
|
||||
}
|
||||
useEffect(() => {
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'F11') {
|
||||
|
|
@ -239,6 +242,7 @@ const App: React.FC = () => {
|
|||
</Route>
|
||||
<Route path='/login' element={<Login />} />
|
||||
<Route path='/meeting' element={<Meeting />} />
|
||||
<Route path='/shareScreenWindow' element={<ShareScreenWindow />} />
|
||||
<Route path='*' element={<NotFound />} />
|
||||
</Routes>
|
||||
<Spin spinning={spinning} fullscreen />
|
||||
|
|
|
|||
|
|
@ -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}`,
|
||||
|
|
|
|||
|
|
@ -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`,
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => {
|
|||
</div>
|
||||
</div>) : <span style={{ display: 'block', textAlign: 'center', color: 'white', padding: '30px 0' }}>暂无数据</span>}
|
||||
</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({
|
||||
...list,
|
||||
pageIndex: e
|
||||
|
|
|
|||
|
|
@ -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}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
<HashRouter>
|
||||
|
|
|
|||
|
|
@ -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<any>();
|
||||
const stupWizardRef = useRef<any>();
|
||||
const [user, setUser] = useState<any>({});
|
||||
const [currentRoomInfo, setCurrentRoomInfo] = useState<any>({});
|
||||
const [subjectList, setSubjectList] = useState<any>([]);
|
||||
const [timeData, setTimeData] = useState<any>([]);
|
||||
const [isCreateRoom, setIsCreateRoom] = useState<boolean>(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<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> => {
|
||||
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="取消"
|
||||
>
|
||||
<div>删除会议室</div>
|
||||
<div className='meetingContentFooterPopoverDel'>删除会议室</div>
|
||||
</Popconfirm> : null}
|
||||
<div onClick={() => {
|
||||
<div className='meetingContentFooterPopoverDefault' onClick={() => {
|
||||
changeOpen(index, false)
|
||||
setTimeSelectModal(true)
|
||||
}}>导出参会记录</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)
|
||||
}}>取消</div>
|
||||
</div>
|
||||
|
|
@ -298,19 +334,19 @@ const Index: React.FC = () => {
|
|||
</div>
|
||||
}
|
||||
<div className={styles.indexContentPagination}>
|
||||
<Pagination size="small" total={list.total} onChange={(e) => {
|
||||
<Pagination size="small" total={list.total} onChange={(e: number) => {
|
||||
setList({
|
||||
...list,
|
||||
pageIndex: e
|
||||
})
|
||||
}} pageSize={list.pageSize} />
|
||||
}} pageSize={list.pageSize} showSizeChanger={false} />
|
||||
</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>
|
||||
<Input
|
||||
{isCreateRoom ? <Input
|
||||
placeholder="请输入房间号"
|
||||
style={{ marginBottom: '14px' }}
|
||||
className={styles.letterSpacing}
|
||||
|
|
@ -344,7 +380,7 @@ const Index: React.FC = () => {
|
|||
>获取随机房间号
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
/> : null}
|
||||
<Input.TextArea
|
||||
placeholder="请输入房间名字"
|
||||
style={{ marginBottom: '14px' }}
|
||||
|
|
@ -358,6 +394,30 @@ const Index: React.FC = () => {
|
|||
})
|
||||
}}
|
||||
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 style={{
|
||||
display: 'flex', justifyContent: 'center'
|
||||
|
|
@ -370,6 +430,13 @@ const Index: React.FC = () => {
|
|||
if (!createRoomFrom.roomNum) {
|
||||
return message.error('请输入房间号!')
|
||||
}
|
||||
if (!createRoomFrom.year) {
|
||||
return message.error('请输入届!')
|
||||
}
|
||||
if (createRoomFrom.subject === "") {
|
||||
return message.error('请选择学科!')
|
||||
}
|
||||
if (isCreateRoom) {
|
||||
isGetCheckoutRoomNum(createRoomFrom.roomNum, (bool: boolean) => {
|
||||
if (bool) {
|
||||
message.error('房间号已存在!')
|
||||
|
|
@ -383,7 +450,16 @@ const Index: React.FC = () => {
|
|||
})
|
||||
}
|
||||
})
|
||||
}}>创建</Button>
|
||||
} else {
|
||||
PostRoomInfo(createRoomFrom).then(res => {
|
||||
if (res.code === 200) {
|
||||
message.success('更新成功!')
|
||||
setCreateRoomModal(false)
|
||||
getRoomList()
|
||||
}
|
||||
})
|
||||
}
|
||||
}}>{isCreateRoom ? '创建' : '更新'}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useEffect, useState, useRef } from "react";
|
|||
import Operation from '@/components/Operation';
|
||||
import { Button, Input, Table, Pagination, Modal, message, Select } from "antd";
|
||||
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 ImageUrl from '@/utils/package/imageUrl';
|
||||
import { storage } from '@/utils';
|
||||
|
|
@ -15,7 +15,7 @@ const fs = require('fs').promises;
|
|||
const User: React.FC = () => {
|
||||
const stupWizardRef = useRef<any>();
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
const [isCreateUser, setIsCreateUser] = useState(false);
|
||||
const [isCreateUser, setIsCreateUser] = useState<'add' | 'batch' | 'edit'>();
|
||||
const [list, setList] = useState({
|
||||
data: [],
|
||||
searchKeywod: '',
|
||||
|
|
@ -30,7 +30,9 @@ const User: React.FC = () => {
|
|||
Account: "",
|
||||
RoleId: null,
|
||||
Pwd: "",
|
||||
UserName: ""
|
||||
UserName: "",
|
||||
subject: null,
|
||||
year: "",
|
||||
})
|
||||
const [changeUserPawModal, setChangeUserPawModal] = useState(false)
|
||||
const [changeImportModal, setChangeImportModal] = useState(false)
|
||||
|
|
@ -39,10 +41,14 @@ const User: React.FC = () => {
|
|||
newPwd: '',
|
||||
})
|
||||
const [deleteUserPawModal, setDeleteUserPawModal] = useState(false)
|
||||
const [subjectList, setSubjectList] = useState<any>([]);
|
||||
useEffect(() => {
|
||||
getSubDpList()
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getUserList()
|
||||
}, [list.pageIndex]);
|
||||
}, [list.pageIndex, list.pageSize]);
|
||||
|
||||
const getUserList = async (): Promise<void> => {
|
||||
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 (
|
||||
<>
|
||||
<div className={styles.user}>
|
||||
|
|
@ -131,13 +144,15 @@ const User: React.FC = () => {
|
|||
onClick={() => {
|
||||
getRoleDpList((bool: boolean) => {
|
||||
if (bool) {
|
||||
setIsCreateUser(true)
|
||||
setIsCreateUser('add')
|
||||
setAddUserFrom({
|
||||
Id: "",
|
||||
Account: "",
|
||||
RoleId: null,
|
||||
Pwd: "",
|
||||
UserName: "",
|
||||
subject: null,
|
||||
year: "",
|
||||
})
|
||||
setAddUserModal(true)
|
||||
}
|
||||
|
|
@ -154,6 +169,31 @@ const User: React.FC = () => {
|
|||
className='m-ant-btn'>
|
||||
批量导入用户
|
||||
</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"
|
||||
icon={<img src={ImageUrl.icon21} alt="" />}
|
||||
className={styles.userBtnsDel}
|
||||
|
|
@ -161,7 +201,7 @@ const User: React.FC = () => {
|
|||
if (selectedRowKeys.length) {
|
||||
setDeleteUserPawModal(true)
|
||||
} 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>
|
||||
</>
|
||||
)} />
|
||||
<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
|
||||
type="primary"
|
||||
|
|
@ -223,13 +269,15 @@ const User: React.FC = () => {
|
|||
onClick={() => {
|
||||
getRoleDpList((bool: boolean) => {
|
||||
if (bool) {
|
||||
setIsCreateUser(false)
|
||||
setIsCreateUser('edit')
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
Id: item.id,
|
||||
Account: item.account,
|
||||
RoleId: item.roleId,
|
||||
UserName: item.userName,
|
||||
subject: item.subject,
|
||||
year: item.year,
|
||||
})
|
||||
setAddUserModal(true)
|
||||
}
|
||||
|
|
@ -258,19 +306,20 @@ const User: React.FC = () => {
|
|||
</Table>
|
||||
<div className={styles.userContentPagination}>
|
||||
<span>共{list.total}项数据</span>
|
||||
<Pagination size="small" total={list.total} onChange={(e) => {
|
||||
<Pagination size="small" total={list.total} onChange={(page, pageSize) => {
|
||||
setList({
|
||||
...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>
|
||||
<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 className={styles.addUserModal}>
|
||||
<div>
|
||||
{isCreateUser !== 'batch' ? <div>
|
||||
<span>账号:</span>
|
||||
<Input
|
||||
style={{ flexGrow: 1 }}
|
||||
|
|
@ -285,7 +334,7 @@ const User: React.FC = () => {
|
|||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div> : null}
|
||||
<div>
|
||||
<span>角色:</span>
|
||||
<Select
|
||||
|
|
@ -299,7 +348,7 @@ const User: React.FC = () => {
|
|||
});
|
||||
}} />;
|
||||
</div>
|
||||
{isCreateUser ? <div>
|
||||
{isCreateUser === 'add' ? <div>
|
||||
<span>密码:</span>
|
||||
<Input.Password
|
||||
placeholder="请输入密码"
|
||||
|
|
@ -313,7 +362,7 @@ const User: React.FC = () => {
|
|||
}}
|
||||
/>
|
||||
</div> : null}
|
||||
<div>
|
||||
{isCreateUser !== 'batch' ? <div>
|
||||
<span>用户名称:</span>
|
||||
<Input
|
||||
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 style={{
|
||||
|
|
@ -333,43 +411,66 @@ const User: React.FC = () => {
|
|||
}}>
|
||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setAddUserModal(false)}>取消</Button>
|
||||
<Button type="primary" className='m-ant-btn' onClick={async () => {
|
||||
if (!addUserFrom.Account) {
|
||||
if (!addUserFrom.Account && isCreateUser !== 'batch') {
|
||||
return message.error('请输入账号!')
|
||||
}
|
||||
if (!addUserFrom.RoleId) {
|
||||
return message.error('请选择角色!')
|
||||
}
|
||||
if (!addUserFrom.Pwd && isCreateUser) {
|
||||
if (!addUserFrom.Pwd && isCreateUser === 'add') {
|
||||
return message.error('请输入密码!')
|
||||
}
|
||||
if (!addUserFrom.UserName) {
|
||||
if (!addUserFrom.UserName && isCreateUser !== 'batch') {
|
||||
return message.error('请输入用户名称!')
|
||||
}
|
||||
if (isCreateUser) {
|
||||
if (!addUserFrom.year) {
|
||||
return message.error('请输入届!')
|
||||
}
|
||||
if (addUserFrom.subject === null) {
|
||||
return message.error('请选择学科!')
|
||||
}
|
||||
if (isCreateUser === 'add') {
|
||||
await PostUser({
|
||||
...addUserFrom,
|
||||
Pwd: CryptoJS.MD5(addUserFrom.Pwd).toString(CryptoJS.enc.Hex)
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
setAddUserModal(false)
|
||||
message.success('添加成功!')
|
||||
res.data ? message.success('添加成功!') : message.error('添加失败!')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
} else if (isCreateUser === 'edit') {
|
||||
await PutUser({
|
||||
Id: addUserFrom.Id,
|
||||
Account: addUserFrom.Account,
|
||||
RoleId: addUserFrom.RoleId,
|
||||
UserName: addUserFrom.UserName
|
||||
UserName: addUserFrom.UserName,
|
||||
subject: addUserFrom.subject,
|
||||
year: addUserFrom.year,
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
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()
|
||||
}}>{isCreateUser ? '添加' : '修改'}</Button>
|
||||
}}>{isCreateUser === 'add' ? '添加' : '修改'}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
|
@ -442,7 +543,6 @@ const User: React.FC = () => {
|
|||
DeleteUser(selectedRowKeys).then(res => {
|
||||
if (res.code === 200) {
|
||||
setDeleteUserPawModal(false)
|
||||
setSelectedRowKeys([])
|
||||
message.success('删除成功!')
|
||||
getUserList()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -811,7 +811,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
>div:nth-child(1) {
|
||||
.meetingContentFooterPopoverDel {
|
||||
background-color: #FF5219;
|
||||
|
||||
&:hover {
|
||||
|
|
@ -823,7 +823,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
>div:nth-child(2) {
|
||||
.meetingContentFooterPopoverDefault {
|
||||
background-color: #31353A;
|
||||
|
||||
&:hover {
|
||||
|
|
@ -835,7 +835,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
>div:nth-child(3) {
|
||||
.meetingContentFooterPopoverCancel {
|
||||
background-color: #101418;
|
||||
|
||||
&:hover {
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ const Meeting: React.FC = () => {
|
|||
const [noViewChatList, setNoViewChatList] = useState(0)
|
||||
const [currentLookUserAccount, setCurrentLookUserAccount] = useState<any>('')
|
||||
const [recorder, setRecorder] = useState<any>('')
|
||||
const [_currentRequestSpeakType, setCurrentRequestSpeakType] = useState<'video' | 'audio' | ''>('')
|
||||
const [_mediaStream, setMediaStream] = useState<any>('')
|
||||
const [isShare, setIsShare] = useState<any>(null)
|
||||
const [isSharePopConfirm, setIsSharePopConfirm] = useState<any>(false)
|
||||
|
|
@ -413,13 +414,23 @@ const Meeting: React.FC = () => {
|
|||
}
|
||||
} else {
|
||||
if (item.user.uid === userInfo.uid) {
|
||||
if (!item.user.isRoomManage) {
|
||||
if (!item.user.isRoomManager) {
|
||||
await agora.allLeaveChannelEx()
|
||||
}
|
||||
message.success(`管理员${item.user.isRoomManager ? '设置' : '取消'}您为发言人`)
|
||||
await agora.updateChannelMediaOptions(item.user.isRoomManager)
|
||||
await postOpenMicrApi(item.user.isRoomManager, userInfo.uid, false)
|
||||
await postOpenCameraApi(item.user.isRoomManager, userInfo.uid)
|
||||
setCurrentRequestSpeakType(res => {
|
||||
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()
|
||||
} else {
|
||||
message.success(`管理员${item.user.isRoomManager ? '设置' : '取消'}${item.user.userName}为发言人`)
|
||||
|
|
@ -602,6 +613,7 @@ const Meeting: React.FC = () => {
|
|||
if (isClicked) {
|
||||
timer = setTimeout(() => {
|
||||
setIsClicked(false);
|
||||
setCurrentRequestSpeakType('')
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
|
|
@ -999,6 +1011,25 @@ const Meeting: React.FC = () => {
|
|||
}
|
||||
// 操作按钮
|
||||
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]
|
||||
setFooterListIndex({
|
||||
itemIndex,
|
||||
|
|
@ -1046,13 +1077,37 @@ const Meeting: React.FC = () => {
|
|||
await postOpenMicr(false, user.uid)
|
||||
break;
|
||||
case '解除静音':
|
||||
await getUserRoomInfo().then(async (res) => {
|
||||
if (res) {
|
||||
await postOpenMicr(true, user.uid)
|
||||
} else {
|
||||
if (!isClicked) {
|
||||
setCurrentRequestSpeakType('audio')
|
||||
setIsClicked(true);
|
||||
requestSpeak()
|
||||
} else {
|
||||
message.error('申请太频繁了,请稍后重试!');
|
||||
}
|
||||
}
|
||||
})
|
||||
break;
|
||||
case '关闭视频':
|
||||
await postOpenCamera(false, user.uid)
|
||||
break;
|
||||
case '开启视频':
|
||||
await getUserRoomInfo().then(async (res) => {
|
||||
if (res) {
|
||||
await postOpenCamera(true, user.uid)
|
||||
} else {
|
||||
if (!isClicked) {
|
||||
setCurrentRequestSpeakType('video')
|
||||
setIsClicked(true);
|
||||
requestSpeak()
|
||||
} else {
|
||||
message.error('申请太频繁了,请稍后重试!');
|
||||
}
|
||||
}
|
||||
})
|
||||
break;
|
||||
case '设置':
|
||||
stupWizardRef.current.changeModal()
|
||||
|
|
@ -1141,11 +1196,7 @@ const Meeting: React.FC = () => {
|
|||
case '申请发言':
|
||||
if (!isClicked) {
|
||||
setIsClicked(true);
|
||||
GetApplySpeak(state.channelId).then(res => {
|
||||
if (res.code === 200) {
|
||||
message.success('申请发言成功')
|
||||
}
|
||||
})
|
||||
requestSpeak()
|
||||
} else {
|
||||
message.error('申请太频繁了,请稍后重试!');
|
||||
}
|
||||
|
|
@ -2177,11 +2228,11 @@ const Meeting: React.FC = () => {
|
|||
okText="结束"
|
||||
cancelText="取消"
|
||||
>
|
||||
<div>全员结束会议</div>
|
||||
<div className='meetingContentFooterPopoverDel'>全员结束会议</div>
|
||||
</Popconfirm>
|
||||
: null}
|
||||
<div onClick={() => leaveChannel()}>仅自己离开</div>
|
||||
<div onClick={() => { setOpen(false) }}>取消</div>
|
||||
<div className='meetingContentFooterPopoverDefault' onClick={() => leaveChannel()}>仅自己离开</div>
|
||||
<div className='meetingContentFooterPopoverCancel' onClick={() => { setOpen(false) }}>取消</div>
|
||||
</div>
|
||||
}
|
||||
title=""
|
||||
|
|
@ -2200,12 +2251,12 @@ const Meeting: React.FC = () => {
|
|||
</div>
|
||||
</Popover>
|
||||
case '申请发言':
|
||||
if (!role.ID.includes(user.roleId)) {
|
||||
return <div className='drag' onClick={() => changeStatusList(row, itemIndex, rowIndex)} key={rowIndex}>
|
||||
<img src={row.active ? row.iconActive : row.icon} alt="" />
|
||||
<span>{row.title}</span>
|
||||
</div>
|
||||
}
|
||||
// if (!role.ID.includes(user.roleId)) {
|
||||
// return <div className='drag' onClick={() => changeStatusList(row, itemIndex, rowIndex)} key={rowIndex}>
|
||||
// <img src={row.active ? row.iconActive : row.icon} alt="" />
|
||||
// <span>{row.title}</span>
|
||||
// </div>
|
||||
// }
|
||||
return null
|
||||
case '结束发言':
|
||||
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>;
|
||||
setRegistry: (uuid: string) => any;
|
||||
getRegistry: () => any;
|
||||
createChildWindow: (config: any) => void;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
|
|
|||
|
|
@ -115,15 +115,15 @@ export const agora = {
|
|||
rtcEngine.registerEventHandler({
|
||||
// 监听本地用户加入频道事件
|
||||
onJoinChannelSuccess: async (connection: RtcConnection, elapsed: number) => {
|
||||
await onJoinChannelSuccess(connection, elapsed)
|
||||
await onJoinChannelSuccess?.(connection, elapsed)
|
||||
},
|
||||
// 监听远端用户加入频道事件
|
||||
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) => {
|
||||
await onUserOffline(connection, remoteUid, reason)
|
||||
await onUserOffline?.(connection, remoteUid, reason)
|
||||
},
|
||||
// // 视频发布状态改变回调
|
||||
// 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) => {
|
||||
await onAudioVolumeIndication(speakers)
|
||||
await onAudioVolumeIndication?.(speakers)
|
||||
},
|
||||
//通话中每个用户的网络上下行 last mile 质量报告回调。
|
||||
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) => {
|
||||
await onRtcStats(stats)
|
||||
await onRtcStats?.(stats)
|
||||
},
|
||||
// 网络连接状态已改变回调。
|
||||
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-next {
|
||||
width: 30px !important;
|
||||
height: 30px !important;
|
||||
border-radius: 50%;
|
||||
background: $pagination-background-color;
|
||||
|
||||
|
|
@ -200,9 +198,6 @@ $pagination-hover-background-color: #5575F2;
|
|||
}
|
||||
|
||||
.ant-pagination-item {
|
||||
width: 30px !important;
|
||||
height: 30px !important;
|
||||
line-height: 30px !important;
|
||||
border-radius: 50%;
|
||||
background: $pagination-background-color !important;
|
||||
margin-right: 10px !important;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ body {
|
|||
|
||||
img {
|
||||
display: block;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue