diff --git a/main.js b/main.js index 78d4267..41e02c9 100644 --- a/main.js +++ b/main.js @@ -98,7 +98,7 @@ function createNotification(user) { const notification = new Notification({ title: `${user.name} 邀请你加入`, body: user.body, - icon: path.join(`${__dirname}/src/assets/avatar.png`) + // icon: path.join(`${__dirname}/src/assets/avatar.png`) }); notification.show(); mainWindow.focus(); diff --git a/package-lock.json b/package-lock.json index 325d141..746ad92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@microsoft/signalr": "^8.0.0", "@types/node": "^20.14.9", "agora-electron-sdk": "^4.3.2", + "animate.css": "^4.1.1", "antd": "^5.18.2", "axios": "^1.7.2", "crypto-js": "^4.2.0", @@ -2686,6 +2687,11 @@ "ajv": "^6.9.1" } }, + "node_modules/animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==" + }, "node_modules/ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -13827,6 +13833,11 @@ "dev": true, "requires": {} }, + "animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==" + }, "ansi-colors": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-1.1.0.tgz", diff --git a/package.json b/package.json index bd3f40b..5f06b09 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@microsoft/signalr": "^8.0.0", "@types/node": "^20.14.9", "agora-electron-sdk": "^4.3.2", + "animate.css": "^4.1.1", "antd": "^5.18.2", "axios": "^1.7.2", "crypto-js": "^4.2.0", @@ -81,4 +82,4 @@ }, "extraResources": [] } -} \ No newline at end of file +} diff --git a/src/App.tsx b/src/App.tsx index 7c0e8a1..e828f58 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,6 +12,8 @@ import { storage } from '@/utils' import { Spin } from "antd"; import { onInvitation } from "@/utils/package/signalr"; import JoinMeetingModal from "./components/JoinMeetingModal"; +import * as CryptoJS from 'crypto-js'; +import { PostLogin } from "@/api/Login"; const App: React.FC = () => { const navigate = useNavigate(); @@ -22,28 +24,47 @@ const App: React.FC = () => { }); const [spinning, setSpinning] = useState(false); useEffect(() => { - if (storage.getItem('user')) { - try { - window.electron.setMainWindowSize({ - width: 1200, - height: 800, - }) - } catch { - - } - navigate('/home') - } else { + function toLogin() { try { window.electron.setMainWindowSize({ width: 752, height: 520, key: 'login' }) - } catch { - - } + } catch { } + storage.removeItem('user') navigate('/login') } + function toHome() { + try { + window.electron.setMainWindowSize({ + width: 1200, + height: 800, + }) + } catch { } + navigate('/home') + } + let userInfo = JSON.parse(storage.getItem('user') as string) + let loginInfo = JSON.parse(storage.getItem('login') as string) + if (userInfo) { + if (loginInfo && loginInfo.isAutoLogin) { + PostLogin({ + account: loginInfo.account, + pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex) + }).then(res => { + if (res.code === 200) { + storage.setItem('user', JSON.stringify(res.data)) + toHome() + } else { + toLogin() + } + }) + } else { + toLogin() + } + } else { + toLogin() + } if (import.meta.env.VITE_ENV !== 'development') { document.addEventListener('keydown', (event) => { if ((event.ctrlKey || event.metaKey) && event.key === 'r') { diff --git a/src/assets/icon21.png b/src/assets/icon21.png index 3cfa117..127b9b2 100644 Binary files a/src/assets/icon21.png and b/src/assets/icon21.png differ diff --git a/src/assets/icon3.png b/src/assets/icon3.png index 15e99a1..e4d9654 100644 Binary files a/src/assets/icon3.png and b/src/assets/icon3.png differ diff --git a/src/components/Avatar/index.module.scss b/src/components/Avatar/index.module.scss new file mode 100644 index 0000000..cd9fd83 --- /dev/null +++ b/src/components/Avatar/index.module.scss @@ -0,0 +1,11 @@ +.avatar { + background-color: #3F51B5; + height: 36px; + width: 36px; + border-radius: 50%; + overflow: hidden; + color: white; + font-size: 14px; + line-height: 36px; + text-align: center; +} \ No newline at end of file diff --git a/src/components/Avatar/index.tsx b/src/components/Avatar/index.tsx new file mode 100644 index 0000000..6b5f066 --- /dev/null +++ b/src/components/Avatar/index.tsx @@ -0,0 +1,18 @@ +import styles from '@/components/Avatar/index.module.scss' +import { useState, useImperativeHandle, forwardRef } from "react"; +const Avatar = forwardRef((props: any, ref: any) => { + useImperativeHandle(ref, () => ({ + getData: () => { + + } + })) + return ( + <> +
+ {props.name ? props.name.slice(-2) : '访客'} +
+ + ) +}) + +export default Avatar \ No newline at end of file diff --git a/src/components/InvitingPersonnelModal/index.module.scss b/src/components/InvitingPersonnelModal/index.module.scss index 1447ee2..d94deba 100644 --- a/src/components/InvitingPersonnelModal/index.module.scss +++ b/src/components/InvitingPersonnelModal/index.module.scss @@ -29,17 +29,7 @@ align-items: center; >div:nth-child(2) { - width: 36px; - height: 36px; - overflow: hidden; - border-radius: 50%; margin: 0 10px; - - >img { - width: 100%; - height: 100%; - object-fit: cover; - } } >span { @@ -86,17 +76,7 @@ margin-bottom: 10px; >div { - width: 36px; - height: 36px; - overflow: hidden; - border-radius: 50%; margin: 0 10px; - - >img { - width: 100%; - height: 100%; - object-fit: cover; - } } >span { diff --git a/src/components/InvitingPersonnelModal/index.tsx b/src/components/InvitingPersonnelModal/index.tsx index 5132fc8..18077fe 100644 --- a/src/components/InvitingPersonnelModal/index.tsx +++ b/src/components/InvitingPersonnelModal/index.tsx @@ -1,15 +1,17 @@ import styles from '@/components/InvitingPersonnelModal/index.module.scss' import { Button, Checkbox, Input, Modal, Pagination, message } from 'antd'; import { useState, useImperativeHandle, forwardRef, useEffect } from "react"; -import ImageUrl from '@/utils/package/imageUrl'; import { SearchOutlined } from '@ant-design/icons'; import { GetUserList } from '@/api/Home/User'; import { useLocation } from 'react-router-dom'; import { PostRoomInvite } from '@/api/Meeting'; import { storage } from '@/utils'; +import Avatar from '@/components/Avatar'; const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { useImperativeHandle(ref, () => ({ changeInvitingPersonnelModal: () => { + let userInfo = JSON.parse(storage.getItem('user') as string) + setUser(userInfo) getUserList() setIsInvitingPersonnelModal(true) } @@ -17,6 +19,7 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { const { state } = useLocation(); const [isInvitingPersonnelModal, setIsInvitingPersonnelModal] = useState(false); const [isFirstRender, setIsFirstRender] = useState(true); + const [user, setUser] = useState({}); const [operation, setOperation] = useState<{ options: { label: string; value: number }[]; optionsValue: number[]; @@ -96,7 +99,7 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { footer={null} onCancel={() => setIsInvitingPersonnelModal(false)} centered - width={'560px'} + width={'700px'} >
@@ -147,8 +150,8 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { return checkedList } }) - }} defaultChecked={item.checked}> -
+ }} defaultChecked={item.checked} disabled={!item.isOnline || item.account === user.account}> +
{item.userName}
{item.isOnline ? '在线' : '离线'}
@@ -159,13 +162,13 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { ...list, pageIndex: e }) - }} pageSize={list.pageSize} current={list.pageIndex} hideOnSinglePage={true} /> + }} pageSize={list.pageSize} current={list.pageIndex} hideOnSinglePage={true} showLessItems={true}/>
已选成员
{checkedList.map((item: any, index: number) =>
-
+
{item.userName}
)}
@@ -175,8 +178,7 @@ const InvitingPersonnelModal = forwardRef((props: any, ref: any) => { @@ -157,17 +157,6 @@ const Index: React.FC = () => {
- { - setCreateRoomFrom({ - ...createRoomFrom, - roomName: e.target.value - }) - }} - /> { { + function generateTimestampWithRandom(): string { + const timestamp = new Date().getTime(); + const lastSixDigits = timestamp.toString().slice(-6); + const randomTwoDigits = ('0' + Math.floor(Math.random() * 100)).slice(-2); + return lastSixDigits + randomTwoDigits; + } setCreateRoomFrom({ ...createRoomFrom, - roomNum: Math.floor(+new Date() / 1000).toString().slice(-8), + roomNum: generateTimestampWithRandom(), }) }} >获取随机房间号 } /> + { + setCreateRoomFrom({ + ...createRoomFrom, + roomName: e.target.value + }) + }} + autoSize />
{
} value={list.searchKeywod} onChange={(e) => { diff --git a/src/page/Home/index.module.scss b/src/page/Home/index.module.scss index 7479b5e..00e09c8 100644 --- a/src/page/Home/index.module.scss +++ b/src/page/Home/index.module.scss @@ -21,18 +21,8 @@ cursor: pointer; >div { - height: 40px; - width: 40px; - border-radius: 50%; - overflow: hidden; margin-right: 14px; flex-shrink: 0; - - >img { - width: 100%; - height: 100%; - object-fit: cover; - } } >span { diff --git a/src/page/Home/index.tsx b/src/page/Home/index.tsx index e7a722e..b30805b 100644 --- a/src/page/Home/index.tsx +++ b/src/page/Home/index.tsx @@ -7,6 +7,7 @@ import 'dayjs/locale/zh-cn' import { storage } from '@/utils'; import ImageUrl from '@/utils/package/imageUrl' import { startSignalr } from '@/utils/package/signalr'; +import Avatar from '@/components/Avatar'; dayjs.locale('zh-cn'); type navListType = { title: string; @@ -84,9 +85,9 @@ const Home: React.FC = () => {
- +
- 欢迎您,{userInfo?.userName} + 欢迎您,{userInfo.userName}
diff --git a/src/page/Login/index.module.scss b/src/page/Login/index.module.scss index 5ef2f2a..3d92f32 100644 --- a/src/page/Login/index.module.scss +++ b/src/page/Login/index.module.scss @@ -106,18 +106,19 @@ display: flex; justify-content: center; align-items: center; - background-color: #FFCFEB; + background-color: #3A1457; + box-shadow: none; border-radius: 10px; width: 56px; margin-left: 4px; transition: 0.3s; &:hover { - background-color: lighten(#FFCFEB, 5%) !important; + background-color: lighten(#3A1457, 5%) !important; } &:active { - background-color: darken(#FFCFEB, 5%) !important; + background-color: darken(#3A1457, 5%) !important; } } } @@ -139,6 +140,7 @@ .ant-input { height: 34px; line-height: 34px; + text-align: center; } } } diff --git a/src/page/Login/index.tsx b/src/page/Login/index.tsx index b98a89b..221aafb 100644 --- a/src/page/Login/index.tsx +++ b/src/page/Login/index.tsx @@ -77,7 +77,10 @@ const Login: React.FC = () => { setAccountPasswordStatus(false) } // 继续 - const continueClick = (): void => { + const continueClick = (): any => { + if (!operation.account) { + return message.error('请输入账号!') + } GetCheckUser(operation.account).then(res => { if (res.code === 200) { res.data ? setAccountPasswordStatus(true) : message.error('账号不存在!') @@ -87,6 +90,9 @@ const Login: React.FC = () => { // 设置勾选 const changeOptionsValue = (checkedValues: string[]): void => { + if (checkedValues.indexOf('isAutoLogin') >= 0 && checkedValues.indexOf('isRememberPassword') === -1) { + checkedValues.push('isRememberPassword') + } setOperation({ ...operation, optionsValue: checkedValues, @@ -159,22 +165,22 @@ const Login: React.FC = () => { placeholder="请输入账号" prefix={} suffix={ - 重置 - + : null) } /> - {!accountPasswordStatus ?
+ {!accountPasswordStatus ?
: null} - {accountPasswordStatus ?
+ {accountPasswordStatus ?
{ @@ -200,11 +206,11 @@ const Login: React.FC = () => {
-
+ {/*
or
-
+
*/} {/*
diff --git a/src/page/Meeting/index.module.scss b/src/page/Meeting/index.module.scss index a47af55..2374c4e 100644 --- a/src/page/Meeting/index.module.scss +++ b/src/page/Meeting/index.module.scss @@ -340,16 +340,6 @@ >div { flex-shrink: 0; - width: 30px; - height: 30px; - overflow: hidden; - border-radius: 50%; - - >img { - width: 100%; - height: 100%; - object-fit: cover; - } } } @@ -482,18 +472,7 @@ margin-left: 4px; } - >div { - width: 30px; - height: 30px; - overflow: hidden; - border-radius: 50%; - - >img { - width: 100%; - height: 100%; - object-fit: cover; - } - } + >div {} } >div:nth-child(2) { @@ -597,6 +576,19 @@ color: #EEEEEE; font-size: 14px; } + + &:hover { + >span { + color: #4096ff; + } + } + + &:active { + >span { + color: darken(#4096ff, 10%) !important; + ; + } + } } } } diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index 0b66bf9..b50ea0e 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -17,6 +17,7 @@ import dayjs from 'dayjs'; import durationPlugin from 'dayjs/plugin/duration'; import { VideoSourceType } from 'agora-electron-sdk'; import { GetUserList } from '@/api/Home/User'; +import Avatar from '@/components/Avatar'; dayjs.extend(durationPlugin); const { Column } = Table const Meeting: React.FC = () => { @@ -122,7 +123,7 @@ const Meeting: React.FC = () => { let time = null as any; if (isInit) { let userInfo = JSON.parse(storage.getItem('user') as string) - setMeetingMode(storage.getItem('meetingMode') as string || 'FreedomMode'); + setMeetingMode('StandardMode'); agora.init() agora.registerEventHandler({ onJoinChannelSuccess: async (info: any, _elapsed: any) => { @@ -258,14 +259,14 @@ const Meeting: React.FC = () => { switch (row.title) { case '成员列表': setStatusList({ - userList: true, + userList: statusList.userList ? false : true, userChatList: false, }) break; case '聊天': setStatusList({ userList: false, - userChatList: true, + userChatList: statusList.userChatList ? false : true, }) break; case '共享屏幕': @@ -606,75 +607,73 @@ const Meeting: React.FC = () => {
{roomUserList.map((item: any, index: number) => { return ( - <> - {item.isShow ?
-
-
- - {item.userName} - {item.roleId === '1' || item.isManager ? - - {item.roleId === '1' ? '主持人' : '临时主持人'} - - : null} - -
-
- - -
- {item.account !== user.account && user.roleId === '1' ?
- {!item.isManager ? : } + item.isShow ?
+
+
+ + {item.userName} + {item.roleId === '1' || item.isManager ? + + {item.roleId === '1' ? '主持人' : '临时主持人'} + + : null} + +
+
+ + +
+ {item.account !== user.account && user.roleId === '1' ?
+ {!item.isManager ? : } - -
: null} +
: null} - +
: null ) } )} @@ -701,7 +700,7 @@ const Meeting: React.FC = () => { key={index} className={`${item.uid !== state.uid ? styles.meetingUserChatContentLeft : styles.meetingUserChatContentRight} drag`}>
-
+
{item.userName}
{item.message}
diff --git a/src/utils/request/request.ts b/src/utils/request/request.ts index bd981b5..67886b4 100644 --- a/src/utils/request/request.ts +++ b/src/utils/request/request.ts @@ -68,6 +68,11 @@ class Request { if (res.code == 200) { storage.setItem('user', JSON.stringify(res.data)) location.reload() + } else { + setTimeout(() => { + storage.removeItem('user') + location.href = location.origin + '/#/login' + }, 3000) } }) } else { diff --git a/src/utils/styles/App.scss b/src/utils/styles/App.scss index 56060ed..7b95595 100644 --- a/src/utils/styles/App.scss +++ b/src/utils/styles/App.scss @@ -40,6 +40,10 @@ $pagination-hover-background-color: #5575F2; } } +.ant-input-data-count { + color: white !important; +} + .ant-input-affix-wrapper { background-color: $input-background-color !important; border: 1px solid $input-border-color; @@ -208,6 +212,9 @@ $pagination-hover-background-color: #5575F2; color: black !important; } } + .ant-pagination-item-ellipsis{ + color: white !important; + } } // popover