diff --git a/main.js b/main.js
index 345ce0f..0415f85 100644
--- a/main.js
+++ b/main.js
@@ -181,6 +181,7 @@ app.on('ready', () => {
connection.off('DriverList');
connection.off('SetDriver');
connection.off('ShowDriverList');
+ connection.off('ModifyNickName');
}
});
ipcMain.handle('onStop', (event) => {
@@ -370,6 +371,14 @@ app.on('ready', () => {
driversJsonString
})
});
+ // 修改用户名称
+ connection.on("ModifyNickName", (uid, nickName) => {
+ mainWindow.webContents.send('onSignalr', {
+ key: 'ModifyNickName',
+ uid,
+ nickName
+ })
+ });
}
});
// 放大缩小退出窗口
diff --git a/package.json b/package.json
index b7a531b..ce35f53 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "WGShare.Metting",
"private": true,
- "version": "0.6.0",
+ "version": "0.6.3",
"main": "main.js",
"authors": "yj",
"description": "智汇享",
diff --git a/src/api/Meeting/index.ts b/src/api/Meeting/index.ts
index 3733fae..22db4c8 100644
--- a/src/api/Meeting/index.ts
+++ b/src/api/Meeting/index.ts
@@ -147,4 +147,11 @@ export const PostRoomSingnIn = (data: any) =>
url: `/room/sign-in`,
method: 'post',
data
+ })
+
+export const PutAlterUname = (data: any) =>
+ request({
+ url: `/room/alter-uname`,
+ method: 'put',
+ data
})
\ No newline at end of file
diff --git a/src/components/JoinSetting/index.tsx b/src/components/JoinSetting/index.tsx
index 18065db..e8be5b5 100644
--- a/src/components/JoinSetting/index.tsx
+++ b/src/components/JoinSetting/index.tsx
@@ -20,18 +20,17 @@ const JoinSetting = forwardRef((_props: any, ref: any) => {
if (location.hash.indexOf('/meeting') === -1) {
await agora.init()
}
- setJoinRoomSettingForm((res: any) => {
- res.forEach(async (item: any, index: number) => {
- if (index === 0 && role.ID.includes(userInfo.roleId)) {
- await agora.getAudioMediaList().then(res => {
- item.active = res.ecordingList.length ? true : false
- })
- } else {
- item.active = false
- }
- });
- return res
- })
+ const list = [...joinRoomSettingForm]
+ list.forEach(async (item: any, index: number) => {
+ if (index === 0 && role.ID.includes(userInfo.roleId)) {
+ await agora.getAudioMediaList().then(res => {
+ item.active = res.ecordingList.length ? true : false
+ })
+ } else {
+ item.active = false
+ }
+ });
+ setJoinRoomSettingForm(list)
setRoomNumber(roomNum)
getDeviceList()
}
diff --git a/src/components/SharedFilesModel/index.tsx b/src/components/SharedFilesModel/index.tsx
index 4ce71d2..2eb8029 100644
--- a/src/components/SharedFilesModel/index.tsx
+++ b/src/components/SharedFilesModel/index.tsx
@@ -1,12 +1,13 @@
import styles from '@/components/SharedFilesModel/index.module.scss'
import {
DeleteOutlined,
+ LoadingOutlined,
ProfileOutlined,
ReloadOutlined,
SearchOutlined,
VerticalAlignBottomOutlined
} from '@ant-design/icons';
-import { Button, Input, message, Modal, Pagination, Progress, Table } from 'antd';
+import { Button, Input, message, Modal, Pagination, Popconfirm, Progress, Table } from 'antd';
import { forwardRef, useEffect, useImperativeHandle, useState, useRef } from "react";
import { DeleteRoomFile, GetRoomFile, GetRoomFileDwUrl, GetRoomUpFileurl, GetRoomUserItem, PostRoomFile } from '@/api/Meeting';
import axios from 'axios';
@@ -100,10 +101,10 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
}
- onChange={(e) => {
+ onPressEnter={(e: any) => {
if (fileList.pageIndex === 1) {
setFileList({
...fileList,
@@ -116,8 +117,30 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
pageIndex: 1
})
}
-
}}
+ onBlur={(e) => {
+ if (fileList.pageIndex === 1) {
+ setFileList({
+ ...fileList,
+ keyword: e.target.value,
+ })
+ } else {
+ setFileList({
+ ...fileList,
+ keyword: e.target.value,
+ pageIndex: 1
+ })
+ }
+ }}
+ suffix={
+
{
+ getRoomFile()
+ }}
+ >搜索
+
+ }
/>
{
if (fileList.pageIndex === 1) {
@@ -129,29 +152,41 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
})
}
}} />
- {roomUserItem && role.ID.includes(roomUserItem.roleId) || roomUserItem.isRoomManager ? {
+ {roomUserItem && (role.ID.includes(roomUserItem.roleId) || roomUserItem.isRoomManager) && fileList.data.length ? {
setShowRowSelection(!showRowSelection)
}} style={{ color: showRowSelection ? '#5575F2' : 'white' }} /> : null}
- {showRowSelection ? {
- if (selectedRowKeys.length) {
- DeleteRoomFile(selectedRowKeys).then(res => {
- if (res.code === 200) {
- message.success('删除成功!')
- if (fileList.pageIndex === 1) {
- getRoomFile()
- } else {
- setFileList({
- ...fileList,
- pageIndex: 1
- })
- }
+ {showRowSelection && fileList.data.length && selectedRowKeys.length ?
+ {
+ if (selectedRowKeys.length) {
+ DeleteRoomFile(selectedRowKeys).then(res => {
+ if (res.code === 200) {
+ message.success('删除成功!')
+ if (fileList.pageIndex === 1) {
+ getRoomFile()
+ } else {
+ setFileList({
+ ...fileList,
+ pageIndex: 1
+ })
+ }
+ }
+ })
+ } else {
+ message.error('请选择文件!')
}
- })
- } else {
- message.error('请选择文件!')
- }
- }} /> : null}
- : null}
+ {roomUserItem && role.ID.includes(roomUserItem.roleId) || roomUserItem.isRoomManager ?
+ >上传 : null}
@@ -258,9 +293,10 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
/>
(
<>
- {
+ storage.setItem('loading', true)
GetRoomFileDwUrl(item.fileUrl, item.id).then(res => {
if (res.code === 200) {
axios({
@@ -329,8 +365,10 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
}, 2000)
})
}
+ }).finally(() => {
+ storage.setItem('loading', false)
})
- }} />
+ }} /> : }
{/* */}
>
)} />
@@ -341,7 +379,7 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
...fileList,
pageIndex: e
})
- }} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} showSizeChanger={false}/>
+ }} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} showSizeChanger={false} />
diff --git a/src/components/UserName/index.module.scss b/src/components/UserName/index.module.scss
new file mode 100644
index 0000000..07f2ea1
--- /dev/null
+++ b/src/components/UserName/index.module.scss
@@ -0,0 +1,8 @@
+.userNameModal {
+
+ .userNameModalFooter {
+ margin-top: 10px;
+ display: flex;
+ justify-content: center;
+ }
+}
\ No newline at end of file
diff --git a/src/components/UserName/index.tsx b/src/components/UserName/index.tsx
new file mode 100644
index 0000000..1bc10d7
--- /dev/null
+++ b/src/components/UserName/index.tsx
@@ -0,0 +1,74 @@
+import { PutAlterUname } from '@/api/Meeting';
+import styles from '@/components/UserName/index.module.scss'
+import { storage } from '@/utils';
+import { Button, Input, message, Modal } from 'antd';
+import { useState, useImperativeHandle, forwardRef } from "react";
+const UserName = forwardRef((props: any, ref: any) => {
+ useImperativeHandle(ref, () => ({
+ changeModal: (data: any) => {
+ setInfo(data)
+ setUserNameModal(true)
+ }
+ }))
+ const [userNameModal, setUserNameModal] = useState(false);
+ const [info, setInfo] = useState({
+ userName: '',
+ uid: ''
+ });
+ return (
+ <>
+ setUserNameModal(false)}
+ centered
+ width={'300px'}
+ >
+
+
+ {
+ setInfo({
+ ...info,
+ userName: e.target.value
+ })
+ }}
+ />
+
+
+
+
+
+
+
+ >
+ )
+})
+
+export default UserName
\ No newline at end of file
diff --git a/src/page/Home/Index/index.tsx b/src/page/Home/Index/index.tsx
index 2c3caeb..270763b 100644
--- a/src/page/Home/Index/index.tsx
+++ b/src/page/Home/Index/index.tsx
@@ -1,7 +1,7 @@
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, Select } from "antd";
+import { Button, Input, Modal, Pagination, Empty, message, Popover, Popconfirm, DatePicker, Select, Radio } from "antd";
import { GetRoom, PostRoom, GetCheckoutRoomNum, GetRoomRtcToken, DeleteRoom, GetRecord, PostRoomInfo, GetQrcode } from '@/api/Home/Index';
import ImageUrl from '@/utils/package/imageUrl'
import { ExclamationCircleFilled, ReloadOutlined } from '@ant-design/icons';
@@ -42,6 +42,7 @@ const Index: React.FC = () => {
const [subjectList, setSubjectList] = useState([]);
const [timeData, setTimeData] = useState([]);
const [isCreateRoom, setIsCreateRoom] = useState(false);
+ const [allowAnonymous, setAllowAnonymous] = useState(true);
const [baseImage, setBaseImage] = useState('');
const userInfo = JSON.parse(storage.getItem('user') as string)
useEffect(() => {
@@ -305,6 +306,7 @@ const Index: React.FC = () => {
year: item.year,
id: item.id,
})
+ setAllowAnonymous(item.allowAnonymous)
getSubDpList()
setIsCreateRoom(false)
setCreateRoomModal(true)
@@ -385,7 +387,6 @@ const Index: React.FC = () => {
placeholder="请输入房间号"
style={{ flexGrow: 1 }}
className={styles.letterSpacing}
- showCount
maxLength={8}
value={createRoomFrom.roomNum}
onChange={(e) => {
@@ -422,7 +423,6 @@ const Index: React.FC = () => {
{
@@ -437,6 +437,7 @@ const Index: React.FC = () => {
届:
{
@@ -463,6 +464,15 @@ const Index: React.FC = () => {
})
}} />
+
+ 游客入会:
+ {
+ setAllowAnonymous(e.target.value);
+ }} value={allowAnonymous}>
+ 开启
+ 关闭
+
+
{
if (bool) {
message.error('房间号已存在!')
} else {
- PostRoom(createRoomFrom).then(res => {
+ PostRoom({ ...createRoomFrom, allowAnonymous }).then(res => {
if (res.code === 200) {
message.success('创建成功!')
setCreateRoomModal(false)
+ setAllowAnonymous(true)
getRoomList()
}
})
}
})
} else {
- PostRoomInfo(createRoomFrom).then(res => {
+ PostRoomInfo({ ...createRoomFrom, allowAnonymous }).then(res => {
if (res.code === 200) {
message.success('更新成功!')
setCreateRoomModal(false)
+ setAllowAnonymous(true)
getRoomList()
}
})
diff --git a/src/page/Home/User/index.tsx b/src/page/Home/User/index.tsx
index b83d7d7..e297033 100644
--- a/src/page/Home/User/index.tsx
+++ b/src/page/Home/User/index.tsx
@@ -221,7 +221,7 @@ const User: React.FC = () => {
>
删除用户
-
+
{
{
const regex = /^[0-9]*$/;
if (regex.test(e.target.value)) {
@@ -602,7 +603,7 @@ const User: React.FC = () => {
onClick={() => {
const file = document.createElement("input") as any;
file.type = "file";
- // file.accept = ".xls,.xlsx";
+ file.accept = ".xls,.xlsx";
file.onchange = async () => {
const setting = await JSON.parse(storage.getItem('setting') as string)
const fileInfo = file.files[0];
@@ -669,7 +670,7 @@ const User: React.FC = () => {
onClick={() => {
const file = document.createElement("input") as any;
file.type = "file";
- // file.accept = ".xls,.xlsx";
+ file.accept = ".xls,.xlsx";
file.onchange = async () => {
const setting = await JSON.parse(storage.getItem('setting') as string)
const fileInfo = file.files[0];
@@ -762,12 +763,17 @@ const User: React.FC = () => {
diff --git a/src/page/Meeting/UserListWindow/index.tsx b/src/page/Meeting/UserListWindow/index.tsx
index 14fd1d9..1630667 100644
--- a/src/page/Meeting/UserListWindow/index.tsx
+++ b/src/page/Meeting/UserListWindow/index.tsx
@@ -7,6 +7,7 @@ import Avatar from '@/components/Avatar';
import { useEffect, useState, useRef } from "react";
import { storage } from '@/utils';
import EquipmentManagement from '@/components/EquipmentManagement';
+import UserName from '@/components/UserName';
const { confirm } = Modal;
const UserListWindow: React.FC = () => {
@@ -14,6 +15,7 @@ const UserListWindow: React.FC = () => {
const [user, setUser] = useState({});
const [roomUserList, setRoomUserList] = useState([])
const equipmentManagementRef = useRef();
+ const userNameRef = useRef();
const channel = new BroadcastChannel('meeting_channel');
const userInfo = JSON.parse(storage.getItem('user') as string)
useEffect(() => {
@@ -149,6 +151,18 @@ const UserListWindow: React.FC = () => {
});
}}
>移出会议
+
}>
{
}}>全员静音
+
{
channel.postMessage({
type: 'userListWindowEquipmentManagement',
diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx
index 07c2de6..ccf0a00 100644
--- a/src/page/Meeting/index.tsx
+++ b/src/page/Meeting/index.tsx
@@ -24,6 +24,7 @@ import { fixWebmDuration } from "webm-duration-fix-buffer";
import { getKeyOpenChildWindow, setKeyOpenChildWindow } from '@/utils/package/public';
import MeetingDisconnected from '@/components/MeetingDisconnected';
import SingIn from '@/components/SingIn';
+import UserName from '@/components/UserName';
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('timers');
const { confirm } = Modal;
const { exec } = require('child_process');
@@ -39,7 +40,9 @@ const Meeting: React.FC = () => {
const equipmentManagementRef = useRef();
const meetingDisconnectedRef = useRef();
const singInRef = useRef();
+ const userNameRef = useRef();
const [isClicked, setIsClicked] = useState(false);
+ const [isClickedMediaSteam, setIsClickedMediaSteam] = useState(false);
const [statusList, setStatusList] = useState({
userList: false,
userChatList: false,
@@ -431,7 +434,7 @@ const Meeting: React.FC = () => {
setTimeout(async () => {
const setting = await JSON.parse(storage.getItem('setting') as string);
const stateInfo = await JSON.parse(storage.getItem('stateInfo') as string);
- if (stateInfo && setting.isRecordingTips) {
+ if (stateInfo && setting.isRecordingTips && location.href.indexOf('/meeting') !== -1) {
setRecorder((data: any) => {
if (!data) {
setIsScreenCapture(bool => {
@@ -855,6 +858,10 @@ const Meeting: React.FC = () => {
}
}
break;
+ // 修改用户名称
+ case 'ModifyNickName':
+ setAllUserListData('ModifyNickName', item)
+ break;
}
})
return () => {
@@ -912,6 +919,18 @@ const Meeting: React.FC = () => {
return () => clearTimeout(timer);
}, [isClicked]);
+ useEffect(() => {
+ let timer: NodeJS.Timeout;
+
+ if (isClickedMediaSteam) {
+ timer = setTimeout(() => {
+ setIsClickedMediaSteam(false)
+ }, 3000);
+ }
+
+ return () => clearTimeout(timer);
+ }, [isClickedMediaSteam]);
+
useEffect(() => {
const elements = document.querySelectorAll('.intersectionObserver-view');
if (elements.length && currentVideoId) {
@@ -1276,6 +1295,15 @@ const Meeting: React.FC = () => {
return res
})
break;
+ case 'ModifyNickName':
+ setRoomUserList((res: any) => {
+ let userItem = res.find((row: any) => row.uid == item.uid)
+ if (userItem) {
+ userItem.userName = item.nickName
+ }
+ return res
+ })
+ break;
}
changeAgoraDevice()
}
@@ -1506,52 +1534,57 @@ const Meeting: React.FC = () => {
case '录制':
const setting = await JSON.parse(storage.getItem('setting') as string);
try {
- await fs.access(setting.recordingFilesPath, fs.constants.F_OK);
- footerListTemplate[itemIndex][rowIndex].title = '录制中';
- footerListTemplate[itemIndex][rowIndex].active = true;
- setFooterList(footerListTemplate);
- window.electron.getSources().then(async (sources: any) => {
- const screenId = sources[0].id;
- const stream = await navigator.mediaDevices.getUserMedia({
- audio: {
- mandatory: {
- chromeMediaSource: 'desktop',
- chromeMediaSourceId: screenId,
- }
- } as any,
- video: {
- mandatory: {
- chromeMediaSource: 'desktop',
- chromeMediaSourceId: screenId,
- }
- } as any
+ if (!isClickedMediaSteam) {
+ setIsClickedMediaSteam(true)
+ await fs.access(setting.recordingFilesPath, fs.constants.F_OK);
+ footerListTemplate[itemIndex][rowIndex].title = '录制中';
+ footerListTemplate[itemIndex][rowIndex].active = true;
+ setFooterList(footerListTemplate);
+ window.electron.getSources().then(async (sources: any) => {
+ const screenId = sources[0].id;
+ const stream = await navigator.mediaDevices.getUserMedia({
+ audio: {
+ mandatory: {
+ chromeMediaSource: 'desktop',
+ chromeMediaSourceId: screenId,
+ }
+ } as any,
+ video: {
+ mandatory: {
+ chromeMediaSource: 'desktop',
+ chromeMediaSourceId: screenId,
+ }
+ } as any
+ });
+ // 获取所有音频输入设备
+ const devices = await navigator.mediaDevices.enumerateDevices();
+ const audioInputDevices = devices.filter(device => device.kind === 'audioinput' &&
+ device.deviceId !== 'default' &&
+ device.deviceId !== 'communications');
+ // 使用Web Audio API来捕获系统声音和麦克风声音,将它们合并到同一个MediaStream中。
+ const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)();
+ const systemSoundSource = audioCtx.createMediaStreamSource(stream);
+ const systemSoundDestination = audioCtx.createMediaStreamDestination();
+ systemSoundSource.connect(systemSoundDestination);
+ // 录制所有音频输入设备
+ audioInputDevices.forEach(async device => {
+ const micStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: device.deviceId } } });
+ setMediaStream((res: any) => [...res, micStream]);
+ const micSoundSource = audioCtx.createMediaStreamSource(micStream);
+ micSoundSource.connect(systemSoundDestination);
+ })
+ // 合并音频流与视频流
+ const combinedSource = new MediaStream([...stream.getVideoTracks(), ...systemSoundDestination.stream.getAudioTracks()]);
+ // 开始录制
+ const mediaRecorder = new MediaRecorder(combinedSource, {
+ mimeType: 'video/webm;codecs=vp9,opus',
+ videoBitsPerSecond: 1.5e6,
+ });
+ setRecorder(mediaRecorder);
});
- // 获取所有音频输入设备
- const devices = await navigator.mediaDevices.enumerateDevices();
- const audioInputDevices = devices.filter(device => device.kind === 'audioinput' &&
- device.deviceId !== 'default' &&
- device.deviceId !== 'communications');
- // 使用Web Audio API来捕获系统声音和麦克风声音,将它们合并到同一个MediaStream中。
- const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)();
- const systemSoundSource = audioCtx.createMediaStreamSource(stream);
- const systemSoundDestination = audioCtx.createMediaStreamDestination();
- systemSoundSource.connect(systemSoundDestination);
- // 录制所有音频输入设备
- audioInputDevices.forEach(async device => {
- const micStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: device.deviceId } } });
- setMediaStream((res: any) => [...res, micStream]);
- const micSoundSource = audioCtx.createMediaStreamSource(micStream);
- micSoundSource.connect(systemSoundDestination);
- })
- // 合并音频流与视频流
- const combinedSource = new MediaStream([...stream.getVideoTracks(), ...systemSoundDestination.stream.getAudioTracks()]);
- // 开始录制
- const mediaRecorder = new MediaRecorder(combinedSource, {
- mimeType: 'video/webm;codecs=vp9,opus',
- videoBitsPerSecond: 1.5e6,
- });
- setRecorder(mediaRecorder);
- });
+ } else {
+ message.error('录制太频繁了,请稍后重试!');
+ }
} catch (error: any) {
if (error.code === 'ENOENT') {
message.error({
@@ -1567,10 +1600,14 @@ const Meeting: React.FC = () => {
break;
case '录制中':
- footerListTemplate[itemIndex][rowIndex].title = '录制'
- footerListTemplate[itemIndex][rowIndex].active = false
- setFooterList(footerListTemplate)
- stopRecorderMedia()
+ if (isClickedMediaSteam) {
+ message.error('录制时长不足3秒,请稍后重试!');
+ } else {
+ footerListTemplate[itemIndex][rowIndex].title = '录制'
+ footerListTemplate[itemIndex][rowIndex].active = false
+ setFooterList(footerListTemplate)
+ stopRecorderMedia()
+ }
break;
case '共享文件':
sharedFilesModelRef.current.getData()
@@ -2329,6 +2366,17 @@ const Meeting: React.FC = () => {
getRoomKickout(state.channelId, item.uid, item.userName)
}}
>移出会议 : null}
+ {item.uid !== user.uid ? : null}
}>
@@ -2487,6 +2535,18 @@ const Meeting: React.FC = () => {
getRoomKickout(state.channelId, item.uid, item.userName)
}}
>移出会议
+
}>
@@ -2995,6 +3055,7 @@ const Meeting: React.FC = () => {
+
>
)
}