From 352161ac96b41f1ec3b6c08f14f6c71d43dc59ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8D=E5=81=9A=E7=A0=81=E5=86=9C?= <599854767@qq.com> Date: Sun, 27 Aug 2023 20:54:30 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=E6=96=B0=E5=A2=9E=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E6=97=B6=E9=95=BF=E3=80=81=E5=8D=95=E7=82=B9=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 6 +- src/assets/styles/login.scss | 2 - src/main.js | 2 +- src/signalr/analysis.js | 89 ++++++++++++++++++++++++++ src/signalr/signalr.js | 76 ++++++++++++++++++++++ src/store/modules/socket.js | 28 +++++--- src/utils/signalR.js | 43 +++++++++---- src/views/index_v1.vue | 37 +++++++++-- src/views/login.vue | 3 +- src/views/monitor/onlineuser/index.vue | 38 +++++++---- 10 files changed, 281 insertions(+), 43 deletions(-) create mode 100644 src/signalr/analysis.js create mode 100644 src/signalr/signalr.js diff --git a/src/App.vue b/src/App.vue index 5609df6..17b3fdb 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,7 +28,11 @@ watch( token, (val) => { if (val) { - proxy.signalr.start() + proxy.signalr.start().then(async (res) => { + if (res) { + await proxy.signalr.SR.invoke('logOut') + } + }) } }, { diff --git a/src/assets/styles/login.scss b/src/assets/styles/login.scss index 1125948..0976eda 100644 --- a/src/assets/styles/login.scss +++ b/src/assets/styles/login.scss @@ -109,11 +109,9 @@ } .login-scan-container { - padding: 0 20px 20px; display: flex; flex-direction: column; text-align: center; align-items: center; - height: 200px; justify-content: space-around; } diff --git a/src/main.js b/src/main.js index ca1a1ce..138aa50 100644 --- a/src/main.js +++ b/src/main.js @@ -11,7 +11,7 @@ import directive from './directive' // directive // 注册指令 import plugins from './plugins' // plugins import { downFile } from '@/utils/request' -import signalR from '@/utils/signalR' +import signalR from '@/signalr/signalr' import vueI18n from './i18n/index' import pinia from '@/store/index' diff --git a/src/signalr/analysis.js b/src/signalr/analysis.js new file mode 100644 index 0000000..f293fbf --- /dev/null +++ b/src/signalr/analysis.js @@ -0,0 +1,89 @@ +// import signalr from './signalr' +import { ElNotification, ElMessage, ElMessageBox } from 'element-plus' +import useSocketStore from '@/store/modules/socket' +import useUserStore from '@/store/modules/user' +import { webNotify } from '@/utils/index' + +export default { + onMessage(connection) { + connection.on(MsgType.M001, (data) => { + useSocketStore().setOnlineUsers(data) + }) + + connection.on(MsgType.M002, (data) => { + // useUserStore().saveConnId(data) + }) + // 接收后台手动推送消息 + connection.on('receiveNotice', (title, data) => { + ElNotification({ + type: 'info', + title: title, + message: data, + dangerouslyUseHTMLString: true, + duration: 0 + }) + webNotify({ title: title, body: data }) + }) + // 接收系统通知/公告 + connection.on('moreNotice', (data) => { + if (data.code == 200) { + useSocketStore().setNoticeList(data.data) + } + }) + + // 接收在线用户 + // connection.on('onlineUser', (data) => { + // useSocketStore().setOnlineUsers(data) + // }) + + // 接收封锁通知 + connection.on('lockUser', (data) => { + ElMessageBox.alert(`你的账号已被锁定,剩余,${data.time}分,原因:${data.reason || '-'}`, '提示', { + confirmButtonText: '确定', + callback: () => { + useUserStore() + .logOut() + .then(() => { + location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + 'index' + }) + } + }) + }) + // 接收聊天数据 + connection.on('receiveChat', (data) => { + const title = `来自${data.userName}的消息通知` + useSocketStore().setChat(data) + + if (data.userid != useUserStore().userId) { + ElNotification({ + title: title, + message: data.message, + type: 'success', + duration: 3000 + }) + } + webNotify({ title: title, body: data.message }) + }) + + connection.on('onlineInfo', (data) => { + useSocketStore().getOnlineInfo(data) + }) + + connection.on('logOut', () => { + useUserStore() + .logOut() + .then(() => { + ElMessageBox.alert(`你的账号已在其他设备登录,如果不是你的操作请尽快修改密码`, '提示', { + confirmButtonText: '确定', + callback: () => { + location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + 'index' + } + }) + }) + }) + } +} +const MsgType = { + M001: 'onlineNum', + M002: 'connId' +} diff --git a/src/signalr/signalr.js b/src/signalr/signalr.js new file mode 100644 index 0000000..bec87ad --- /dev/null +++ b/src/signalr/signalr.js @@ -0,0 +1,76 @@ +// 官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-2.2&tabs=visual-studio +import * as signalR from '@microsoft/signalr' +import { getToken } from '@/utils/auth' +import { ElMessage } from 'element-plus' + +import analysis from '@/signalr/analysis' + +export default { + // signalR对象 + SR: {}, + // 失败连接重试次数 + failNum: 4, + init(url) { + var socketUrl = window.location.origin + url + const connection = new signalR.HubConnectionBuilder() + .withUrl(socketUrl, { accessTokenFactory: () => getToken() }) + .withAutomaticReconnect() //自动重新连接 + .configureLogging(signalR.LogLevel.Warning) + .build() + this.SR = connection + // 断线重连 + connection.onclose(async (error) => { + console.error('断开连接了' + error) + console.assert(connection.state === signalR.HubConnectionState.Disconnected) + // 建议用户重新刷新浏览器 + await this.start() + }) + + connection.onreconnected((connectionId) => { + ElMessage({ + message: '与服务器通讯已连接成功', + type: 'success', + duration: 2000 + }) + console.log('断线重新连接成功' + connectionId) + }) + + connection.onreconnecting(async () => { + console.log('断线重新连接中... ') + + await this.start() + }) + analysis.onMessage(connection) + // this.receiveMsg(connection) + // 启动 + // this.start(); + }, + /** + * 调用 this.signalR.start().then(async () => { await this.SR.invoke("method")}) + * @returns + */ + async start() { + try { + console.log('signalR-1', this.SR.state) + //使用async和await 或 promise的then 和catch 处理来自服务端的异常 + if (this.SR.state === signalR.HubConnectionState.Disconnected) { + await this.SR.start() + } + + console.log('signalR-2', this.SR.state) + return true + } catch (error) { + console.error(error) + this.failNum-- + // console.log(`失败重试剩余次数${that.failNum}`, error) + if (this.failNum > 0 && this.SR.state.Disconnected) { + setTimeout(async () => { + await this.start() + }, 5000) + } + return false + } + }, + // 接收消息处理 + receiveMsg(connection) {} +} diff --git a/src/store/modules/socket.js b/src/store/modules/socket.js index 998e9d0..60802a2 100644 --- a/src/store/modules/socket.js +++ b/src/store/modules/socket.js @@ -3,7 +3,12 @@ const useSocketStore = defineStore('socket', { onlineNum: 0, onlineUsers: [], noticeList: [], - noticeDot: false + noticeDot: false, + //在线用户信息 + onlineInfo: {}, + // 聊天数据 + chatList: [], + leaveUser: {} }), actions: { //更新在线人数 @@ -15,14 +20,19 @@ const useSocketStore = defineStore('socket', { this.noticeList = data this.noticeDot = data.length > 0 }, - // setOnlineUsers(data) { - // const { onlineNum, users } = data - // this.onlineUsers = users - // this.onlineNum = onlineNum - // }, - sendChat(data) { - const { proxy } = getCurrentInstance() - console.log(data) + setOnlineUsers(data) { + const { onlineClients, num, leaveUser } = data + this.onlineUsers = onlineClients + this.onlineNum = num + if (leaveUser != null) { + this.leaveUser = leaveUser + } + }, + getOnlineInfo(data) { + this.onlineInfo = data + }, + setChat(data) { + this.chatList.push(data) } } }) diff --git a/src/utils/signalR.js b/src/utils/signalR.js index cb19aa1..da13ad5 100644 --- a/src/utils/signalR.js +++ b/src/utils/signalR.js @@ -19,20 +19,20 @@ export default { .build() this.SR = connection // 断线重连 - connection.onclose(async () => { - console.log('断开连接了') + connection.onclose(async (error) => { + console.error('断开连接了' + error) console.assert(connection.state === signalR.HubConnectionState.Disconnected) // 建议用户重新刷新浏览器 await this.start() }) - connection.onreconnected(() => { + connection.onreconnected((connectionId) => { ElMessage({ message: '与服务器通讯已连接成功', type: 'success', duration: 2000 }) - console.log('断线重新连接成功') + console.log('断线重新连接成功' + connectionId) }) connection.onreconnecting(async () => { @@ -74,7 +74,7 @@ export default { // 接收消息处理 receiveMsg(connection) { connection.on('onlineNum', (data) => { - useSocketStore().setOnlineUserNum(data) + useSocketStore().setOnlineUsers(data) }) // 接收欢迎语 connection.on('welcome', (data) => { @@ -125,14 +125,35 @@ export default { // 接收聊天数据 connection.on('receiveChat', (data) => { const title = `来自${data.userName}的消息通知` - ElNotification({ - title: title, - message: data.message, - type: 'success', - duration: 0 - }) + useSocketStore().setChat(data) + if (data.userid != useUserStore().userId) { + ElNotification({ + title: title, + message: data.message, + type: 'success', + duration: 3000 + }) + } webNotify({ title: title, body: data.message }) }) + + connection.on('onlineInfo', (data) => { + console.log('onlineInfo', data) + useSocketStore().getOnlineInfo(data) + }) + + connection.on('logOut', () => { + useUserStore() + .logOut() + .then(() => { + ElMessageBox.alert(`你的账号已在其他设备登录,如果不是你的操作请尽快修改密码`, '提示', { + confirmButtonText: '确定', + callback: () => { + location.href = import.meta.env.VITE_APP_ROUTER_PREFIX + 'index' + } + }) + }) + }) } } diff --git a/src/views/index_v1.vue b/src/views/index_v1.vue index 443c3d9..dd8aa6a 100644 --- a/src/views/index_v1.vue +++ b/src/views/index_v1.vue @@ -2,7 +2,7 @@
- +
@@ -12,7 +12,10 @@
- {{ userInfo.welcomeMessage }} {{ userInfo.nickName }} {{ userInfo.welcomeContent }} +
+ {{ userInfo.welcomeMessage }} {{ userInfo.nickName }} + ({{ userInfo.welcomeContent }}) +
@@ -24,10 +27,19 @@
- +
{{ currentTime }} {{ weekName }}
-
上次登录时间:{{ userInfo.loginDate }}
+
+
+
今日工作时长
+
{{ onlineInfo.onlineTime }}分
+
+
+
在线设备数
+
{{ onlineInfo.clientNum }}
+
+
@@ -94,6 +106,7 @@ import BarChart from './dashboard/BarChart' import CommonMenu from './components/CommonMenu' import useUserStore from '@/store/modules/user' +import useSocketStore from '@/store/modules/socket' import { getWeek } from '@/utils/ruoyi' const showEdit = ref(false) const data = { @@ -118,6 +131,9 @@ const { proxy } = getCurrentInstance() const userInfo = computed(() => { return useUserStore().userInfo }) +const onlineInfo = computed(() => { + return useSocketStore().onlineInfo +}) const currentTime = computed(() => { return proxy.parseTime(new Date(), 'YYYY-MM-DD') }) @@ -165,6 +181,19 @@ function handleAdd() { height: 200px; // overflow-y: scroll; } + + .work-wrap { + display: grid; + grid-template-columns: repeat(2, 50%); + + .item { + text-align: center; + + .name { + color: #606666; + } + } + } } .chart-wrapper { background: var(--base-bg-main); diff --git a/src/views/login.vue b/src/views/login.vue index 4883805..159a2b1 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -31,7 +31,7 @@ @@ -59,6 +59,7 @@
diff --git a/src/views/monitor/onlineuser/index.vue b/src/views/monitor/onlineuser/index.vue index bef028d..2614400 100644 --- a/src/views/monitor/onlineuser/index.vue +++ b/src/views/monitor/onlineuser/index.vue @@ -3,11 +3,10 @@ 刷新 - - +