首页人员
This commit is contained in:
parent
375fb2a022
commit
12859e9e0b
25
main.js
25
main.js
|
|
@ -1,4 +1,4 @@
|
|||
const { app, systemPreferences, BrowserWindow, screen, Tray, nativeImage, Menu, ipcMain } = require('electron');
|
||||
const { app, BrowserWindow, screen, Tray, nativeImage, Menu, ipcMain, clipboard } = require('electron');
|
||||
const path = require('node:path')
|
||||
app.allowRendererProcessReuse = false;
|
||||
let mainWindow = null;
|
||||
|
|
@ -141,6 +141,12 @@ app.on('ready', () => {
|
|||
ipcMain.handle('getIsMaximized', () => {
|
||||
return mainWindow.isMaximized();
|
||||
});
|
||||
|
||||
// 复制文字
|
||||
ipcMain.handle('setWriteText', (event, text) => {
|
||||
clipboard.writeText(text)
|
||||
});
|
||||
|
||||
// 设置桌面应用基础属性
|
||||
ipcMain.handle('setMainWindowSize', (event, config) => {
|
||||
// 设置最小窗口尺寸
|
||||
|
|
@ -163,20 +169,3 @@ app.on('ready', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// 检查并获取设备权限
|
||||
async function checkAndApplyDeviceAccessPrivilege() {
|
||||
// 检查并获取摄像头权限
|
||||
const cameraPrivilege = systemPreferences.getMediaAccessStatus('camera');
|
||||
if (cameraPrivilege !== 'granted') {
|
||||
await systemPreferences.askForMediaAccess('camera');
|
||||
}
|
||||
|
||||
// 检查并获取麦克风权限
|
||||
const micPrivilege = systemPreferences.getMediaAccessStatus('microphone');
|
||||
if (micPrivilege !== 'granted') {
|
||||
await systemPreferences.askForMediaAccess('microphone');
|
||||
}
|
||||
}
|
||||
|
||||
checkAndApplyDeviceAccessPrivilege();
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.11",
|
||||
"electron-squirrel-startup": "^1.0.1",
|
||||
"js-md5": "^0.8.3",
|
||||
"path": "^0.12.7",
|
||||
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
||||
"react": "^18.3.1",
|
||||
|
|
@ -8783,6 +8784,11 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/js-md5": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz",
|
||||
"integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ=="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
|
@ -20730,6 +20736,11 @@
|
|||
"is-object": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"js-md5": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz",
|
||||
"integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.11",
|
||||
"electron-squirrel-startup": "^1.0.1",
|
||||
"js-md5": "^0.8.3",
|
||||
"path": "^0.12.7",
|
||||
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
||||
"react": "^18.3.1",
|
||||
|
|
|
|||
140
preload.js
140
preload.js
|
|
@ -7,7 +7,9 @@ const {
|
|||
VideoViewSetupMode,
|
||||
ScreenCaptureSourceType,
|
||||
RenderModeType,
|
||||
ChannelProfileType
|
||||
ChannelProfileType,
|
||||
MediaRecorderContainerFormat,
|
||||
MediaRecorderStreamType
|
||||
} = require("agora-electron-sdk");
|
||||
const agoraAonfig = require('./src/utils/package/agoraConfig');
|
||||
const { message } = require('antd');
|
||||
|
|
@ -15,16 +17,54 @@ const rtcEngine = createAgoraRtcEngine();
|
|||
rtcEngine.initialize({
|
||||
appId: agoraAonfig.appid,
|
||||
});
|
||||
|
||||
let videoID = '';
|
||||
let iMediaRecorder = '';
|
||||
|
||||
const getDom = () => {
|
||||
return document.getElementById(videoID);
|
||||
}
|
||||
// 离开频道
|
||||
const leaveChannel = () => {
|
||||
rtcEngine.leaveChannel({
|
||||
stopAudioMixing: true,
|
||||
stopAllEffect: true,
|
||||
stopMicrophoneRecording: true,
|
||||
})
|
||||
}
|
||||
// 离开频道
|
||||
const joinChannel = (bool) => {
|
||||
if (bool) {
|
||||
rtcEngine.joinChannel(agoraAonfig.token, agoraAonfig.channelId, 123, {
|
||||
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting, //设置频道场景为直播场景
|
||||
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //用户角色 1主播 2观众
|
||||
publishMicrophoneTrack: true, //设置是否发布麦克风采集到的音频
|
||||
publishCameraTrack: false, //设置是否发布摄像头采集的视频
|
||||
publishScreenTrack: true, //设置是否发布屏幕采集的视频
|
||||
autoSubscribeAudio: true, //设置是否自动订阅所有音频流
|
||||
autoSubscribeVideo: true, //设置是否自动订阅所有视频流
|
||||
});
|
||||
} else {
|
||||
rtcEngine.joinChannel(agoraAonfig.token, agoraAonfig.channelId, 123, {
|
||||
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting, //设置频道场景为直播场景
|
||||
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //设置用户角色为主播;如果要将用户角色设置为观众,保持默认值即可
|
||||
publishMicrophoneTrack: true, //发布麦克风采集的音频
|
||||
publishCameraTrack: true, //发布摄像头采集的视频
|
||||
publishScreenTrack: false, //设置是否发布屏幕采集的视频
|
||||
autoSubscribeAudio: true, //自动订阅所有音频流
|
||||
autoSubscribeVideo: true, //自动订阅所有视频流
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const EventHandles = {
|
||||
// 停止共享屏幕
|
||||
const stopScreenCapture = () => {
|
||||
rtcEngine.stopScreenCapture();
|
||||
}
|
||||
|
||||
rtcEngine.registerEventHandler({
|
||||
// 监听本地用户加入频道事件
|
||||
onJoinChannelSuccess: ({ channelId, localUid }, elapsed) => {
|
||||
console.log({ channelId, localUid });
|
||||
console.log({ channelId, localUid }, elapsed, '加入房间');
|
||||
// 本地用户加入频道后,设置本地视频窗口
|
||||
rtcEngine.setupLocalVideo({
|
||||
renderMode: RenderModeType.RenderModeFit,
|
||||
|
|
@ -50,6 +90,18 @@ const EventHandles = {
|
|||
);
|
||||
|
||||
},
|
||||
// 视频发布状态改变回调
|
||||
onVideoPublishStateChanged: (source, channel, oldState, newState, elapseSinceLastState) => {
|
||||
if (newState === 1) {
|
||||
|
||||
}
|
||||
},
|
||||
// 音频发布状态改变回调
|
||||
onAudioPublishStateChanged: (channel, oldState, newState, elapseSinceLastState) => {
|
||||
if (newState === 1) {
|
||||
|
||||
}
|
||||
},
|
||||
// 监听用户离开频道事件
|
||||
onUserOffline: ({ channelId, localUid }, remoteUid, reason) => {
|
||||
// 远端用户离开频道后,关闭远端视频窗口
|
||||
|
|
@ -70,8 +122,7 @@ const EventHandles = {
|
|||
document.getElementById('recordingDeviceTest').style.width = `${percentage}%`
|
||||
}
|
||||
}
|
||||
};
|
||||
rtcEngine.registerEventHandler(EventHandles);
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld(
|
||||
'electron',
|
||||
|
|
@ -83,7 +134,7 @@ contextBridge.exposeInMainWorld(
|
|||
|
||||
// 共享屏幕采集
|
||||
setDesktopCapturerVideo: (targetSource) => {
|
||||
rtcEngine.stopScreenCapture()
|
||||
stopScreenCapture()
|
||||
if (
|
||||
targetSource.type ===
|
||||
ScreenCaptureSourceType.ScreencapturesourcetypeScreen
|
||||
|
|
@ -109,34 +160,13 @@ contextBridge.exposeInMainWorld(
|
|||
);
|
||||
}
|
||||
videoID = `vidoe-${123}-${agoraAonfig.channelId}`;
|
||||
rtcEngine.joinChannelEx(agoraAonfig.token, {
|
||||
channelId: agoraAonfig.channelId,
|
||||
localUid: 123,
|
||||
}, {
|
||||
autoSubscribeAudio: true, //设置是否自动订阅所有音频流
|
||||
autoSubscribeVideo: true, //设置是否自动订阅所有视频流
|
||||
publishMicrophoneTrack: false, //设置是否发布麦克风采集到的音频
|
||||
publishCameraTrack: false, //设置是否发布摄像头采集的视频
|
||||
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //用户角色 1主播 2观众
|
||||
publishScreenTrack: true, //设置是否发布屏幕采集的视频
|
||||
});
|
||||
joinChannel(true)
|
||||
},
|
||||
// 摄像头采集
|
||||
setCameraCapture: () => {
|
||||
rtcEngine.startCameraCapture(VideoSourceType.VideoSourceCamera, {})
|
||||
videoID = `vidoe-${123}-${agoraAonfig.channelId}`;
|
||||
rtcEngine.joinChannelEx(agoraAonfig.token, {
|
||||
channelId: agoraAonfig.channelId,
|
||||
localUid: 123,
|
||||
}, {
|
||||
channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting, //设置频道场景为直播场景
|
||||
clientRoleType: ClientRoleType.ClientRoleBroadcaster, //设置用户角色为主播;如果要将用户角色设置为观众,保持默认值即可
|
||||
publishMicrophoneTrack: true, //发布麦克风采集的音频
|
||||
publishCameraTrack: true, //发布摄像头采集的视频
|
||||
autoSubscribeAudio: true, //自动订阅所有音频流
|
||||
autoSubscribeVideo: true, //自动订阅所有视频流
|
||||
publishScreenTrack: false, //设置是否发布屏幕采集的视频
|
||||
});
|
||||
joinChannel(false)
|
||||
},
|
||||
// 加入频道
|
||||
setJoinChannel: () => {
|
||||
|
|
@ -153,6 +183,22 @@ contextBridge.exposeInMainWorld(
|
|||
publishScreenTrack: true, //设置是否发布屏幕采集的视频
|
||||
});
|
||||
},
|
||||
// 离开频道
|
||||
leaveChannel: () => {
|
||||
leaveChannel()
|
||||
},
|
||||
// 停止共享屏幕
|
||||
stopScreenCapture: () => {
|
||||
stopScreenCapture()
|
||||
},
|
||||
// 取消或恢复发布本地音频流
|
||||
muteLocalAudioStream: (mute) => {
|
||||
rtcEngine.muteLocalAudioStream(mute)
|
||||
},
|
||||
// 取消或恢复发布本地视频流
|
||||
muteLocalVideoStream: (mute) => {
|
||||
rtcEngine.muteLocalVideoStream(mute)
|
||||
},
|
||||
// 获取当前生成的视频id
|
||||
getVideoId: () => {
|
||||
return videoID;
|
||||
|
|
@ -223,7 +269,35 @@ contextBridge.exposeInMainWorld(
|
|||
resolve(true)
|
||||
});
|
||||
})
|
||||
|
||||
},
|
||||
// 开始录制音视频
|
||||
startRecording: () => {
|
||||
iMediaRecorder = rtcEngine.createMediaRecorder({
|
||||
channelId: agoraAonfig.channelId,
|
||||
uid: 123,
|
||||
})
|
||||
iMediaRecorder.setMediaRecorderObserver({
|
||||
// 录制状态发生改变回调。
|
||||
onRecorderStateChanged: (channelId, uid, state, reason) => {
|
||||
console.log(channelId, uid, state, reason, '录制状态发生改变回调。');
|
||||
},
|
||||
// 录制信息更新回调。
|
||||
onRecorderInfoUpdated: (channelId, uid, info) => {
|
||||
console.log(channelId, uid, info, '录制信息更新回调。');
|
||||
},
|
||||
})
|
||||
iMediaRecorder.startRecording({
|
||||
storagePath: `D:/word/${+new Date()}.mp4`, //录音文件在本地保存的绝对路径,需精确到文件名及格式
|
||||
containerFormat: MediaRecorderContainerFormat.FormatMp4, //录制文件的格式
|
||||
streamType: MediaRecorderStreamType.StreamTypeBoth, //录制内容
|
||||
maxDurationMs: 7200000, //maxDurationMs
|
||||
})
|
||||
},
|
||||
// 停止录制音视频
|
||||
stopRecording: () => {
|
||||
iMediaRecorder.stopRecording()
|
||||
rtcEngine.destroyMediaRecorder(iMediaRecorder)
|
||||
iMediaRecorder = ""
|
||||
},
|
||||
// 设置窗口大小
|
||||
setMainWindowSize: (config) => {
|
||||
|
|
@ -236,6 +310,10 @@ contextBridge.exposeInMainWorld(
|
|||
// 获取当前是否全屏
|
||||
getIsMaximized: () => {
|
||||
return ipcRenderer.invoke('getIsMaximized')
|
||||
},
|
||||
// 复制文字
|
||||
setWriteText: (text) => {
|
||||
return ipcRenderer.invoke('setWriteText', text)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { request } from '@/utils'
|
||||
export const GetRoom = (data: { pageIndex: number, pageSize: number }) =>
|
||||
request({
|
||||
url: `/home/room?pageIndex=${data.pageIndex}&pageSize=${data.pageSize}`,
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const PostRomm = (data: any) =>
|
||||
request({
|
||||
url: `/home/room`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
|
||||
export const GetCheckoutRoomNum = (roomNum: string) =>
|
||||
request({
|
||||
url: `/room/checkout?roomNum=${roomNum}`,
|
||||
method: 'get',
|
||||
})
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import { request } from '@/utils'
|
||||
export const GetUserList = (data: { pageIndex: number, pageSize: number, searchKeywod: string }) =>
|
||||
request({
|
||||
url: `/user/list?pageIndex=${data.pageIndex}&pageSize=${data.pageSize}&searchKeywod=${data.searchKeywod}`,
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const PostUser = (data: any) =>
|
||||
request({
|
||||
url: `/user`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
|
||||
export const PutUser = (data: any) =>
|
||||
request({
|
||||
url: `/user`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
export const DeleteUser = (data: any) =>
|
||||
request({
|
||||
url: `/user`,
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
|
||||
export const PutUserPwd = (data: { id: string, pwd: string }) =>
|
||||
request({
|
||||
url: `/user/pwd`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
|
||||
export const GetRoleDpList = () =>
|
||||
request({
|
||||
url: `/pub/role-dp-list`,
|
||||
method: 'get',
|
||||
})
|
||||
|
|
@ -5,21 +5,10 @@ export const GetCheckUser = (userName: string) =>
|
|||
method: 'get'
|
||||
})
|
||||
|
||||
export const GetOcrDetail = (mid: string) =>
|
||||
export const PostLogin = (data: any) =>
|
||||
request({
|
||||
url: `/api/ocr/${mid}`,
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const PostSave = (data: any) =>
|
||||
request({
|
||||
url: `/api/ocr/save`,
|
||||
url: `/auth/login`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
|
||||
export const GetLock = (mid: string) =>
|
||||
request({
|
||||
url: `/api/ocr/lock?mid=${mid}`,
|
||||
method: 'get',
|
||||
})
|
||||
|
Before Width: | Height: | Size: 977 B After Width: | Height: | Size: 977 B |
|
|
@ -2,10 +2,13 @@ import ReactDOM from 'react-dom/client'
|
|||
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';
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<HashRouter>
|
||||
<App />
|
||||
<ConfigProvider locale={zhCN}>
|
||||
<App />
|
||||
</ConfigProvider>
|
||||
</HashRouter>
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -44,18 +44,20 @@
|
|||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.indexContentList {
|
||||
margin: 20px 0;
|
||||
overflow-y: scroll;
|
||||
flex-grow: 1;
|
||||
height: 0px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
|
||||
>div {
|
||||
.indexContentListItem {
|
||||
border: 1px solid #353741;
|
||||
margin-bottom: 34px;
|
||||
background-color: #1E1E1F;
|
||||
|
|
@ -118,5 +120,18 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.indexContentEmpty {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 18%;
|
||||
}
|
||||
|
||||
.indexContentPagination {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,57 @@ import styles from '@/page/Home/Index/index.module.scss'
|
|||
import { useEffect, useState } from "react";
|
||||
import Operation from '@/components/Operation';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button } from "antd";
|
||||
import { Button, Input, Modal, Pagination, Empty, message } from "antd";
|
||||
import { GetRoom, PostRomm, GetCheckoutRoomNum } from '@/api/Home/Index';
|
||||
// import { clipboard } from 'electron'
|
||||
const Index: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const [list, setList] = useState([{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}])
|
||||
const [list, setList] = useState({
|
||||
data: [],
|
||||
total: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 12,
|
||||
})
|
||||
const [createRoomModal, setCreateRoomModal] = useState(false)
|
||||
const [createRoomFrom, setCreateRoomFrom] = useState<{ roomName: string, roomNum: string }>({
|
||||
roomName: "",
|
||||
roomNum: ""
|
||||
})
|
||||
const [joinRoomModal, setJoinRoomModal] = useState(false)
|
||||
const [joinRoomFrom, setJoinRoomFrom] = useState<string>('')
|
||||
useEffect(() => {
|
||||
getRoomList()
|
||||
}, [list.pageIndex]);
|
||||
|
||||
|
||||
const getRoomList = async (): Promise<void> => {
|
||||
await GetRoom({
|
||||
pageIndex: list.pageIndex,
|
||||
pageSize: list.pageSize,
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
setList({
|
||||
...list,
|
||||
total: res.data.total,
|
||||
data: res.data.items,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const copyRoomNum = (roomNum: string): void => {
|
||||
window.electron.setWriteText(roomNum)
|
||||
message.success('复制成功')
|
||||
}
|
||||
|
||||
const isGetCheckoutRoomNum = async (roomNum: string, callBack: Function): Promise<void> => {
|
||||
await GetCheckoutRoomNum(roomNum).then(res => {
|
||||
if (res.code === 200) {
|
||||
callBack(res.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<div className={styles.index}>
|
||||
|
|
@ -18,10 +62,21 @@ const Index: React.FC = () => {
|
|||
<div className={styles.indexBtns}>
|
||||
<Button type="primary"
|
||||
icon={<img src="/src/assets/icon8.png" alt="" />}
|
||||
className='m-ant-btn drag'>
|
||||
className='m-ant-btn drag'
|
||||
onClick={() => {
|
||||
setCreateRoomFrom({
|
||||
roomName: "",
|
||||
roomNum: ""
|
||||
})
|
||||
setCreateRoomModal(true)
|
||||
}}
|
||||
>
|
||||
新建会议室
|
||||
</Button>
|
||||
<Button type="primary"
|
||||
<Button type="primary" onClick={() => {
|
||||
setJoinRoomFrom('')
|
||||
setJoinRoomModal(true)
|
||||
}}
|
||||
icon={<img src="/src/assets/icon7.png" alt="" />}
|
||||
className={`${styles.indexBtnsJoin} drag`}>
|
||||
加入会议
|
||||
|
|
@ -31,24 +86,25 @@ const Index: React.FC = () => {
|
|||
<div className={styles.indexContentTitle}>
|
||||
会议室列表
|
||||
</div>
|
||||
<div className={`${styles.indexContentList} drag`}>
|
||||
{list.map((_item, index: number) => {
|
||||
{list.data.length ? <div className={styles.indexContentList}>
|
||||
{list.data.map((item: any, index: number) => {
|
||||
return (
|
||||
<div className={styles.indexContentListItem} key={index}>
|
||||
<div className={`${styles.indexContentListItem} drag`} key={index}>
|
||||
<div>
|
||||
<div>奉节中学期末考分析总结会议</div>
|
||||
<div>{item.roomName}</div>
|
||||
<div>
|
||||
<img src="/src/assets/icon11.png" alt="" />
|
||||
<span>2人</span>
|
||||
<span>{item.onlineUserCount}人</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span>252535356565</span>
|
||||
<div onClick={() => copyRoomNum(item.roomNum)} title='复制房间号'>
|
||||
<span>{item.roomNum}</span>
|
||||
<img src="/src/assets/icon10.png" alt="" />
|
||||
</div>
|
||||
<div>
|
||||
<Button type="primary" danger>设置</Button>
|
||||
|
||||
{/* <Button type="primary" danger>设置</Button> */}
|
||||
<Button type="primary"
|
||||
iconPosition={'end'}
|
||||
onClick={() => {
|
||||
|
|
@ -63,11 +119,130 @@ const Index: React.FC = () => {
|
|||
</div>
|
||||
)
|
||||
})}
|
||||
<div style={{ visibility: 'hidden' }}></div>
|
||||
<div style={{ visibility: 'hidden' }}></div>
|
||||
<div style={{ visibility: 'hidden' }} className={`${styles.indexContentListItem} drag`}></div>
|
||||
<div style={{ visibility: 'hidden' }} className={`${styles.indexContentListItem} drag`}></div>
|
||||
</div> :
|
||||
<div className={styles.indexContentEmpty}>
|
||||
<Empty />
|
||||
</div>
|
||||
}
|
||||
<div className={styles.indexContentPagination}>
|
||||
<Pagination size="small" total={list.total} onChange={(e) => {
|
||||
setList({
|
||||
...list,
|
||||
pageIndex: e
|
||||
})
|
||||
}} pageSize={list.pageSize} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal title="新建会议室" open={createRoomModal} footer={null} closable={false} centered width={'30vw'}>
|
||||
<div>
|
||||
<div>
|
||||
<Input
|
||||
placeholder="请输入房间名字"
|
||||
style={{ marginBottom: '14px' }}
|
||||
value={createRoomFrom.roomName}
|
||||
onChange={(e) => {
|
||||
setCreateRoomFrom({
|
||||
...createRoomFrom,
|
||||
roomName: e.target.value
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder="请输入房间号"
|
||||
style={{ marginBottom: '14px' }}
|
||||
showCount
|
||||
maxLength={8}
|
||||
value={createRoomFrom.roomNum}
|
||||
onChange={(e) => {
|
||||
const regex = /^[0-9 ]*$/;
|
||||
if (regex.test(e.target.value)) {
|
||||
setCreateRoomFrom({
|
||||
...createRoomFrom,
|
||||
roomNum: e.target.value
|
||||
})
|
||||
}
|
||||
}}
|
||||
suffix={
|
||||
<span
|
||||
style={{ color: '#47D3D0', cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setCreateRoomFrom({
|
||||
...createRoomFrom,
|
||||
roomNum: Math.floor(+new Date() / 1000).toString().slice(-8),
|
||||
})
|
||||
}}
|
||||
>获取随机房间号
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex', justifyContent: 'center'
|
||||
}}>
|
||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setCreateRoomModal(false)}>取消</Button>
|
||||
<Button type="primary" className='m-ant-btn' onClick={() => {
|
||||
if (!createRoomFrom.roomName) {
|
||||
return message.error('请输入房间名字!')
|
||||
}
|
||||
if (!createRoomFrom.roomNum) {
|
||||
return message.error('请输入房间号!')
|
||||
}
|
||||
isGetCheckoutRoomNum(createRoomFrom.roomNum, (bool: boolean) => {
|
||||
if (bool) {
|
||||
message.error('房间号已存在!')
|
||||
} else {
|
||||
PostRomm(createRoomFrom).then(res => {
|
||||
if (res.code === 200) {
|
||||
message.success('创建成功!')
|
||||
setCreateRoomModal(false)
|
||||
getRoomList()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}}>创建</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal title="加入会议室" open={joinRoomModal} footer={null} closable={false} centered width={'30vw'}>
|
||||
<div>
|
||||
<div>
|
||||
<Input
|
||||
placeholder="请输入房间号"
|
||||
style={{ marginBottom: '14px' }}
|
||||
showCount
|
||||
maxLength={8}
|
||||
value={joinRoomFrom}
|
||||
onChange={(e) => {
|
||||
const regex = /^[0-9 ]*$/;
|
||||
if (regex.test(e.target.value)) {
|
||||
setJoinRoomFrom(e.target.value)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex', justifyContent: 'center'
|
||||
}}>
|
||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setJoinRoomModal(false)}>取消</Button>
|
||||
<Button type="primary" className='m-ant-btn' onClick={() => {
|
||||
if (!joinRoomFrom) {
|
||||
return message.error('请输入房间号!')
|
||||
}
|
||||
isGetCheckoutRoomNum(joinRoomFrom, (bool: boolean) => {
|
||||
if (bool) {
|
||||
|
||||
} else {
|
||||
message.error('房间号不存在!')
|
||||
}
|
||||
})
|
||||
}}>加入</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,23 @@
|
|||
|
||||
>span {
|
||||
color: #8B8787;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.addUserModal {
|
||||
>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
>span {
|
||||
flex-shrink: 0;
|
||||
color: #EEEEEE;
|
||||
width: 120px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +1,76 @@
|
|||
import styles from '@/page/Home/User/index.module.scss'
|
||||
import { useEffect, useState } from "react";
|
||||
import Operation from '@/components/Operation';
|
||||
import { Button, Input, Table, Pagination } from "antd";
|
||||
import { Button, Input, Table, Pagination, Modal, message, Select } from "antd";
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import type { TableColumnsType } from 'antd';
|
||||
const columns: TableColumnsType = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '账号',
|
||||
dataIndex: 'account',
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
dataIndex: 'role',
|
||||
},
|
||||
{
|
||||
title: '账号状态',
|
||||
dataIndex: 'status',
|
||||
render: (text) => {
|
||||
return (
|
||||
<div style={{ color: '#02B188' }}>{text}</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const data = [] as any;
|
||||
for (let i = 0; i < 46; i++) {
|
||||
data.push({
|
||||
key: i,
|
||||
name: `潇潇`,
|
||||
account: 5256589545,
|
||||
role: `教师`,
|
||||
status: `在线`,
|
||||
});
|
||||
}
|
||||
import { GetUserList, PostUser, PutUser, DeleteUser, PutUserPwd, GetRoleDpList } from '@/api/Home/User';
|
||||
import { md5 } from 'js-md5';
|
||||
const { Column } = Table
|
||||
const User: React.FC = () => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
useEffect(() => {
|
||||
const [isCreateUser, setIsCreateUser] = useState(false);
|
||||
const [list, setList] = useState({
|
||||
data: [],
|
||||
searchKeywod: '',
|
||||
total: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 6,
|
||||
})
|
||||
const [roleList, setRoleList] = useState([])
|
||||
const [addUserModal, setAddUserModal] = useState(false)
|
||||
const [addUserFrom, setAddUserFrom] = useState({
|
||||
Id: "",
|
||||
Account: "",
|
||||
RoleId: null,
|
||||
Pwd: "",
|
||||
UserName: ""
|
||||
})
|
||||
const [changeUserPawModal, setChangeUserPawModal] = useState(false)
|
||||
const [changeUserPawFrom, setChangeUserPawFrom] = useState({
|
||||
Pwd: "",
|
||||
newPwd: '',
|
||||
})
|
||||
const [deleteUserPawModal, setDeleteUserPawModal] = useState(false)
|
||||
|
||||
}, []);
|
||||
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
|
||||
setSelectedRowKeys(newSelectedRowKeys);
|
||||
};
|
||||
const rowSelection = {
|
||||
selectedRowKeys,
|
||||
onChange: onSelectChange,
|
||||
};
|
||||
useEffect(() => {
|
||||
getUserList()
|
||||
}, [list.pageIndex]);
|
||||
|
||||
const getUserList = async (): Promise<void> => {
|
||||
await GetUserList({
|
||||
pageIndex: list.pageIndex,
|
||||
pageSize: list.pageSize,
|
||||
searchKeywod: list.searchKeywod,
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
setList({
|
||||
...list,
|
||||
total: res.data.total,
|
||||
data: res.data.items.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
key: item.id,
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getRoleDpList = async (callBack: Function): Promise<void> => {
|
||||
await GetRoleDpList().then(res => {
|
||||
if (res.code === 200) {
|
||||
setRoleList(res.data.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
value: item.id,
|
||||
label: item.roleName
|
||||
}
|
||||
}))
|
||||
callBack(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className={styles.user}>
|
||||
|
|
@ -59,36 +80,313 @@ const User: React.FC = () => {
|
|||
<div className={styles.userBtns}>
|
||||
<div className={`${styles.userBtnsLeft} drag`}>
|
||||
<Button type="primary"
|
||||
onClick={() => {
|
||||
getRoleDpList((bool: boolean) => {
|
||||
if (bool) {
|
||||
setIsCreateUser(true)
|
||||
setAddUserFrom({
|
||||
Id: "",
|
||||
Account: "",
|
||||
RoleId: null,
|
||||
Pwd: "",
|
||||
UserName: "",
|
||||
})
|
||||
setAddUserModal(true)
|
||||
}
|
||||
})
|
||||
}}
|
||||
icon={<img src="/src/assets/icon8.png" alt="" />}
|
||||
className='m-ant-btn'>
|
||||
添加用户
|
||||
</Button>
|
||||
<Button type="primary"
|
||||
icon={<img src="/src/assets/icon21.png" alt="" />}
|
||||
className={styles.userBtnsDel}>
|
||||
className={styles.userBtnsDel}
|
||||
onClick={() => {
|
||||
setDeleteUserPawModal(true)
|
||||
}}
|
||||
>
|
||||
删除用户
|
||||
</Button>
|
||||
</div>
|
||||
<div className={`${styles.userBtnsRight} drag`}>
|
||||
<Input placeholder="请输入用户名" prefix={<SearchOutlined style={{ color: 'white' }} />} />
|
||||
<Button className='m-border-ant-button'>查询</Button>
|
||||
<Input
|
||||
placeholder="请输入用户名"
|
||||
prefix={<SearchOutlined style={{ color: 'white' }} />}
|
||||
onChange={(e) => {
|
||||
setList({
|
||||
...list,
|
||||
searchKeywod: e.target.value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Button className='m-border-ant-button' onClick={() => {
|
||||
if (list.pageIndex === 1) {
|
||||
getUserList()
|
||||
} else {
|
||||
setList({
|
||||
...list,
|
||||
pageIndex: 1
|
||||
})
|
||||
}
|
||||
}}>查询</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${styles.userContent} drag`}>
|
||||
<Table
|
||||
rowSelection={rowSelection}
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
size={'small'}
|
||||
rowSelection={{
|
||||
selectedRowKeys,
|
||||
onChange: (newSelectedRowKeys: React.Key[]) => {
|
||||
setSelectedRowKeys(newSelectedRowKeys);
|
||||
}
|
||||
}}
|
||||
dataSource={list.data}
|
||||
pagination={false}
|
||||
scroll={{ y: '64vh' }}
|
||||
style={{ width: '77.6vw', flexGrow: 1 }}
|
||||
/>
|
||||
scroll={{ y: '70vh' }}
|
||||
style={{ width: '81.4vw', flexGrow: 1 }}
|
||||
>
|
||||
<Column title="姓名" dataIndex="userName" key="userName" />
|
||||
<Column title="账号" dataIndex="account" key="account" />
|
||||
<Column title="角色" dataIndex="roleName" key="roleName" />
|
||||
<Column title="在线状态" render={(item) => (
|
||||
<>
|
||||
<div style={{ color: '#02B188' }}>{item.account}</div>
|
||||
</>
|
||||
)} />
|
||||
<Column title="操作" render={(item) => (
|
||||
<>
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ backgroundColor: '#0085FF30', marginRight: '14px' }}
|
||||
size={'small'}
|
||||
onClick={() => {
|
||||
getRoleDpList((bool: boolean) => {
|
||||
if (bool) {
|
||||
setIsCreateUser(false)
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
Id: item.id,
|
||||
Account: item.account,
|
||||
RoleId: item.roleId,
|
||||
UserName: item.userName,
|
||||
})
|
||||
setAddUserModal(true)
|
||||
}
|
||||
})
|
||||
}}>编辑</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
style={{ backgroundColor: '#715AFF40', marginRight: '14px' }}
|
||||
size={'small'}
|
||||
onClick={() => {
|
||||
setChangeUserPawFrom({
|
||||
Pwd: "",
|
||||
newPwd: '',
|
||||
})
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
Id: item.id,
|
||||
Account: item.account,
|
||||
RoleId: item.roleId,
|
||||
UserName: item.userName,
|
||||
})
|
||||
setChangeUserPawModal(true)
|
||||
}}>更改密码</Button>
|
||||
</>
|
||||
)} />
|
||||
</Table>
|
||||
<div className={styles.userContentPagination}>
|
||||
<span>共653项数据</span>
|
||||
<Pagination size="small" total={50} />
|
||||
<span>共{list.total}项数据</span>
|
||||
<Pagination size="small" total={list.total} onChange={(e) => {
|
||||
setList({
|
||||
...list,
|
||||
pageIndex: e
|
||||
})
|
||||
}} pageSize={list.pageSize} current={list.pageIndex} hideOnSinglePage={true} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal title={isCreateUser ? '添加用户' : '编辑用户'} open={addUserModal} footer={null} closable={false} centered width={'40vw'}>
|
||||
<div>
|
||||
<div className={styles.addUserModal}>
|
||||
<div>
|
||||
<span>账号:</span>
|
||||
<Input
|
||||
placeholder="请输入账号"
|
||||
value={addUserFrom.Account}
|
||||
onChange={(e) => {
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
Account: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span>角色:</span>
|
||||
<Select
|
||||
placeholder='请选择角色'
|
||||
options={roleList}
|
||||
style={{ flexGrow: 1 }}
|
||||
value={addUserFrom.RoleId} onChange={(e) => {
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
RoleId: e
|
||||
});
|
||||
}} />;
|
||||
</div>
|
||||
{isCreateUser ? <div>
|
||||
<span>密码:</span>
|
||||
<Input.Password
|
||||
placeholder="请输入密码"
|
||||
style={{ flexGrow: 1 }}
|
||||
value={addUserFrom.Pwd}
|
||||
onChange={(e) => {
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
Pwd: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div> : null}
|
||||
<div>
|
||||
<span>用户名称:</span>
|
||||
<Input
|
||||
placeholder="请输入用户名称"
|
||||
style={{ flexGrow: 1 }}
|
||||
value={addUserFrom.UserName}
|
||||
onChange={(e) => {
|
||||
setAddUserFrom({
|
||||
...addUserFrom,
|
||||
UserName: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex', justifyContent: 'center'
|
||||
}}>
|
||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setAddUserModal(false)}>取消</Button>
|
||||
<Button type="primary" className='m-ant-btn' onClick={async () => {
|
||||
if (!addUserFrom.Account) {
|
||||
return message.error('请输入账号!')
|
||||
}
|
||||
if (!addUserFrom.RoleId) {
|
||||
return message.error('请选择角色!')
|
||||
}
|
||||
if (!addUserFrom.Pwd && isCreateUser) {
|
||||
return message.error('请输入密码!')
|
||||
}
|
||||
if (!addUserFrom.UserName) {
|
||||
return message.error('请输入用户名称!')
|
||||
}
|
||||
if (isCreateUser) {
|
||||
await PostUser({
|
||||
...addUserFrom,
|
||||
Pwd: md5(addUserFrom.Pwd)
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
setAddUserModal(false)
|
||||
message.success('添加成功!')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await PutUser({
|
||||
Id: addUserFrom.Id,
|
||||
Account: addUserFrom.Account,
|
||||
RoleId: addUserFrom.RoleId,
|
||||
UserName: addUserFrom.UserName
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
setAddUserModal(false)
|
||||
message.success('修改成功!')
|
||||
}
|
||||
})
|
||||
}
|
||||
await getUserList()
|
||||
}}>{isCreateUser ? '添加' : '修改'}</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal title='更改密码' open={changeUserPawModal} footer={null} closable={false} centered width={'40vw'}>
|
||||
<div>
|
||||
<div className={styles.addUserModal}>
|
||||
<div>
|
||||
<span>新密码:</span>
|
||||
<Input.Password
|
||||
placeholder="请输入新密码"
|
||||
style={{ flexGrow: 1 }}
|
||||
value={changeUserPawFrom.Pwd}
|
||||
onChange={(e) => {
|
||||
setChangeUserPawFrom({
|
||||
...changeUserPawFrom,
|
||||
Pwd: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span>确认密码:</span>
|
||||
<Input.Password
|
||||
placeholder="再次输入密码"
|
||||
style={{ flexGrow: 1 }}
|
||||
value={changeUserPawFrom.newPwd}
|
||||
onChange={(e) => {
|
||||
setChangeUserPawFrom({
|
||||
...changeUserPawFrom,
|
||||
newPwd: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex', justifyContent: 'center'
|
||||
}}>
|
||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setChangeUserPawModal(false)}>取消</Button>
|
||||
<Button type="primary" className='m-ant-btn' onClick={async () => {
|
||||
if (!changeUserPawFrom.Pwd || !changeUserPawFrom.newPwd) {
|
||||
return message.error('请输入密码!')
|
||||
}
|
||||
if (changeUserPawFrom.Pwd !== changeUserPawFrom.newPwd) {
|
||||
return message.error('新密码与确认密码不一致!')
|
||||
}
|
||||
await PutUserPwd({ id: addUserFrom.Id, pwd: md5(changeUserPawFrom.Pwd) }).then(res => {
|
||||
if (res.code === 200) {
|
||||
setChangeUserPawModal(false)
|
||||
message.success('修改成功')
|
||||
}
|
||||
})
|
||||
await getUserList()
|
||||
}}>修改</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal title='' open={deleteUserPawModal} footer={null} centered width={'24vw'}>
|
||||
<div>
|
||||
<div style={{ color: 'white', fontSize: '18px', textAlign: 'center', marginBottom: '20px' }}>
|
||||
是否确认删除该用户?
|
||||
</div>
|
||||
<div style={{
|
||||
display: 'flex', justifyContent: 'center'
|
||||
}}>
|
||||
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }}
|
||||
onClick={() => setDeleteUserPawModal(false)}>取消</Button>
|
||||
<Button type="primary" className='m-ant-btn' onClick={() => {
|
||||
DeleteUser(selectedRowKeys).then(res => {
|
||||
if (res.code === 200) {
|
||||
setDeleteUserPawModal(true)
|
||||
setSelectedRowKeys([])
|
||||
message.success('删除成功!')
|
||||
getUserList()
|
||||
}
|
||||
})
|
||||
}}>确定</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Outlet, useNavigate } from 'react-router-dom';
|
|||
import { Popconfirm } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import 'dayjs/locale/zh-cn'
|
||||
import { storage } from '@/utils';
|
||||
dayjs.locale('zh-cn');
|
||||
type navListType = {
|
||||
title: string;
|
||||
|
|
@ -31,6 +32,7 @@ const Home: React.FC = () => {
|
|||
path: '/home/user'
|
||||
},
|
||||
]);
|
||||
const [userInfo, setUserInfo] = useState<any>({})
|
||||
const [dateInfo, setDateInfo] = useState<{
|
||||
work: string;
|
||||
time: string;
|
||||
|
|
@ -41,6 +43,10 @@ const Home: React.FC = () => {
|
|||
specific: '',
|
||||
})
|
||||
useEffect(() => {
|
||||
const user = JSON.parse(storage.getItem('user') as string);
|
||||
if (user) {
|
||||
setUserInfo(user)
|
||||
}
|
||||
const updateTime = () => {
|
||||
setDateInfo({
|
||||
work: dayjs().format('ddd'),
|
||||
|
|
@ -76,7 +82,7 @@ const Home: React.FC = () => {
|
|||
<div>
|
||||
<img src="/src/assets/avatar.png" alt="" />
|
||||
</div>
|
||||
<span>欢迎您,u0001</span>
|
||||
<span>欢迎您,{userInfo?.userName}</span>
|
||||
</div>
|
||||
<div>
|
||||
<img src="/src/assets/icon14.png" alt="" />
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
import styles from '@/page/Login/index.module.scss'
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Input, Button, Checkbox } from "antd"
|
||||
import { Input, Button, Checkbox, message } from "antd"
|
||||
import { storage } from '@/utils'
|
||||
import { GetCheckUser } from '@/api/Login'
|
||||
import { GetCheckUser, PostLogin } from '@/api/Login'
|
||||
import { md5 } from 'js-md5';
|
||||
|
||||
const Login: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const [accountPasswordStatus, setAccountPasswordStatus] = useState<boolean>(false);
|
||||
const [accountStatus, setAccountStatus] = useState<boolean>(false);
|
||||
const [operation, setOperation] = useState<{
|
||||
isRememberPassword: boolean;
|
||||
isAutoLogin: boolean;
|
||||
|
|
@ -29,6 +31,11 @@ const Login: React.FC = () => {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
window.electron.setMainWindowSize({
|
||||
width: 752,
|
||||
height: 520,
|
||||
key: 'login'
|
||||
})
|
||||
if (storage.getItem('login')) {
|
||||
const login = JSON.parse(storage.getItem('login') as string);
|
||||
const data = {
|
||||
|
|
@ -49,6 +56,11 @@ const Login: React.FC = () => {
|
|||
...data,
|
||||
})
|
||||
}
|
||||
GetCheckUser(login.account).then(res => {
|
||||
if (res.code === 200) {
|
||||
setAccountStatus(res.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
|
@ -88,18 +100,27 @@ const Login: React.FC = () => {
|
|||
|
||||
// 登录
|
||||
const loginClick = (): void => {
|
||||
storage.setItem('login', JSON.stringify({
|
||||
isRememberPassword: operation.optionsValue.includes('isRememberPassword'),
|
||||
isAutoLogin: operation.optionsValue.includes('isAutoLogin'),
|
||||
PostLogin({
|
||||
account: operation.account,
|
||||
password: operation.password,
|
||||
optionsValue: operation.optionsValue,
|
||||
}))
|
||||
window.electron.setMainWindowSize({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
pwd: md5(operation.password)
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
message.success('登录成功!')
|
||||
storage.setItem('login', JSON.stringify({
|
||||
isRememberPassword: operation.optionsValue.includes('isRememberPassword'),
|
||||
isAutoLogin: operation.optionsValue.includes('isAutoLogin'),
|
||||
account: operation.account,
|
||||
password: operation.password,
|
||||
optionsValue: operation.optionsValue,
|
||||
}))
|
||||
storage.setItem('user', JSON.stringify(res.data))
|
||||
window.electron.setMainWindowSize({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
})
|
||||
navigate('/home')
|
||||
}
|
||||
})
|
||||
navigate('/home')
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -126,9 +147,13 @@ const Login: React.FC = () => {
|
|||
...operation,
|
||||
account: e.target.value
|
||||
})
|
||||
// GetCheckUser(e.target.value).then(res => {
|
||||
// console.log(res);
|
||||
// })
|
||||
if (e.target.value) {
|
||||
GetCheckUser(e.target.value).then(res => {
|
||||
if (res.code === 200) {
|
||||
setAccountStatus(res.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}}
|
||||
className={`${styles.loginInputIcon} drag`}
|
||||
style={{ marginBottom: '12px' }}
|
||||
|
|
@ -143,7 +168,7 @@ const Login: React.FC = () => {
|
|||
}
|
||||
/>
|
||||
|
||||
{operation.account && !accountPasswordStatus ? <div style={{ marginTop: '36px' }} className='drag'>
|
||||
{operation.account && !accountPasswordStatus && accountStatus ? <div style={{ marginTop: '36px' }} className='drag'>
|
||||
<Button type="primary"
|
||||
onClick={continueClick}
|
||||
style={{ width: '100%' }}
|
||||
|
|
|
|||
|
|
@ -20,64 +20,68 @@ const Meeting: React.FC = () => {
|
|||
const [isStupWizard, setIsStupWizard] = useState(false);
|
||||
const [sharedScreenList, setSharedScreenList] = useState<any>([]);
|
||||
const [sharedScreenItem, setSharedScreenItem] = useState<any>('');
|
||||
const [footerList] = useState([
|
||||
const [footerList, setFooterList] = useState([
|
||||
[
|
||||
{
|
||||
title: '关闭声音',
|
||||
icon: '/src/assets/icon22.png',
|
||||
icon: '/src/assets/icon22',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '关闭视频',
|
||||
icon: '/src/assets/icon23.png',
|
||||
icon: '/src/assets/icon23',
|
||||
active: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
title: '共享屏幕',
|
||||
icon: '/src/assets/icon24.png',
|
||||
icon: '/src/assets/icon24',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '共享文件',
|
||||
icon: '/src/assets/icon25.png',
|
||||
icon: '/src/assets/icon25',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '邀请人员',
|
||||
icon: '/src/assets/icon26.png',
|
||||
icon: '/src/assets/icon26',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '录制',
|
||||
icon: '/src/assets/icon27.png',
|
||||
icon: '/src/assets/icon27',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '设置向导',
|
||||
icon: '/src/assets/icon28.png',
|
||||
icon: '/src/assets/icon28',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '结束',
|
||||
icon: '/src/assets/icon29.png',
|
||||
icon: '/src/assets/icon29',
|
||||
active: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
title: '成员列表',
|
||||
icon: '/src/assets/icon30.png',
|
||||
icon: '/src/assets/icon30',
|
||||
active: false,
|
||||
},
|
||||
{
|
||||
title: '聊天',
|
||||
icon: '/src/assets/icon31.png',
|
||||
active: false
|
||||
icon: '/src/assets/icon31',
|
||||
active: false,
|
||||
},
|
||||
],
|
||||
])
|
||||
const [footerListIndex, setFooterListIndex] = useState<any>({
|
||||
itemIndex: 0,
|
||||
rowIndex: 0,
|
||||
});
|
||||
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
|
||||
currentDevices: [],
|
||||
currentDevice: {},
|
||||
|
|
@ -93,7 +97,12 @@ const Meeting: React.FC = () => {
|
|||
|
||||
}, []);
|
||||
|
||||
const changeStatusList = (row: any): void => {
|
||||
const changeStatusList = (row: any, itemIndex: number, rowIndex: number): void => {
|
||||
const footerListTemplate = [...footerList]
|
||||
setFooterListIndex({
|
||||
itemIndex,
|
||||
rowIndex,
|
||||
})
|
||||
switch (row.title) {
|
||||
case '成员列表':
|
||||
setStatusList({
|
||||
|
|
@ -111,15 +120,51 @@ const Meeting: React.FC = () => {
|
|||
getDesktopCapturerVideo()
|
||||
setIsSharedScreenModal(true)
|
||||
break;
|
||||
case '停止共享':
|
||||
window.electron.stopScreenCapture()
|
||||
footerListTemplate[itemIndex][rowIndex].title = '共享屏幕'
|
||||
break;
|
||||
case '关闭声音':
|
||||
window.electron.setJoinChannel()
|
||||
setVideoID(window.electron.getVideoId())
|
||||
footerListTemplate[itemIndex][rowIndex].title = '开启声音'
|
||||
footerListTemplate[itemIndex][rowIndex].active = true
|
||||
setFooterList(footerListTemplate)
|
||||
window.electron.muteLocalAudioStream(true)
|
||||
break;
|
||||
case '开启声音':
|
||||
footerListTemplate[itemIndex][rowIndex].title = '关闭声音'
|
||||
footerListTemplate[itemIndex][rowIndex].active = false
|
||||
setFooterList(footerListTemplate)
|
||||
window.electron.muteLocalAudioStream(false)
|
||||
break;
|
||||
case '关闭视频':
|
||||
footerListTemplate[itemIndex][rowIndex].title = '开启视频'
|
||||
footerListTemplate[itemIndex][rowIndex].active = true
|
||||
setFooterList(footerListTemplate)
|
||||
window.electron.muteLocalVideoStream(true)
|
||||
break;
|
||||
case '开启视频':
|
||||
footerListTemplate[itemIndex][rowIndex].title = '关闭视频'
|
||||
footerListTemplate[itemIndex][rowIndex].active = false
|
||||
setFooterList(footerListTemplate)
|
||||
window.electron.muteLocalVideoStream(false)
|
||||
break;
|
||||
case '设置向导':
|
||||
getAudioMediaList()
|
||||
window.electron.startRecordingDeviceTest(200)
|
||||
setIsStupWizard(true)
|
||||
break;
|
||||
case '录制':
|
||||
footerListTemplate[itemIndex][rowIndex].title = '录制中'
|
||||
footerListTemplate[itemIndex][rowIndex].active = true
|
||||
setFooterList(footerListTemplate)
|
||||
window.electron.startRecording()
|
||||
break;
|
||||
case '录制中':
|
||||
footerListTemplate[itemIndex][rowIndex].title = '录制'
|
||||
footerListTemplate[itemIndex][rowIndex].active = false
|
||||
setFooterList(footerListTemplate)
|
||||
window.electron.stopRecording()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +174,8 @@ const Meeting: React.FC = () => {
|
|||
} else {
|
||||
let data = sharedScreenList.find((item: any) => item.sourceId === sharedScreenItem.sourceId)
|
||||
if (data) {
|
||||
const footerListTemplate = [...footerList]
|
||||
footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享'
|
||||
setIsSharedScreenModal(false)
|
||||
window.electron.setDesktopCapturerVideo(sharedScreenItem)
|
||||
setVideoID(window.electron.getVideoId())
|
||||
|
|
@ -300,9 +347,15 @@ const Meeting: React.FC = () => {
|
|||
content={
|
||||
<div className='meetingContentFooterPopover'>
|
||||
<div onClick={() => {
|
||||
window.electron.leaveChannel()
|
||||
window.electron.stopScreenCapture()
|
||||
navigate(-1)
|
||||
}}>全员结束会议</div>
|
||||
<div onClick={() => { navigate(-1) }}>仅自己离开</div>
|
||||
<div onClick={() => {
|
||||
window.electron.leaveChannel()
|
||||
window.electron.stopScreenCapture()
|
||||
navigate(-1)
|
||||
}}>仅自己离开</div>
|
||||
<div onClick={() => { setOpen(false) }}>取消</div>
|
||||
</div>
|
||||
}
|
||||
|
|
@ -312,12 +365,12 @@ const Meeting: React.FC = () => {
|
|||
onOpenChange={() => setOpen(true)}
|
||||
>
|
||||
<div className='drag'>
|
||||
<img src={row.icon} alt="" />
|
||||
<img src={row.active ? row.icon + '-active.png' : row.icon + '.png'} alt="" />
|
||||
<span>{row.title}</span>
|
||||
</div>
|
||||
</Popover> :
|
||||
<div className='drag' onClick={() => changeStatusList(row)} key={rowIndex}>
|
||||
<img src={row.icon} alt="" />
|
||||
<div className='drag' onClick={() => changeStatusList(row, itemIndex, rowIndex)} key={rowIndex}>
|
||||
<img src={row.active ? row.icon + '-active.png' : row.icon + '.png'} alt="" />
|
||||
<span>{row.title}</span>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,9 +11,16 @@ export interface IElectronAPI {
|
|||
setViewStatus: (status: 'quit' | 'maximize' | 'minimize' | 'unmaximize') => void;
|
||||
setJoinChannel: () => Promise<void>;
|
||||
getVideoId: () => string;
|
||||
startRecordingDeviceTest: (indicationInterval:number) => void;
|
||||
startRecordingDeviceTest: (indicationInterval: number) => void;
|
||||
stopAudioDeviceLoopbackTest: () => void;
|
||||
startPreview: () => Promise<boolean>;
|
||||
startRecording: () => void;
|
||||
stopRecording: () => void;
|
||||
leaveChannel: () => void;
|
||||
stopScreenCapture: () => void;
|
||||
muteLocalAudioStream: (mute: boolean) => void;
|
||||
muteLocalVideoStream: (mute: boolean) => void;
|
||||
setWriteText: (text: string) => void;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import { RequestConfig, RequestInterceptors } from './types'
|
|||
import { storage } from '@/utils'
|
||||
import { constant } from '@/config'
|
||||
import { message } from 'antd';
|
||||
|
||||
class Request {
|
||||
// axios实例
|
||||
instance: AxiosInstance
|
||||
|
|
@ -17,10 +16,10 @@ class Request {
|
|||
// 类请求拦截器
|
||||
this.instance.interceptors.request.use(
|
||||
(req: any) => {
|
||||
const token = localStorage.getItem('token')
|
||||
if (token) {
|
||||
const user = JSON.parse(storage.getItem('user') as string);
|
||||
if (user) {
|
||||
// 如果有token给请求头加上
|
||||
req.headers.Authorization = `${token}`
|
||||
req.headers.Authorization = `Bearer ${user.token}`
|
||||
req.timeout = constant.CONFIG_REQUEST_TIMEOUT_TIME
|
||||
}
|
||||
if (req.contentType) {
|
||||
|
|
@ -62,13 +61,13 @@ class Request {
|
|||
},
|
||||
(err: any) => {
|
||||
function toLogin() {
|
||||
storage.removeItem(constant.CONFIG_TOKEN)
|
||||
|
||||
storage.removeItem('user')
|
||||
location.href = location.origin + '/#/login'
|
||||
}
|
||||
// 根据自己业务/接口返回做相应调整
|
||||
if (err.response) {
|
||||
const { status, data } = err.response
|
||||
message.error(data.message || data.title)
|
||||
const { status } = err.response
|
||||
message.error(err.message)
|
||||
switch (status) {
|
||||
case 401:
|
||||
toLogin()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,25 @@
|
|||
.ant-select .ant-select-selector {
|
||||
background-color: #28282C !important;
|
||||
border: 1px solid #404145 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ant-select .ant-select-selector .ant-select-selection-item {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ant-select .ant-select-selector .ant-select-selection-placeholder {
|
||||
color: #EEEEEE;
|
||||
}
|
||||
|
||||
.ant-select .ant-select-suffix {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.ant-input {
|
||||
background-color: #28282C !important;
|
||||
border: 1px solid #404145;
|
||||
color: white;
|
||||
color: white !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
|
@ -23,6 +41,10 @@
|
|||
color: white !important;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper .ant-input-show-count-suffix {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.m-ant-btn.ant-btn {
|
||||
background-color: #3F51B5;
|
||||
box-shadow: none;
|
||||
|
|
@ -94,6 +116,18 @@
|
|||
background-color: #0d0f12 !important;
|
||||
}
|
||||
|
||||
.ant-table .ant-table-body .ant-table-placeholder {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.ant-table .ant-table-body .ant-table-placeholder .ant-table-cell {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.ant-pagination {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-prev {
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
|
@ -120,6 +154,10 @@
|
|||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-item > a {
|
||||
color: #878787 !important;
|
||||
}
|
||||
|
||||
.ant-pagination .ant-pagination-item:hover {
|
||||
background: #5575F2 !important;
|
||||
border: none;
|
||||
|
|
@ -140,6 +178,10 @@
|
|||
color: black !important;
|
||||
}
|
||||
|
||||
.ant-popover {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.ant-popover:not(.ant-popconfirm) .ant-popover-arrow::before {
|
||||
background-color: #07090B !important;
|
||||
}
|
||||
|
|
@ -152,6 +194,10 @@
|
|||
background-color: rgba(0, 0, 0, 0.25) !important;
|
||||
}
|
||||
|
||||
.ant-modal {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.ant-modal .ant-modal-content {
|
||||
background-color: #07090B;
|
||||
}
|
||||
|
|
@ -187,3 +233,7 @@
|
|||
background-color: #3672E9;
|
||||
box-shadow: 0 0 0 2px #3672E9;
|
||||
}
|
||||
|
||||
.ant-empty .ant-empty-description {
|
||||
color: #808080;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
.ant-input{background-color:#28282C !important;border:1px solid #404145;color:white;box-sizing:border-box}.ant-input::placeholder{color:#E6E6E6}.ant-input-affix-wrapper{background-color:#28282C !important;border:1px solid #404145;box-sizing:border-box}.ant-input-affix-wrapper .ant-input{color:white !important}.ant-input-affix-wrapper .ant-input-password-icon{color:white !important}.m-ant-btn.ant-btn{background-color:#3F51B5;box-shadow:none}.m-ant-btn.ant-btn:hover{background-color:#606fc7 !important}.m-ant-btn.ant-btn:active{background-color:#32408f !important}.m-border-ant-button.ant-btn{border:1px solid #5575F2 !important;color:#5575F2 !important;background-color:#1E1E1F !important}.ant-checkbox-wrapper{color:#848484}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner{background-color:#28282C !important;border:1px solid #404145}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner::after{background-color:#3F51B5 !important}.ant-checkbox-wrapper .ant-checkbox-checked .ant-checkbox-inner{background-color:#3F51B5 !important;border:1px solid #404145}.ant-table{background-color:#1B1E24 !important;border-radius:0px !important}.ant-table .ant-table-header .ant-table-cell{background-color:#1B1E24;color:#808080;box-shadow:none;border-bottom:1px solid transparent}.ant-table .ant-table-header .ant-table-cell::before{visibility:hidden}.ant-table .ant-table-body .ant-table-row{background-color:#16191e;color:white}.ant-table .ant-table-body .ant-table-row .ant-table-cell{border-bottom:1px solid #292F3A}.ant-table .ant-table-body .ant-table-row-selected .ant-table-cell{background-color:#0d0f12 !important;color:white}.ant-table .ant-table-body .ant-table-cell-row-hover{background-color:#0d0f12 !important}.ant-pagination .ant-pagination-prev{margin-right:10px !important}.ant-pagination .ant-pagination-prev,.ant-pagination .ant-pagination-next{width:30px !important;height:30px !important;border-radius:50%;background:#20242C}.ant-pagination .ant-pagination-prev .anticon,.ant-pagination .ant-pagination-next .anticon{color:#808080}.ant-pagination .ant-pagination-item{width:30px !important;height:30px !important;line-height:30px !important;border-radius:50%;background:#20242C !important;margin-right:10px !important}.ant-pagination .ant-pagination-item:hover{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item:hover a{color:black !important}.ant-pagination .ant-pagination-item-active{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item-active a{color:black !important}.ant-popover:not(.ant-popconfirm) .ant-popover-arrow::before{background-color:#07090B !important}.ant-popover:not(.ant-popconfirm) .ant-popover-content .ant-popover-inner{background-color:#07090B}.ant-modal-mask{background-color:rgba(0,0,0,0.25) !important}.ant-modal .ant-modal-content{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header .ant-modal-title{text-align:center;color:#EEEEEE;font-weight:bold}.ant-modal .ant-modal-content .ant-modal-body{max-height:70vh;overflow-y:auto}.ant-slider:hover .ant-slider-rail{background-color:#fff}.ant-slider .ant-slider-rail{background-color:#D9D9D9}.ant-slider .ant-slider-track{background-color:#3672E9}.ant-slider .ant-slider-handle::after{background-color:#3672E9;box-shadow:0 0 0 2px #3672E9}
|
||||
.ant-select .ant-select-selector{background-color:#28282C !important;border:1px solid #404145 !important;box-sizing:border-box}.ant-select .ant-select-selector .ant-select-selection-item{color:white}.ant-select .ant-select-selector .ant-select-selection-placeholder{color:#EEEEEE}.ant-select .ant-select-suffix{color:white !important}.ant-input{background-color:#28282C !important;border:1px solid #404145;color:white !important;box-sizing:border-box}.ant-input::placeholder{color:#E6E6E6}.ant-input-affix-wrapper{background-color:#28282C !important;border:1px solid #404145;box-sizing:border-box}.ant-input-affix-wrapper .ant-input{color:white !important}.ant-input-affix-wrapper .ant-input-password-icon{color:white !important}.ant-input-affix-wrapper .ant-input-show-count-suffix{color:white}.m-ant-btn.ant-btn{background-color:#3F51B5;box-shadow:none}.m-ant-btn.ant-btn:hover{background-color:#606fc7 !important}.m-ant-btn.ant-btn:active{background-color:#32408f !important}.m-border-ant-button.ant-btn{border:1px solid #5575F2 !important;color:#5575F2 !important;background-color:#1E1E1F !important}.ant-checkbox-wrapper{color:#848484}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner{background-color:#28282C !important;border:1px solid #404145}.ant-checkbox-wrapper .ant-checkbox .ant-checkbox-inner::after{background-color:#3F51B5 !important}.ant-checkbox-wrapper .ant-checkbox-checked .ant-checkbox-inner{background-color:#3F51B5 !important;border:1px solid #404145}.ant-table{background-color:#1B1E24 !important;border-radius:0px !important}.ant-table .ant-table-header .ant-table-cell{background-color:#1B1E24;color:#808080;box-shadow:none;border-bottom:1px solid transparent}.ant-table .ant-table-header .ant-table-cell::before{visibility:hidden}.ant-table .ant-table-body .ant-table-row{background-color:#16191e;color:white}.ant-table .ant-table-body .ant-table-row .ant-table-cell{border-bottom:1px solid #292F3A}.ant-table .ant-table-body .ant-table-row-selected .ant-table-cell{background-color:#0d0f12 !important;color:white}.ant-table .ant-table-body .ant-table-cell-row-hover{background-color:#0d0f12 !important}.ant-table .ant-table-body .ant-table-placeholder{background:transparent !important}.ant-table .ant-table-body .ant-table-placeholder .ant-table-cell{border:none}.ant-pagination{-webkit-app-region:no-drag}.ant-pagination .ant-pagination-prev{margin-right:10px !important}.ant-pagination .ant-pagination-prev,.ant-pagination .ant-pagination-next{width:30px !important;height:30px !important;border-radius:50%;background:#20242C}.ant-pagination .ant-pagination-prev .anticon,.ant-pagination .ant-pagination-next .anticon{color:#808080}.ant-pagination .ant-pagination-item{width:30px !important;height:30px !important;line-height:30px !important;border-radius:50%;background:#20242C !important;margin-right:10px !important}.ant-pagination .ant-pagination-item>a{color:#878787 !important}.ant-pagination .ant-pagination-item:hover{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item:hover a{color:black !important}.ant-pagination .ant-pagination-item-active{background:#5575F2 !important;border:none;box-shadow:0px 0px 10px 0px #66C8FF}.ant-pagination .ant-pagination-item-active a{color:black !important}.ant-popover{-webkit-app-region:no-drag}.ant-popover:not(.ant-popconfirm) .ant-popover-arrow::before{background-color:#07090B !important}.ant-popover:not(.ant-popconfirm) .ant-popover-content .ant-popover-inner{background-color:#07090B}.ant-modal-mask{background-color:rgba(0,0,0,0.25) !important}.ant-modal{-webkit-app-region:no-drag}.ant-modal .ant-modal-content{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header{background-color:#07090B}.ant-modal .ant-modal-content .ant-modal-header .ant-modal-title{text-align:center;color:#EEEEEE;font-weight:bold}.ant-modal .ant-modal-content .ant-modal-body{max-height:70vh;overflow-y:auto}.ant-slider:hover .ant-slider-rail{background-color:#fff}.ant-slider .ant-slider-rail{background-color:#D9D9D9}.ant-slider .ant-slider-track{background-color:#3672E9}.ant-slider .ant-slider-handle::after{background-color:#3672E9;box-shadow:0 0 0 2px #3672E9}.ant-empty .ant-empty-description{color:#808080}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,31 @@ $table-content-background-color: rgb(22, 25, 30);
|
|||
$pagination-background-color: #20242C;
|
||||
$pagination-hover-background-color: #5575F2;
|
||||
|
||||
.ant-select {
|
||||
.ant-select-selector {
|
||||
background-color: $input-background-color !important;
|
||||
border: 1px solid $input-border-color !important;
|
||||
box-sizing: border-box;
|
||||
|
||||
.ant-select-selection-item {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ant-select-selection-placeholder {
|
||||
color: #EEEEEE;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select-suffix {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
|
||||
// input
|
||||
.ant-input {
|
||||
background-color: $input-background-color !important;
|
||||
border: 1px solid $input-border-color;
|
||||
color: white;
|
||||
color: white !important;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::placeholder {
|
||||
|
|
@ -32,6 +52,10 @@ $pagination-hover-background-color: #5575F2;
|
|||
.ant-input-password-icon {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.ant-input-show-count-suffix {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
// button
|
||||
|
|
@ -115,11 +139,21 @@ $pagination-hover-background-color: #5575F2;
|
|||
.ant-table-cell-row-hover {
|
||||
background-color: darken($table-content-background-color, 4%) !important;
|
||||
}
|
||||
|
||||
.ant-table-placeholder {
|
||||
background: transparent !important;
|
||||
|
||||
.ant-table-cell {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pagination
|
||||
.ant-pagination {
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
.ant-pagination-prev {
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
|
@ -144,6 +178,10 @@ $pagination-hover-background-color: #5575F2;
|
|||
background: $pagination-background-color !important;
|
||||
margin-right: 10px !important;
|
||||
|
||||
>a {
|
||||
color: #878787 !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $pagination-hover-background-color !important;
|
||||
border: none;
|
||||
|
|
@ -167,6 +205,10 @@ $pagination-hover-background-color: #5575F2;
|
|||
}
|
||||
|
||||
// popover
|
||||
.ant-popover {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.ant-popover:not(.ant-popconfirm) {
|
||||
.ant-popover-arrow {
|
||||
&::before {
|
||||
|
|
@ -187,6 +229,8 @@ $pagination-hover-background-color: #5575F2;
|
|||
}
|
||||
|
||||
.ant-modal {
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
.ant-modal-content {
|
||||
background-color: #07090B;
|
||||
|
||||
|
|
@ -229,4 +273,11 @@ $pagination-hover-background-color: #5575F2;
|
|||
box-shadow: 0 0 0 2px #3672E9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// empty
|
||||
.ant-empty {
|
||||
.ant-empty-description {
|
||||
color: #808080;
|
||||
}
|
||||
}
|
||||
|
|
@ -50,5 +50,5 @@ export default defineConfig({
|
|||
base: './', // 这里更改打包相对绝对路径
|
||||
plugins: [
|
||||
react(),
|
||||
],
|
||||
]
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue