Compare commits

...

9 Commits

Author SHA1 Message Date
youngq 7f394dcede Merge branch 'yangjie' 2024-09-26 11:58:21 +08:00
youngq 5161699ad8 修复npm 安装报错问题 2024-09-26 11:57:30 +08:00
yj a6f191b736 去除多余代码 2024-09-26 11:42:58 +08:00
yj 75a4f1b191 优化 2024-09-26 11:40:23 +08:00
yj eecbd88eea 优化 2024-09-26 11:10:31 +08:00
yj 6df9b3fa63 去除多余代码 2024-09-26 10:54:35 +08:00
yj 84bd0ba160 样式优化 2024-09-26 10:21:29 +08:00
yj ffcd869113 优化 2024-09-26 09:40:01 +08:00
yj 7c7b2dd574 匿名登录 2024-09-26 09:28:23 +08:00
17 changed files with 351 additions and 80 deletions

31
main.js
View File

@ -13,12 +13,14 @@ const {
const path = require('node:path')
const fs = require('fs');
const https = require('https');
const Registry = require('winreg');
const { autoUpdater, CancellationToken } = require('electron-updater');
const cancellationToken = new CancellationToken()
app.allowRendererProcessReuse = false;
let mainWindow = null;
let isMaximized = false;
let env;
let regKey;
class AppWindow extends BrowserWindow {
constructor(config) {
@ -134,6 +136,10 @@ app.on('ready', () => {
updateHandle() // 每一小时检查更新
}, 1000 * 60 * 60)
createTray()
regKey = new Registry({
hive: Registry.HKCU,
key: '\\Software\\ZhiHuiXiang'
});
// 获取当前脚本所在目录的绝对路径
const currentDirectory = __dirname;
// 获取安装父目录
@ -272,7 +278,28 @@ app.on('ready', () => {
const y = Math.round((display.workArea.height - mainWindow.getSize()[1]) / 2);
mainWindow.setPosition(x, y);
});
// 写入注册表
ipcMain.handle('setRegistry', (event, uuid) => {
regKey.create((err) => {
if (err) {
return;
}
// 设置键和值
regKey.set('uuid', Registry.REG_SZ, uuid, (err) => {
if (err) {
return;
}
});
});
});
// 读取注册表
ipcMain.handle('getRegistry', async () => {
return new Promise((resolve, reject) => {
regKey.get('uuid', (err, item) => {
resolve(item)
})
});
});
// 监听渲染进程请求应用数据目录
ipcMain.handle('get-user-data-path', () => {
return app.getPath('userData');
@ -360,8 +387,6 @@ function quitAndInstall() {
autoUpdater.quitAndInstall();
}
// 下载文件
function downloadFile(url, dest) {
return new Promise((resolve, reject) => {

75
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "WGShare.Metting",
"version": "0.1.14",
"version": "0.3.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "WGShare.Metting",
"version": "0.1.14",
"version": "0.3.5",
"dependencies": {
"@ant-design/icons": "^5.3.7",
"@microsoft/signalr": "^8.0.0",
@ -29,10 +29,12 @@
"react-router-dom": "^6.23.1",
"sass": "^1.77.5",
"tldraw": "^2.2.0",
"webm-duration-fix-buffer": "^1.0.0"
"uuid": "^10.0.0",
"webm-duration-fix-buffer": "^1.0.0",
"winreg": "^1.2.5"
},
"devDependencies": {
"@types/react": "^17.0.33",
"@types/react": "^18.0.0",
"@types/react-dom": "^17.0.25",
"@vitejs/plugin-react": "^1.0.7",
"concurrently": "^7.6.0",
@ -2506,13 +2508,12 @@
"devOptional": true
},
"node_modules/@types/react": {
"version": "17.0.80",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-17.0.80.tgz",
"integrity": "sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==",
"version": "18.3.9",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-18.3.9.tgz",
"integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==",
"devOptional": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "^0.16",
"csstype": "^3.0.2"
}
},
@ -2525,6 +2526,17 @@
"@types/react": "^17"
}
},
"node_modules/@types/react-dom/node_modules/@types/react": {
"version": "17.0.82",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-17.0.82.tgz",
"integrity": "sha512-wTW8Lu/PARGPFE8tOZqCvprOKg5sen/2uS03yKn2xbCDFP9oLncm7vMDQ2+dEQXHVIXrOpW6u72xUXEXO0ypSw==",
"devOptional": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "^0.16",
"csstype": "^3.0.2"
}
},
"node_modules/@types/responselike": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/@types/responselike/-/responselike-1.0.3.tgz",
@ -11808,6 +11820,18 @@
"resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
},
"node_modules/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8flags": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/v8flags/-/v8flags-3.2.0.tgz",
@ -12038,6 +12062,11 @@
"resolved": "https://registry.npmmirror.com/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ=="
},
"node_modules/winreg": {
"version": "1.2.5",
"resolved": "https://registry.npmmirror.com/winreg/-/winreg-1.2.5.tgz",
"integrity": "sha512-uf7tHf+tw0B1y+x+mKTLHkykBgK2KMs3g+KlzmyMbLvICSHQyB/xOFjTT8qZ3oeTFyU7Bbj4FzXitGG6jvKhYw=="
},
"node_modules/winston": {
"version": "3.13.1",
"resolved": "https://registry.npmmirror.com/winston/-/winston-3.13.1.tgz",
@ -13813,13 +13842,12 @@
"devOptional": true
},
"@types/react": {
"version": "17.0.80",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-17.0.80.tgz",
"integrity": "sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==",
"version": "18.3.9",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-18.3.9.tgz",
"integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==",
"devOptional": true,
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "^0.16",
"csstype": "^3.0.2"
}
},
@ -13830,6 +13858,19 @@
"devOptional": true,
"requires": {
"@types/react": "^17"
},
"dependencies": {
"@types/react": {
"version": "17.0.82",
"resolved": "https://registry.npmmirror.com/@types/react/-/react-17.0.82.tgz",
"integrity": "sha512-wTW8Lu/PARGPFE8tOZqCvprOKg5sen/2uS03yKn2xbCDFP9oLncm7vMDQ2+dEQXHVIXrOpW6u72xUXEXO0ypSw==",
"devOptional": true,
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "^0.16",
"csstype": "^3.0.2"
}
}
}
},
"@types/responselike": {
@ -20805,6 +20846,11 @@
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="
},
"v8flags": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/v8flags/-/v8flags-3.2.0.tgz",
@ -20983,6 +21029,11 @@
"resolved": "https://registry.npmmirror.com/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ=="
},
"winreg": {
"version": "1.2.5",
"resolved": "https://registry.npmmirror.com/winreg/-/winreg-1.2.5.tgz",
"integrity": "sha512-uf7tHf+tw0B1y+x+mKTLHkykBgK2KMs3g+KlzmyMbLvICSHQyB/xOFjTT8qZ3oeTFyU7Bbj4FzXitGG6jvKhYw=="
},
"winston": {
"version": "3.13.1",
"resolved": "https://registry.npmmirror.com/winston/-/winston-3.13.1.tgz",

View File

@ -1,7 +1,7 @@
{
"name": "WGShare.Metting",
"private": true,
"version": "0.3.10",
"version": "0.4.3",
"main": "main.js",
"authors": "yj",
"description": "智汇享",
@ -44,10 +44,12 @@
"react-router-dom": "^6.23.1",
"sass": "^1.77.5",
"tldraw": "^2.2.0",
"webm-duration-fix-buffer": "^1.0.0"
"uuid": "^10.0.0",
"webm-duration-fix-buffer": "^1.0.0",
"winreg": "^1.2.5"
},
"devDependencies": {
"@types/react": "^17.0.33",
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^17.0.25",
"@vitejs/plugin-react": "^1.0.7",
"concurrently": "^7.6.0",

View File

@ -64,5 +64,13 @@ window.electron = {
// 下载文件
downFile: (callback) => {
ipcRenderer.on('downFile', callback)
}
},
// 读取注册表
getRegistry: () => {
return ipcRenderer.invoke('getRegistry')
},
// 写入注册表
setRegistry: (uuid) => {
ipcRenderer.invoke('setRegistry', uuid)
},
}

View File

@ -9,7 +9,7 @@ import Meeting from '@/page/Meeting/index'
import NotFound from '@/page/NotFound/index'
import { storage } from '@/utils'
import { message, Spin } from "antd";
import { onOtherSignalr, onReconnected, onStart, onStop, startSignalr } from "@/utils/package/signalr";
import { onOtherSignalr, onReconnected, onStop, startSignalr } from "@/utils/package/signalr";
import JoinMeetingModal from "@/components/JoinMeetingModal";
import UpdateModal from "@/components/UpdateModal";
import * as CryptoJS from 'crypto-js';
@ -35,7 +35,7 @@ const App: React.FC = () => {
useEffect(() => {
let userInfo = JSON.parse(storage.getItem('user') as string)
let loginInfo = JSON.parse(storage.getItem('login') as string)
if (userInfo) {
if (userInfo && Number(userInfo.perms)) {
if (loginInfo && loginInfo.isAutoLogin) {
PostLogin({
account: loginInfo.account,
@ -160,13 +160,10 @@ const App: React.FC = () => {
width: window.innerWidth,
height: window.innerHeight,
});
try {
window.electron.getIsMaximized().then((res: boolean) => {
const dom = document.getElementById('root') as HTMLElement;
dom.style.borderRadius = res ? '0px' : '10px'
})
} catch {
}
window.electron.getIsMaximized().then((res: boolean) => {
const dom = document.getElementById('root') as HTMLElement;
dom.style.borderRadius = res ? '0px' : '10px'
})
};
const onEventSignalr = (): void => {
@ -196,7 +193,6 @@ const App: React.FC = () => {
window.electron.getWindowSize().then((res: any) => {
switch (path) {
case '/login':
storage.removeItem('user')
storage.setItem('userLogin', false)
navigate('/login')
break;
@ -230,6 +226,7 @@ const App: React.FC = () => {
}
} else if (e.key === 'userLogin') {
if (!Boolean(e.value)) {
storage.removeItem('user')
navigate('/login')
}
}

View File

@ -15,4 +15,11 @@ export const PostRefresh = (refreshToken: string) =>
request({
url: `auth/refresh?refreshToken=${refreshToken}`,
method: 'post',
})
export const PostAnonLogin = (data: any) =>
request({
url: `/auth/anon-login`,
method: 'post',
data,
})

View File

@ -66,11 +66,9 @@ const Operation: React.FC = () => {
}, []);
const getIsMaximized = (): void => {
try {
window.electron.getIsMaximized().then((res: boolean) => {
changeOperationList(res ? 'maximize' : 'unmaximize')
})
} catch { }
window.electron.getIsMaximized().then((res: boolean) => {
changeOperationList(res ? 'maximize' : 'unmaximize')
})
}
const changeOperationList = (str: OperationKeyType): void => {

View File

@ -196,7 +196,7 @@ const SharedFilesModel = forwardRef((props: any, ref: any) => {
setIsUpFile(false)
setUploadProgress(100)
message.success('上传成功')
}).catch(error => {
}).catch(_error => {
setIsUpFile(false)
message.error('上传失败')
});

View File

@ -16,7 +16,6 @@
.buttons {
width: 100%;
margin-top: 10px;
text-align: center;
.button2 {

View File

@ -139,7 +139,6 @@ const Home: React.FC = () => {
title="提示"
description="确认退出吗?"
onConfirm={() => {
storage.removeItem('user')
storage.setItem('userLogin', false)
}}
onCancel={() => {

View File

@ -22,7 +22,7 @@
display: flex;
flex-direction: column;
@for $i from 1 through 3 {
@for $i from 1 through 5 {
>div:nth-child(#{$i}) {
@if $i ==1 {
flex-shrink: 0;
@ -66,6 +66,66 @@
}
@else if $i ==3 {
flex-shrink: 0;
margin-bottom: 20px;
color: #ccc;
font-size: 16px;
display: flex;
align-items: center;
>div {
flex-grow: 1;
height: 1px;
background-color: #3F3F3F;
}
>span {
flex-shrink: 0;
margin: 0 4px;
color: #7A7A7A;
font-size: 12px;
}
}
@else if $i ==4 {
display: flex;
align-items: center;
margin-bottom: 10px;
@for $i from 1 through 2 {
>div:nth-child(#{$i}) {
@if $i ==1 {
flex-grow: 1;
}
@else if $i ==2 {
flex-shrink: 0;
cursor: pointer;
height: 44px;
line-height: 44px;
display: flex;
justify-content: center;
align-items: center;
background-color: #3A1457;
box-shadow: none;
border-radius: 10px;
width: 56px;
margin-left: 4px;
transition: 0.3s;
&:hover {
background-color: lighten(#3A1457, 5%) !important;
}
&:active {
background-color: darken(#3A1457, 5%) !important;
}
}
}
}
}
@else if $i ==5 {
flex-shrink: 0;
color: #ccc;
text-align: right;
@ -75,12 +135,6 @@
}
}
// 登录页固定大小不允许放大缩小固需要单独写样式~
.loginInput {
height: 44px;
line-height: 44px;
}
.loginInputIcon {
:global {
.ant-input {

View File

@ -2,12 +2,14 @@
import styles from '@/page/Login/index.module.scss'
import { useEffect, useState } from "react";
import { useNavigate } from 'react-router-dom';
import { Input, Button, Checkbox, message } from "antd"
import { Input, Button, Checkbox, message, Modal } from "antd"
import { storage } from '@/utils'
import { GetCheckUser, PostLogin } from '@/api/Login'
import { GetCheckUser, PostAnonLogin, PostLogin } from '@/api/Login'
import * as CryptoJS from 'crypto-js';
import ImageUrl from '@/utils/package/imageUrl'
import { startSignalr } from '@/utils/package/signalr';
import { v4 as uuidv4 } from 'uuid';
import { GetCheckoutRoomNum, GetRoomInfo, GetRoomRtcToken } from '@/api/Home/Index';
const Login: React.FC = () => {
const navigate = useNavigate();
const [accountPasswordStatus, setAccountPasswordStatus] = useState<boolean>(false);
@ -30,17 +32,19 @@ const Login: React.FC = () => {
],
optionsValue: []
});
const [anonInfo, setAnonInfo] = useState({
deviceId: '',
nickName: '',
roomNum: '',
})
const [nameModal, setNameModal] = useState(false)
useEffect(() => {
try {
window.electron.setMainWindowSize({
width: 752,
height: 520,
key: 'login'
})
} catch {
}
window.electron.setMainWindowSize({
width: 752,
height: 520,
key: 'login'
})
if (storage.getItem('login')) {
const login = JSON.parse(storage.getItem('login') as string);
const data = {
@ -119,7 +123,20 @@ const Login: React.FC = () => {
optionsValue: checkedValues,
}))
};
const getRoomRtcToken = async (roomNum: string, callBack: Function): Promise<void> => {
Promise.all([GetRoomRtcToken(roomNum), GetRoomRtcToken(roomNum + 'a')]).then(res => {
if (res[0].code === 200 && res[1].code === 200) {
callBack({
token: res[0].data,
tokenA: res[1].data,
})
} else {
storage.setItem('loading', false)
}
}).catch(() => {
storage.setItem('loading', false)
})
}
// 登录
const loginClick = (): void => {
if (operation.password === '') {
@ -141,16 +158,12 @@ const Login: React.FC = () => {
}))
storage.setItem('user', JSON.stringify(res.data))
storage.setItem('userLogin', true)
try {
window.electron.getWindowSize().then((res: any) => {
window.electron.setMainWindowSize({
width: Math.ceil(res.width / 1.5),
height: Math.ceil(res.height / 1.3),
})
window.electron.getWindowSize().then((res: any) => {
window.electron.setMainWindowSize({
width: Math.ceil(res.width / 1.5),
height: Math.ceil(res.height / 1.3),
})
} catch {
}
})
startSignalr()
navigate('/home')
}
@ -228,11 +241,127 @@ const Login: React.FC = () => {
</div> : null}
</div>
</div>
<div>
<div></div>
<span></span>
<div></div>
</div>
<div className={`drag`}>
<div>
<Input
placeholder="输入会议号"
style={{ height: '44px' }}
value={anonInfo.roomNum}
onChange={e => {
setAnonInfo({
...anonInfo,
roomNum: e.target.value
})
}} />
</div>
<div
onClick={() => {
if (!anonInfo.roomNum) {
return message.error('请输入房间号!')
}
GetCheckoutRoomNum(anonInfo.roomNum).then(res => {
if (res.code === 200) {
if (res.data) {
window.electron.getRegistry().then(async (res: any) => {
const uuid = uuidv4();
if (!res) {
window.electron.setRegistry(uuid)
}
setAnonInfo({
...anonInfo,
deviceId: res ? res.value : uuid,
nickName: storage.getItem('nickName') || ''
})
storage.getItem('nickName')
setNameModal(true)
})
} else {
message.error('房间号不存在!')
}
}
})
}}
><img src={ImageUrl.icon3} alt="" /></div>
</div>
<div>
{version}
</div>
</div>
</div>
<Modal title="参会昵称" open={nameModal} footer={null} closable={false} centered width={'300px'}>
<div>
<div>
<Input
placeholder="请输入参会昵称"
value={anonInfo.nickName}
onChange={(e) => {
setAnonInfo({
...anonInfo,
nickName: e.target.value
})
storage.setItem('nickName', e.target.value)
}}
/>
</div>
<div style={{
display: 'flex', justifyContent: 'center', marginTop: '10px'
}}>
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setNameModal(false)}></Button>
<Button type="primary" className='m-ant-btn' onClick={() => {
if (!anonInfo.nickName) {
return message.error('请输入参会昵称!')
}
storage.setItem('loading', true)
PostAnonLogin(anonInfo).then(async (res) => {
if (res.code == 200) {
storage.setItem('user', JSON.stringify(res.data))
storage.setItem('userLogin', true)
await startSignalr()
getRoomRtcToken(anonInfo.roomNum, (options: any) => {
if (options) {
GetRoomInfo(anonInfo.roomNum).then(async (res) => {
if (res.code === 200) {
setTimeout(() => {
storage.setItem('loading', false)
window.electron.getWindowSize().then((res: any) => {
window.electron.setMainWindowSize({
width: Math.ceil(res.width / 1.5),
height: Math.ceil(res.height / 1.3),
})
})
navigate(`/meeting`, {
state: {
channelId: anonInfo.roomNum,
token: options.token,
tokenA: options.tokenA,
roomId: res.data.id,
roomName: res.data.roomName,
enableMicr: false,
enableCamera: false,
}
})
}, 2000)
} else {
storage.setItem('loading', false)
}
}).catch(() => {
storage.setItem('loading', false)
})
}
})
}
}).catch(() => {
storage.setItem('loading', false)
})
}}></Button>
</div>
</div>
</Modal>
</>
)
}

View File

@ -188,15 +188,11 @@ const Meeting: React.FC = () => {
let time: NodeJS.Timeout;
// let getDesktopCapturerVideoTime: NodeJS.Timeout;
setUser(userInfo)
setTimeout(() => {
if (location.hash.indexOf('/login') === -1) {
window.electron.getIsMaximized().then((res: boolean) => {
if (!res) {
window.electron.setViewStatus('maximize')
}
})
window.electron.getIsMaximized().then((res: boolean) => {
if (!res) {
window.electron.setViewStatus('maximize')
}
}, 1000)
})
setMeetingMode('StandardMode');
agoraInit()
storage.setItem('noViewChatList', 0)
@ -667,8 +663,8 @@ const Meeting: React.FC = () => {
// 声网初始化
const agoraInit = async () => {
await getJoin(state.enableMicr, state.enableCamera)
await agora.init(true)
await getJoin(state.enableMicr, state.enableCamera)
agora.registerEventHandler({
onJoinChannelSuccess: async (connection: RtcConnection, _elapsed: number) => {
if (connection.channelId === state.channelId) {
@ -1215,8 +1211,12 @@ const Meeting: React.FC = () => {
if (bool) {
await getLeave()
}
agora.leaveChannel()
navigate('/home/index')
await agora.leaveChannel()
if (Number(user.perms)) {
navigate('/home/index')
} else {
storage.setItem('userLogin', false)
}
}
// 分享屏幕
const clickSharedScreen = async (): Promise<void> => {

2
src/render.d.ts vendored
View File

@ -16,6 +16,8 @@ export interface IElectronAPI {
downFile: (callBack: Function) => void;
quitAndInstall: (callBack: Function) => void;
getVersion: () => Promise<string>;
setRegistry: (uuid: string) => any;
getRegistry: () => any;
}
declare global {

View File

@ -1,2 +1,3 @@
declare module 'react-dom/client';
declare module 'crypto-js';
declare module 'crypto-js';
declare module 'uuid';

View File

@ -10,7 +10,7 @@ export const startSignalr = async () => {
accessTokenFactory: () => user.token
})
.build();
onStart()
await onStart()
storage.setItem('isSignalr', true)
connection.onclose(async () => {
await onStart()

View File

@ -112,7 +112,6 @@ class Request {
}
}
function toLogin() {
storage.removeItem('user')
storage.setItem('userLogin', false)
}
function updatePostRefresh() {