This commit is contained in:
parent
20132c3086
commit
1b02462e4b
|
|
@ -93,3 +93,8 @@ export const PostRoomInvite = (roomId: string, data: any) =>
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
export const GetShowUser = (roomNum: string) =>
|
||||||
|
request({
|
||||||
|
url: `/room/show-user?roomNum=${roomNum}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,47 @@
|
||||||
.sharedFilesModel {
|
.sharedFilesModel {
|
||||||
> div:nth-child(1) {
|
>div:nth-child(1) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
> span {
|
>div:nth-child(1) {
|
||||||
color: #EEEEEE;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> div {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
> span {
|
>span {
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
>span {
|
||||||
|
color: #EEEEEE;
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>div:nth-child(2) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
>span {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> div:nth-child(2) {
|
>div:nth-child(2) {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.updateDiv {
|
|
||||||
color: #ffffff;
|
|
||||||
|
|
||||||
.ant-progress .ant-progress-text {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -6,14 +6,14 @@ import {
|
||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
VerticalAlignBottomOutlined
|
VerticalAlignBottomOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {Button, Input, message, Modal, Pagination, Progress, Table} from 'antd';
|
import { Button, Input, message, Modal, Pagination, Progress, Table } from 'antd';
|
||||||
import {forwardRef, useEffect, useImperativeHandle, useState} from "react";
|
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
||||||
import {DeleteRoomFile, GetRoomFile, GetRoomFileDwUrl, GetRoomUpFileurl, PostRoomFile} from '@/api/Meeting';
|
import { DeleteRoomFile, GetRoomFile, GetRoomFileDwUrl, GetRoomUpFileurl, PostRoomFile } from '@/api/Meeting';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {useLocation} from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import {storage} from '@/utils';
|
import { storage } from '@/utils';
|
||||||
|
|
||||||
const {Column} = Table
|
const { Column } = Table
|
||||||
|
|
||||||
const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
@ -21,7 +21,7 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
setIsSharedFilesModel(true)
|
setIsSharedFilesModel(true)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
const {state} = useLocation();
|
const { state } = useLocation();
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||||
const [showRowSelection, setShowRowSelection] = useState(false);
|
const [showRowSelection, setShowRowSelection] = useState(false);
|
||||||
const [isSharedFilesModel, setIsSharedFilesModel] = useState(false);
|
const [isSharedFilesModel, setIsSharedFilesModel] = useState(false);
|
||||||
|
|
@ -74,18 +74,24 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.sharedFilesModel}>
|
<div className={styles.sharedFilesModel}>
|
||||||
<div className={styles.updateDiv}>
|
<div>
|
||||||
<span>共{fileList.total}个文件</span>
|
|
||||||
<div>
|
<div>
|
||||||
<Progress percent={uploadProgress} strokeColor={'green'} trailColor={'#e8e8e8'}
|
<span>
|
||||||
percentPosition={{align: 'center', type: 'inner'}}
|
共{fileList.total}个文件
|
||||||
size={{width: 100, height: 20}}/>
|
</span>
|
||||||
|
<div>
|
||||||
|
<span>上传进度:</span>
|
||||||
|
{/* <span>{uploadProgress === 100 ? '上传完成' : '上传中'} </span> */}
|
||||||
|
<Progress percent={uploadProgress} trailColor={'#e8e8e8'}
|
||||||
|
percentPosition={{ align: 'center', type: 'inner' }}
|
||||||
|
size={{ width: 100, height: 20 }} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{color: 'white'}}>
|
<div style={{ color: 'white' }}>
|
||||||
<Input
|
<Input
|
||||||
placeholder="搜索"
|
placeholder="搜索"
|
||||||
style={{width: '200px'}}
|
style={{ width: '200px' }}
|
||||||
prefix={<SearchOutlined style={{color: 'white'}}/>}
|
prefix={<SearchOutlined style={{ color: 'white' }} />}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setFileList({
|
setFileList({
|
||||||
...fileList,
|
...fileList,
|
||||||
|
|
@ -122,10 +128,10 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
pageIndex: 1
|
pageIndex: 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}}/>
|
}} />
|
||||||
<ProfileOutlined title={showRowSelection ? '取消框选' : '显示框选'} onClick={() => {
|
<ProfileOutlined title={showRowSelection ? '取消框选' : '显示框选'} onClick={() => {
|
||||||
setShowRowSelection(!showRowSelection)
|
setShowRowSelection(!showRowSelection)
|
||||||
}} style={{color: showRowSelection ? '#5575F2' : 'white'}}/>
|
}} style={{ color: showRowSelection ? '#5575F2' : 'white' }} />
|
||||||
{showRowSelection ? <DeleteOutlined title='删除' onClick={() => {
|
{showRowSelection ? <DeleteOutlined title='删除' onClick={() => {
|
||||||
if (selectedRowKeys.length) {
|
if (selectedRowKeys.length) {
|
||||||
DeleteRoomFile(selectedRowKeys).then(res => {
|
DeleteRoomFile(selectedRowKeys).then(res => {
|
||||||
|
|
@ -137,57 +143,56 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
} else {
|
} else {
|
||||||
message.error('请选择文件!')
|
message.error('请选择文件!')
|
||||||
}
|
}
|
||||||
}}/> : null}
|
}} /> : null}
|
||||||
<Button type="primary" style={{backgroundColor: '#31353A'}}
|
<Button type="primary" style={{ backgroundColor: '#31353A' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const file = document.createElement("input") as any;
|
const file = document.createElement("input") as any;
|
||||||
file.accept = "image/*,.doc,.docx,.ppt,.pptx,.xls,.xlsx,application/pdf";
|
file.accept = "image/*,.doc,.docx,.ppt,.pptx,.xls,.xlsx,application/pdf";
|
||||||
file.type = "file";
|
file.type = "file";
|
||||||
file.onchange = async () => {
|
file.onchange = async () => {
|
||||||
const fileInfo = file.files[0];
|
const fileInfo = file.files[0];
|
||||||
const maxSize = 100 * 1024 * 1024; // 100MB in bytes
|
const maxSize = 100 * 1024 * 1024; // 100MB in bytes
|
||||||
|
|
||||||
if (fileInfo.size > maxSize) {
|
if (fileInfo.size > maxSize) {
|
||||||
message.error('文件太大!请上传小于100MB的文件。')
|
message.error('文件太大!请上传小于100MB的文件。')
|
||||||
// 清除文件输入框的值,以便用户可以选择其他文件
|
// 清除文件输入框的值,以便用户可以选择其他文件
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const fileType = fileInfo.name.split('.');
|
const fileType = fileInfo.name.split('.');
|
||||||
const fileTypeName = fileType[fileType.length - 1];
|
const fileTypeName = fileType[fileType.length - 1];
|
||||||
await GetRoomUpFileurl(state.channelId, fileTypeName).then(async res => {
|
await GetRoomUpFileurl(state.channelId, fileTypeName).then(async res => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("name", fileInfo.name);
|
formData.append("name", fileInfo.name);
|
||||||
formData.append("OSSAccessKeyId", res.data.ossAccessKeyId);
|
formData.append("OSSAccessKeyId", res.data.ossAccessKeyId);
|
||||||
formData.append("key", res.data.key);
|
formData.append("key", res.data.key);
|
||||||
formData.append("policy", res.data.policy);
|
formData.append("policy", res.data.policy);
|
||||||
formData.append("signature", res.data.signature);
|
formData.append("signature", res.data.signature);
|
||||||
formData.append("success_action_status", res.data.success_action_status);
|
formData.append("success_action_status", res.data.success_action_status);
|
||||||
formData.append("file", fileInfo);
|
formData.append("file", fileInfo);
|
||||||
await axios.post(res.data.host, formData, {
|
await axios.post(res.data.host, formData, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "multipart/form-data",
|
"Content-Type": "multipart/form-data",
|
||||||
"Authorization": `Bearer ${user.token}`
|
"Authorization": `Bearer ${user.token}`
|
||||||
},
|
},
|
||||||
withCredentials: false,
|
withCredentials: false,
|
||||||
onUploadProgress: (progressEvent: any) => {
|
onUploadProgress: (progressEvent: any) => {
|
||||||
// 获取上传进度
|
// 获取上传进度
|
||||||
const {loaded, total} = progressEvent;
|
const { loaded, total } = progressEvent;
|
||||||
const progress = Math.round((loaded * 100) / total);
|
const progress = Math.round((loaded * 100) / total);
|
||||||
console.log(`上传进度: ${progress}%`);
|
setUploadProgress(progress)
|
||||||
setUploadProgress(progress)
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
await PostRoomFile({
|
|
||||||
fileUrl: res.data.key,
|
|
||||||
size: fileInfo.size,
|
|
||||||
fileName: fileInfo.name,
|
|
||||||
roomId: state.roomId
|
|
||||||
})
|
|
||||||
getRoomFile()
|
|
||||||
})
|
})
|
||||||
};
|
await PostRoomFile({
|
||||||
file.click();
|
fileUrl: res.data.key,
|
||||||
}}
|
size: fileInfo.size,
|
||||||
|
fileName: fileInfo.name,
|
||||||
|
roomId: state.roomId
|
||||||
|
})
|
||||||
|
getRoomFile()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
file.click();
|
||||||
|
}}
|
||||||
>上传</Button>
|
>上传</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -202,130 +207,97 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
|
||||||
} : undefined}
|
} : undefined}
|
||||||
dataSource={fileList.data}
|
dataSource={fileList.data}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
scroll={{y: '40vh'}}
|
scroll={{ y: '40vh' }}
|
||||||
style={{width: '100%'}}
|
style={{ width: '100%' }}
|
||||||
>
|
>
|
||||||
<Column title="文件" dataIndex="fileName" key="fileName" width={140}/>
|
<Column title="文件" width={140}
|
||||||
<Column title="更新时间" dataIndex="modifyTime" key="modifyTime" width={200}/>
|
render={(item) => (
|
||||||
|
<>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||||
|
<span>{item.fileName}</span>
|
||||||
|
<span>
|
||||||
|
{item.showPercentComplete ? <Progress percent={item.percentComplete} trailColor={'#e8e8e8'}
|
||||||
|
percentPosition={{ align: 'center', type: 'inner' }}
|
||||||
|
size={{ width: 40, height: 10 }} /> : null}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Column title="更新时间" dataIndex="modifyTime" key="modifyTime" width={200} />
|
||||||
<Column title="大小" render={(item) => (
|
<Column title="大小" render={(item) => (
|
||||||
<>
|
<>
|
||||||
<span>{item.size / 1024 > 1000 ? (item.size / (1024 * 1024)).toFixed(2) + 'MB' : (item.size / 1024).toFixed(2) + 'KB'}</span>
|
<span>{item.size / 1024 > 1000 ? (item.size / (1024 * 1024)).toFixed(2) + 'MB' : (item.size / 1024).toFixed(2) + 'KB'}</span>
|
||||||
</>
|
</>
|
||||||
)}/>
|
)} />
|
||||||
<Column title="上传者" dataIndex="userName" key="userName"/>
|
<Column title="上传者" dataIndex="userName" key="userName" />
|
||||||
<Column title="下载次数"
|
<Column title="下载次数"
|
||||||
render={(item) => (
|
render={(item) => (
|
||||||
<>
|
<>
|
||||||
<span>{item.downloadCount}次</span>
|
<span>{item.downloadCount}次</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Column title="操作" render={(item) => (
|
<Column title="操作" render={(item) => (
|
||||||
<>
|
<>
|
||||||
<VerticalAlignBottomOutlined title='下载'
|
<VerticalAlignBottomOutlined title='下载'
|
||||||
style={{color: '#5575F2', cursor: 'pointer'}}
|
style={{ color: '#5575F2', cursor: 'pointer' }}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
GetRoomFileDwUrl(item.fileUrl, item.id).then(res => {
|
GetRoomFileDwUrl(item.fileUrl, item.id).then(res => {
|
||||||
console.log(res)
|
if (res.code === 200) {
|
||||||
if (res.code === 200) {
|
axios({
|
||||||
// const downloadLink = document.createElement("a");
|
url: res.data,
|
||||||
// downloadLink.href = res.data;
|
method: 'GET',
|
||||||
// downloadLink.download = item.fileName;
|
onDownloadProgress: (progressEvent: any) => {
|
||||||
axios({
|
const totalLength = item.size;
|
||||||
url: res.data,
|
if (totalLength !== null) {
|
||||||
method: 'GET',
|
const percentComplete = (progressEvent.loaded / totalLength * 100).toFixed(2);
|
||||||
// headers: {
|
const fileIndex = fileList.data.findIndex((row: any) => row.id === item.id);
|
||||||
// "Authorization": `Bearer ${user.token}`,
|
let fileItem = [...fileList.data] as any;
|
||||||
// "responseType": 'stream'
|
fileItem[fileIndex].percentComplete = percentComplete
|
||||||
// },
|
fileItem[fileIndex].showPercentComplete = true
|
||||||
onDownloadProgress: (progressEvent: any) => {
|
setFileList({
|
||||||
const totalLength = item.size;
|
...fileList,
|
||||||
console.log(2222222)
|
data: fileItem,
|
||||||
if (totalLength !== null) {
|
})
|
||||||
const percentComplete = (progressEvent.loaded / totalLength * 100).toFixed(2);
|
}
|
||||||
console.log(`下载进度: ${percentComplete}%`);
|
}
|
||||||
item.percentComplete = percentComplete
|
}).then(() => {
|
||||||
}
|
const fileIndex = fileList.data.findIndex((row: any) => row.id === item.id);
|
||||||
}
|
let fileItem = [...fileList.data] as any;
|
||||||
}).then(() => {
|
fileItem[fileIndex].percentComplete = 100
|
||||||
const downloadLink = document.createElement("a");
|
setTimeout(() => {
|
||||||
downloadLink.href = res.data;
|
fileItem[fileIndex].showPercentComplete = false
|
||||||
downloadLink.download = item.fileName;
|
}, 3000)
|
||||||
downloadLink.click();
|
setFileList({
|
||||||
getRoomFile()
|
...fileList,
|
||||||
})
|
data: fileItem,
|
||||||
// downloadLink.click();
|
})
|
||||||
// getRoomFile()
|
const downloadLink = document.createElement("a");
|
||||||
}
|
downloadLink.href = res.data;
|
||||||
})
|
downloadLink.download = item.fileName;
|
||||||
|
downloadLink.click();
|
||||||
|
getRoomFile()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// const url = "https://wgshare.oss-cn-chengdu.aliyuncs.com/share_file/559167236182085/20421555/b24e2c41f47140308c47cdd77e6305c7.jpg?Expires=1722923931&OSSAccessKeyId=LTAI5tQYVQHkkXxXTmjwiSDv&Signature=eJTWD93ifV2v1R6XCHSOa6j1R%2FE%3D"
|
}} />
|
||||||
// axios({
|
|
||||||
// url,
|
|
||||||
// method: 'GET',
|
|
||||||
// // headers: {
|
|
||||||
// // "Authorization": `Bearer ${user.token}`,
|
|
||||||
// // "responseType": 'stream'
|
|
||||||
// // },
|
|
||||||
// onDownloadProgress: (progressEvent: any) => {
|
|
||||||
// const totalLength = item.size;
|
|
||||||
// console.log(2222222)
|
|
||||||
// if (totalLength !== null) {
|
|
||||||
// const percentComplete = (progressEvent.loaded / totalLength * 100).toFixed(2);
|
|
||||||
// console.log(`下载进度: ${percentComplete}%`);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .then((response: any) => {
|
|
||||||
// const downloadLink = document.createElement("a");
|
|
||||||
// downloadLink.href = response.data;
|
|
||||||
// downloadLink.download = item.fileName;
|
|
||||||
// downloadLink.click();
|
|
||||||
// getRoomFile()
|
|
||||||
// })
|
|
||||||
|
|
||||||
// await axios.get(`${import.meta.env.VITE_BASE_URL_API}/room/file-dw-url?fileUrl=${item.fileUrl}&fileId=${item.id}`, {
|
|
||||||
// headers: {
|
|
||||||
// "Authorization": `Bearer ${user.token}`,
|
|
||||||
// "responseType": 'stream'
|
|
||||||
// },
|
|
||||||
// onDownloadProgress: (progressEvent: any) => {
|
|
||||||
// const totalLength = item.size;
|
|
||||||
// const percentComplete = (progressEvent.loaded / totalLength * 100).toFixed(2);
|
|
||||||
// console.log(`下载进度: ${percentComplete}%`);
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// await axios.get(`${import.meta.env.VITE_BASE_URL_API}/room/file-dw-url?fileUrl=${item.fileUrl}&fileId=${item.id}`, {
|
|
||||||
// headers: {
|
|
||||||
// "ResponseType": "blob",
|
|
||||||
// "Authorization": `Bearer ${user.token}`
|
|
||||||
// },
|
|
||||||
// withCredentials: false,
|
|
||||||
// onDownloadProgress: (progressEvent: any) => {
|
|
||||||
// console.log(progressEvent, 33333)
|
|
||||||
// // 获取上传进度
|
|
||||||
// const {loaded, total} = progressEvent;
|
|
||||||
// const progress = Math.round((loaded * 100) / total);
|
|
||||||
// console.log(`下载进度: ${progress}%`);
|
|
||||||
// setUploadProgress(progress)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
}}/>
|
|
||||||
{/* <FolderOutlined title='文件' style={{ color: '#FFA000', cursor: 'pointer' }} /> */}
|
{/* <FolderOutlined title='文件' style={{ color: '#FFA000', cursor: 'pointer' }} /> */}
|
||||||
</>
|
</>
|
||||||
)}/>
|
)} />
|
||||||
</Table>
|
</Table>
|
||||||
<div style={{display: 'flex', justifyContent: 'center', marginTop: '10px'}}>
|
<div style={{ display: 'flex', justifyContent: 'center', marginTop: '10px' }}>
|
||||||
<Pagination size="small" total={fileList.total} onChange={(e) => {
|
<Pagination size="small" total={fileList.total} onChange={(e) => {
|
||||||
setFileList({
|
setFileList({
|
||||||
...fileList,
|
...fileList,
|
||||||
pageIndex: e
|
pageIndex: e
|
||||||
})
|
})
|
||||||
}} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true}/>
|
}} pageSize={fileList.pageSize} current={fileList.pageIndex} hideOnSinglePage={true} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'flex-end'}}>
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ const Index: React.FC = () => {
|
||||||
maxLength={8}
|
maxLength={8}
|
||||||
value={createRoomFrom.roomNum}
|
value={createRoomFrom.roomNum}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const regex = /^[0-9 ]*$/;
|
const regex = /^[0-9]*$/;
|
||||||
if (regex.test(e.target.value)) {
|
if (regex.test(e.target.value)) {
|
||||||
setCreateRoomFrom({
|
setCreateRoomFrom({
|
||||||
...createRoomFrom,
|
...createRoomFrom,
|
||||||
|
|
|
||||||
|
|
@ -225,10 +225,13 @@ const User: React.FC = () => {
|
||||||
showCount={true}
|
showCount={true}
|
||||||
value={addUserFrom.Account}
|
value={addUserFrom.Account}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setAddUserFrom({
|
const regex = /^[0-9]*$/;
|
||||||
...addUserFrom,
|
if (regex.test(e.target.value)) {
|
||||||
Account: e.target.value,
|
setAddUserFrom({
|
||||||
});
|
...addUserFrom,
|
||||||
|
Account: e.target.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ const Login: React.FC = () => {
|
||||||
if (!operation.account) {
|
if (!operation.account) {
|
||||||
return message.error('请输入账号!')
|
return message.error('请输入账号!')
|
||||||
}
|
}
|
||||||
operation.password = "";
|
|
||||||
GetCheckUser(operation.account).then(res => {
|
GetCheckUser(operation.account).then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
res.data ? setAccountPasswordStatus(true) : message.error('账号不存在!')
|
res.data ? setAccountPasswordStatus(true) : message.error('账号不存在!')
|
||||||
|
|
|
||||||
|
|
@ -694,7 +694,7 @@
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
>div {
|
>div {
|
||||||
// border: 1px solid #EBEBEB;
|
border: 1px solid #EBEBEB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { SearchOutlined } from '@ant-design/icons';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { thumbImageBufferToBase64 } from '@/utils/package/base64'
|
import { thumbImageBufferToBase64 } from '@/utils/package/base64'
|
||||||
import { storage } from '@/utils';
|
import { storage } from '@/utils';
|
||||||
import { GetRoomUser, PostOpenMicr, PostOpenCamera, PostRoomManager, DeleteRoomManager, GetRoomKickout } from '@/api/Meeting';
|
import { GetRoomUser, PostOpenMicr, PostOpenCamera, PostRoomManager, DeleteRoomManager, GetRoomKickout, GetShowUser } from '@/api/Meeting';
|
||||||
import ImageUrl from '@/utils/package/ImageUrl'
|
import ImageUrl from '@/utils/package/ImageUrl'
|
||||||
import agora from '@/utils/package/agora'
|
import agora from '@/utils/package/agora'
|
||||||
import { onInvoke, onSignalr, offSignalr, onStart } from '@/utils/package/signalr';
|
import { onInvoke, onSignalr, offSignalr, onStart } from '@/utils/package/signalr';
|
||||||
|
|
@ -112,6 +112,7 @@ const Meeting: React.FC = () => {
|
||||||
const [meetingMode, setMeetingMode] = useState('')
|
const [meetingMode, setMeetingMode] = useState('')
|
||||||
const [userSearchValue, setUserSearchValue] = useState('')
|
const [userSearchValue, setUserSearchValue] = useState('')
|
||||||
const [noViewChatList, setNoViewChatList] = useState(0)
|
const [noViewChatList, setNoViewChatList] = useState(0)
|
||||||
|
const [currentLookUserAccount, setCurrentLookUserAccount] = useState<string>('')
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let time = null as any;
|
let time = null as any;
|
||||||
let userInfo = JSON.parse(storage.getItem('user') as string)
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
|
|
@ -131,7 +132,9 @@ const Meeting: React.FC = () => {
|
||||||
account: Number(info.localUid),
|
account: Number(info.localUid),
|
||||||
view: document.getElementById(`video-${info.localUid}`) as HTMLElement,
|
view: document.getElementById(`video-${info.localUid}`) as HTMLElement,
|
||||||
channelId: info.channelId,
|
channelId: info.channelId,
|
||||||
|
sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
||||||
})
|
})
|
||||||
|
getShowUser();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
onUserJoined: async (info: any, remoteUid: any, _elapsed: any) => {
|
onUserJoined: async (info: any, remoteUid: any, _elapsed: any) => {
|
||||||
|
|
@ -155,7 +158,7 @@ const Meeting: React.FC = () => {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
agora.setCameraCapture(VideoSourceType.VideoSourceCameraPrimary)
|
agora.setCameraCapture()
|
||||||
agora.setJoinChannel({
|
agora.setJoinChannel({
|
||||||
channelId: state.channelId,
|
channelId: state.channelId,
|
||||||
userid: userInfo.account,
|
userid: userInfo.account,
|
||||||
|
|
@ -249,6 +252,27 @@ const Meeting: React.FC = () => {
|
||||||
|
|
||||||
}, [currentVideoId])
|
}, [currentVideoId])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const userItem = allUserList.find((item: any) => item.account === currentLookUserAccount)
|
||||||
|
if (userItem) {
|
||||||
|
if (userItem.account === user.account) {
|
||||||
|
// agora.setupLocalVideo({
|
||||||
|
// account: Number(userItem.account),
|
||||||
|
// view: document.getElementById(`look-video`) as HTMLElement,
|
||||||
|
// channelId: state.channelId,
|
||||||
|
// sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
||||||
|
// })
|
||||||
|
} else {
|
||||||
|
// agora.setupRemoteVideoJoin({
|
||||||
|
// account: Number(userItem.account),
|
||||||
|
// view: document.getElementById(`look-video`) as HTMLElement,
|
||||||
|
// channelId: state.channelId,
|
||||||
|
// sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [allUserList, currentLookUserAccount])
|
||||||
|
|
||||||
// 网络
|
// 网络
|
||||||
const handleNetworkChange = (): void => {
|
const handleNetworkChange = (): void => {
|
||||||
if (navigator.onLine) {
|
if (navigator.onLine) {
|
||||||
|
|
@ -267,6 +291,14 @@ const Meeting: React.FC = () => {
|
||||||
message.error('网络已断开!')
|
message.error('网络已断开!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 全员观看
|
||||||
|
const getShowUser = async (): Promise<void> => {
|
||||||
|
await GetShowUser(state.channelId).then(res => {
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
setCurrentLookUserAccount(res.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
// 加入房间时间
|
// 加入房间时间
|
||||||
const changeCurrentSeconds = (): string => {
|
const changeCurrentSeconds = (): string => {
|
||||||
const duration = dayjs.duration(currentSeconds, 'seconds');
|
const duration = dayjs.duration(currentSeconds, 'seconds');
|
||||||
|
|
@ -304,7 +336,7 @@ const Meeting: React.FC = () => {
|
||||||
setIsSharedScreenModal(true)
|
setIsSharedScreenModal(true)
|
||||||
break;
|
break;
|
||||||
case '停止共享':
|
case '停止共享':
|
||||||
agora.setCameraCapture(VideoSourceType.VideoSourceCameraPrimary)
|
agora.setCameraCapture()
|
||||||
footerListTemplate[itemIndex][rowIndex].title = '共享屏幕'
|
footerListTemplate[itemIndex][rowIndex].title = '共享屏幕'
|
||||||
break;
|
break;
|
||||||
case '关闭声音':
|
case '关闭声音':
|
||||||
|
|
@ -386,7 +418,7 @@ const Meeting: React.FC = () => {
|
||||||
const footerListTemplate = [...footerList]
|
const footerListTemplate = [...footerList]
|
||||||
footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享'
|
footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享'
|
||||||
setIsSharedScreenModal(false)
|
setIsSharedScreenModal(false)
|
||||||
agora.setDesktopCapturerVideo(sharedScreenItem, VideoSourceType.VideoSourceScreen)
|
agora.setDesktopCapturerVideo(sharedScreenItem)
|
||||||
} else {
|
} else {
|
||||||
message.error('请选择应用!')
|
message.error('请选择应用!')
|
||||||
}
|
}
|
||||||
|
|
@ -538,8 +570,8 @@ const Meeting: React.FC = () => {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
// 设置单个视频样式
|
// 设置单个视频样式
|
||||||
const setMeetingContentSwiperCardClass = (account: string): string => {
|
const setMeetingContentSwiperCardClass = (account: string, bool: boolean = false): string => {
|
||||||
if (currentVideoId === account && (meetingMode === 'StandardMode' || meetingMode === 'SpeakerMode')) {
|
if ((bool || currentVideoId === account) && (meetingMode === 'StandardMode' || meetingMode === 'SpeakerMode')) {
|
||||||
switch (meetingMode) {
|
switch (meetingMode) {
|
||||||
case 'StandardMode':
|
case 'StandardMode':
|
||||||
return styles.meetingContentSwiperCardStandardMode
|
return styles.meetingContentSwiperCardStandardMode
|
||||||
|
|
@ -569,11 +601,12 @@ const Meeting: React.FC = () => {
|
||||||
<div className={styles.meetingContentBody}>
|
<div className={styles.meetingContentBody}>
|
||||||
<div className={`${styles.meetingContentBodyLeft} drag`}>
|
<div className={`${styles.meetingContentBodyLeft} drag`}>
|
||||||
<div className={getMeetingContentBodyLeftModeClass()} >
|
<div className={getMeetingContentBodyLeftModeClass()} >
|
||||||
|
{/* ${setMeetingContentSwiperCardClass(item.account)} */}
|
||||||
{allUserList.map((item: any, index: number) => {
|
{allUserList.map((item: any, index: number) => {
|
||||||
return (
|
return (
|
||||||
item.isRoom ?
|
item.isRoom ?
|
||||||
<div
|
<div
|
||||||
className={`${styles.meetingContentSwiperCard} ${setMeetingContentSwiperCardClass(item.account)}`}
|
className={`${styles.meetingContentSwiperCard}`}
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (footerList[1][3].active) {
|
if (footerList[1][3].active) {
|
||||||
|
|
@ -593,6 +626,19 @@ const Meeting: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
{currentLookUserAccount ?
|
||||||
|
<div className={`${styles.meetingContentSwiperCard} ${setMeetingContentSwiperCardClass(currentLookUserAccount)}`}>
|
||||||
|
<div className={`${styles.meetingContentSwiperCardVdeio}`} id={`look-video`}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div className={`${styles.meetingContentSwiperCard} ${setMeetingContentSwiperCardClass(currentLookUserAccount, true)}`}>
|
||||||
|
<div className={`${styles.meetingContentSwiperCardVdeio}`} style={{ color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
暂无视频
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ const option: any = {
|
||||||
token: '',
|
token: '',
|
||||||
channelId: '',
|
channelId: '',
|
||||||
userid: '',
|
userid: '',
|
||||||
sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
|
||||||
}
|
}
|
||||||
let iMediaRecorder: any = '';
|
let iMediaRecorder: any = '';
|
||||||
let rtcEngine: any = '';
|
let rtcEngine: any = '';
|
||||||
|
|
@ -80,19 +79,11 @@ const agora = {
|
||||||
setupLocalVideo: async (item: any) => {
|
setupLocalVideo: async (item: any) => {
|
||||||
await rtcEngine.setupLocalVideo({
|
await rtcEngine.setupLocalVideo({
|
||||||
renderMode: RenderModeType.RenderModeFit,
|
renderMode: RenderModeType.RenderModeFit,
|
||||||
sourceType: option.sourceType,
|
sourceType: item.sourceType,
|
||||||
uid: item.account,
|
uid: item.account,
|
||||||
view: item.view,
|
view: item.view,
|
||||||
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
setupMode: VideoViewSetupMode.VideoViewSetupAdd,
|
||||||
});
|
});
|
||||||
switch (option.sourceType) {
|
|
||||||
case VideoSourceType.VideoSourceCameraPrimary:
|
|
||||||
agora.updateChannelMediaOptions(true)
|
|
||||||
break;
|
|
||||||
case VideoSourceType.VideoSourceScreen:
|
|
||||||
agora.updateChannelMediaOptions(false)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 远端加入
|
// 远端加入
|
||||||
setupRemoteVideoJoin: async (item: any) => {
|
setupRemoteVideoJoin: async (item: any) => {
|
||||||
|
|
@ -135,33 +126,14 @@ const agora = {
|
||||||
},
|
},
|
||||||
// 加入频道
|
// 加入频道
|
||||||
joinChannel: () => {
|
joinChannel: () => {
|
||||||
rtcEngine.joinChannel(option.token, option.channelId, option.userid, {});
|
rtcEngine.joinChannel(option.token, option.channelId, option.userid, {
|
||||||
},
|
autoSubscribeAudio: true,
|
||||||
// 更新频道信息
|
autoSubscribeVideo: true,
|
||||||
updateChannelMediaOptions: (bool: boolean) => {
|
publishMicrophoneTrack: true,
|
||||||
if (bool) {
|
publishCameraTrack: true,
|
||||||
// 摄像头
|
clientRoleType: ClientRoleType.ClientRoleBroadcaster,
|
||||||
rtcEngine.updateChannelMediaOptions({
|
publishScreenTrack: false,
|
||||||
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting, //设置频道场景为直播场景
|
});
|
||||||
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //设置用户角色为主播;如果要将用户角色设置为观众,保持默认值即可
|
|
||||||
publishMicrophoneTrack: true, //发布麦克风采集的音频
|
|
||||||
publishCameraTrack: true, //发布摄像头采集的视频
|
|
||||||
publishScreenTrack: false, //设置是否发布屏幕采集的视频
|
|
||||||
autoSubscribeAudio: true, //自动订阅所有音频流
|
|
||||||
autoSubscribeVideo: true, //自动订阅所有视频流
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 屏幕
|
|
||||||
rtcEngine.updateChannelMediaOptions({
|
|
||||||
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting, //设置频道场景为直播场景
|
|
||||||
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //用户角色 1主播 2观众
|
|
||||||
publishMicrophoneTrack: true, //设置是否发布麦克风采集到的音频
|
|
||||||
publishCameraTrack: false, //设置是否发布摄像头采集的视频
|
|
||||||
publishScreenTrack: true, //设置是否发布屏幕采集的视频
|
|
||||||
autoSubscribeAudio: true, //设置是否自动订阅所有音频流
|
|
||||||
autoSubscribeVideo: true, //设置是否自动订阅所有视频流
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 停止共享屏幕
|
// 停止共享屏幕
|
||||||
stopScreenCapture: () => {
|
stopScreenCapture: () => {
|
||||||
|
|
@ -176,17 +148,15 @@ const agora = {
|
||||||
rtcEngine.muteLocalVideoStream(mute)
|
rtcEngine.muteLocalVideoStream(mute)
|
||||||
},
|
},
|
||||||
// 摄像头采集
|
// 摄像头采集
|
||||||
setCameraCapture: (sourceType: number) => {
|
setCameraCapture: () => {
|
||||||
agora.stopScreenCapture()
|
agora.stopScreenCapture()
|
||||||
if (sourceType !== option.sourceType) {
|
// rtcEngine.destroyRendererByConfig(option.sourceType, option.channelId, option.account)
|
||||||
rtcEngine.destroyRendererByConfig(option.sourceType, option.channelId, option.account)
|
agora.setupLocalVideo({
|
||||||
option.sourceType = sourceType
|
account: Number(option.userid),
|
||||||
agora.setupLocalVideo({
|
view: document.getElementById(`video-${option.userid}`),
|
||||||
account: Number(option.userid),
|
channelId: option.channelId,
|
||||||
view: document.getElementById(`video-${option.userid}`),
|
sourceType: VideoSourceType.VideoSourceCameraPrimary,
|
||||||
channelId: option.channelId,
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
||||||
},
|
},
|
||||||
// 加入频道
|
// 加入频道
|
||||||
|
|
@ -201,18 +171,28 @@ const agora = {
|
||||||
return rtcEngine.getScreenCaptureSources({ width: 300, height: 300 }, { width: 300, height: 300 }, true);
|
return rtcEngine.getScreenCaptureSources({ width: 300, height: 300 }, { width: 300, height: 300 }, true);
|
||||||
},
|
},
|
||||||
// 共享屏幕采集
|
// 共享屏幕采集
|
||||||
setDesktopCapturerVideo: async (targetSource: any, sourceType: number) => {
|
setDesktopCapturerVideo: async (targetSource: any) => {
|
||||||
if (sourceType !== option.sourceType) {
|
// await rtcEngine.stopCameraCapture(option.sourceType)
|
||||||
await rtcEngine.stopCameraCapture(option.sourceType)
|
// rtcEngine.destroyRendererByConfig(option.sourceType, option.channelId, option.account)
|
||||||
rtcEngine.destroyRendererByConfig(option.sourceType, option.channelId, option.account)
|
await agora.setupLocalVideo({
|
||||||
option.sourceType = sourceType
|
account: Number(option.userid),
|
||||||
agora.setupLocalVideo({
|
view: document.getElementById(`look-video`),
|
||||||
account: Number(option.userid),
|
channelId: option.channelId,
|
||||||
view: document.getElementById(`video-${option.userid}`),
|
sourceType: VideoSourceType.VideoSourceScreen,
|
||||||
channelId: option.channelId,
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
agora.stopScreenCapture();
|
agora.stopScreenCapture();
|
||||||
|
rtcEngine.joinChannelEx(
|
||||||
|
option.token,
|
||||||
|
{ channelId: option.channelId, localUid: option.account },
|
||||||
|
{
|
||||||
|
autoSubscribeAudio: false,
|
||||||
|
autoSubscribeVideo: false,
|
||||||
|
publishMicrophoneTrack: false,
|
||||||
|
publishCameraTrack: false,
|
||||||
|
clientRoleType: ClientRoleType.ClientRoleBroadcaster,
|
||||||
|
publishScreenTrack: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
targetSource.type ===
|
targetSource.type ===
|
||||||
ScreenCaptureSourceType.ScreencapturesourcetypeScreen
|
ScreenCaptureSourceType.ScreencapturesourcetypeScreen
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,12 @@ class Request {
|
||||||
message.error(resData.message)
|
message.error(resData.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (resData.code === 1403) {
|
||||||
|
setTimeout(() => {
|
||||||
|
storage.removeItem('user')
|
||||||
|
location.href = location.origin + '/#/login'
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
return resData
|
return resData
|
||||||
},
|
},
|
||||||
(err: any) => {
|
(err: any) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue