服务端开发模式-vue-element-admin重新整理websocket

embedded/2025/1/19 11:26:16/

一、App.vue修改

<template><div id="app"><router-view /></div>
</template><script>import store from './store'import {succ} from '@/utils/message'
export default {name: 'App',data() {return {reverseCount:0,}},created() {// 因为我的页面有缓存机制,用户下次有可能直接打开某个登录后才能访问的页面 比如F5刷新了某个页面 需要重连// 又比如后端服务器因为什么原因突然中断了一下 也需要重新连接WebSocket// 每3秒检测一次websocket连接状态 未连接 则尝试连接 尽量保证网站启动的时候 WebSocket都能正常长连接setInterval(this.WebSocket_StatusCheck, 2000)},methods: {// 1、WebSocket连接状态检测:WebSocket_StatusCheck() {//如果登录了情况下,验证是否已经绑定if(store.getters.token != undefined || store.getters.token != null){if (!this.$WebSocket.WebSocketHandle || this.$WebSocket.WebSocketHandle.readyState !== 1) {this.reverseCount++;this.WebSocketINI()}else{this.reverseCount = 0;this.$WebSocket.WebSocketHandle.send(JSON.stringify({type: 'ping'}))}}},// 2、WebSocket初始化:async WebSocketINI() {// 1、浏览器是否支持WebSocket检测if (!('WebSocket' in window)) {return}// 2、从后台提取WebScoket服务器连接地址:根据自己业务接口获取 或者直接跳过 下面直接写死var Base64 = require('js-base64').Base64const tokenData = Base64.decode(store.getters.token).split("|");const token = tokenData[0]const loginTime = new Date(tokenData[1]).getTime() / 1000const tmpWebsocketSrverAddress = 'ws://www.baidu.com?extremity_type=1&token='+ token + '&login_time=' +loginTime//可以直接赋值如:ws://127.0.0.1:1234// 3、创建Websocket连接const tmpWebsocket = new WebSocket(tmpWebsocketSrverAddress)// 4、全局保存WebSocket操作句柄:main.js 全局引用this.$WebSocket.WebsocketINI(tmpWebsocket)// 5、WebSocket连接成功提示tmpWebsocket.onopen = function(ev){}tmpWebsocket.onmessage = function(ev){const datas = JSON.parse(ev.data)switch (datas.type) {// 异地登录case "repeat_close":store.dispatch('user/resetToken',{type:"repeat"})// 延时setTimeout(() => {window.location.reload()}, 1000)break// 正常退出case "artificial_close":store.dispatch('user/resetToken',{type:"artificial"})// 延时setTimeout(() => {window.location.reload()}, 1000)breakcase "expire_close":store.dispatch('user/resetToken',{type:"expire"})// 延时setTimeout(() => {window.location.reload()}, 1000)breakdefault:}}//6、连接失败提示tmpWebsocket.onclose = (ev)=> {if(this.reverseCount >= 5){store.dispatch('user/logout')store.dispatch('user/resetToken',{type:"close"})window.location.reload()}}}}
}
</script>

二、Navbar.vue

<template><div class="navbar"><hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /><breadcrumb id="breadcrumb-container" class="breadcrumb-container" /><div class="right-menu"><template v-if="device!=='mobile'"><search id="header-search" class="right-menu-item" /><error-log class="errLog-container right-menu-item hover-effect" /><screenfull id="screenfull" class="right-menu-item hover-effect" /><el-tooltip content="Global Size" effect="dark" placement="bottom"><size-select id="size-select" class="right-menu-item hover-effect" /></el-tooltip></template><el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"><div class="avatar-wrapper"><span>欢迎<b style="color:red;">{{username}}</b>使用后台</span><i class="el-icon-caret-bottom" /></div><el-dropdown-menu slot="dropdown"><router-link to="/profile/index"><el-dropdown-item>个人信息</el-dropdown-item></router-link><el-dropdown-item divided @click.native="logout"><span style="display:block;">退出</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div></div>
</template><script>
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
import ErrorLog from '@/components/ErrorLog'
import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch'export default {components: {Breadcrumb,Hamburger,ErrorLog,Screenfull,SizeSelect,Search},computed: {...mapGetters(['sidebar','username','device'])},methods: {toggleSideBar() {this.$store.dispatch('app/toggleSideBar')},async logout() {await this.$store.dispatch('user/logout')//this.$router.push(`/login?redirect=${this.$route.fullPath}`)}}
}
</script><style lang="scss" scoped>
.navbar {height: 50px;overflow: hidden;position: relative;background: #fff;box-shadow: 0 1px 4px rgba(0,21,41,.08);.hamburger-container {line-height: 46px;height: 100%;float: left;cursor: pointer;transition: background .3s;-webkit-tap-highlight-color:transparent;&:hover {background: rgba(0, 0, 0, .025)}}.breadcrumb-container {float: left;}.errLog-container {display: inline-block;vertical-align: top;}.right-menu {float: right;height: 100%;line-height: 50px;&:focus {outline: none;}.right-menu-item {display: inline-block;padding: 0 8px;height: 100%;font-size: 18px;color: #5a5e66;vertical-align: text-bottom;&.hover-effect {cursor: pointer;transition: background .3s;&:hover {background: rgba(0, 0, 0, .025)}}}.avatar-container {margin-right: 30px;.avatar-wrapper {margin-top: 5px;position: relative;.user-avatar {cursor: pointer;width: 40px;height: 40px;border-radius: 10px;}.el-icon-caret-bottom {cursor: pointer;position: absolute;right: -20px;top: 20px;font-size: 12px;}}}}
}
</style>

三、user.js

import {getInfo, login, logout, repeatInfo} from '@/api/common'
import {getToken, removeToken, setToken} from '@/utils/auth'
import router, {resetRouter} from '@/router'
import moment from 'moment'
import {succ, warn, err} from '@/utils/message'
import Encrypt from 'encryptlong' // encryptlong是基于jsencrypt扩展的长文本分段加解密功能。const state = {token: getToken(),username: '',avatar: '',email: '',realname: '',department_title: '',grade_title: '',rolename: '',roles: [],butts: []
}const mutations = {SET_TOKEN: (state, token) => {state.token = token},SET_EMAIL: (state, email) => {state.email = email},SET_USERNAME: (state, username) => {state.username = username},SET_AVATAR: (state, avatar) => {state.avatar = avatar},SET_REALNAME: (state, realname) => {state.realname = realname},SET_DEPARTMENT_TITLE: (state, department_title) => {state.department_title = department_title},SET_GRADE_TITLE: (state, grade_title) => {state.grade_title = grade_title},SET_ROLENAME: (state, rolename) => {state.rolename = rolename},SET_BUTTS: (state, butts) => {state.butts = butts},SET_ROLES: (state, roles) => {state.roles = roles}
}
// 私钥Key
const privateKey = ''
const actions = {// user loginlogin({commit}, userInfo) {const {username, password, captcha_code} = userInfoconst login_time = moment().format('YYYY-MM-DD hh:mm:ss')return new Promise((resolve, reject) => {login({username: username.trim(),password: password.trim(),captcha_code: captcha_code.trim(),login_time: login_time.trim()}).then(response => {if (response.code === 50034) {reject(response.message)} else if (response.code === 50000) {warn(response.message)} else {succ(response.message)const PRIVATE_KEY = privateKeyvar encryptor = new Encrypt()encryptor.setPrivateKey(PRIVATE_KEY)// 如果是对象/数组的话,需要先JSON.stringify转换成字符串var result = encryptor.decryptLong(response.data)// 引用加密var Base64 = require('js-base64').Base64// base64加密var tokenBase64 = Base64.encode(result + '|' + login_time.trim())commit('SET_TOKEN', tokenBase64)setToken(tokenBase64)resolve()}}).catch(error => {reject(error)})})},// get user infogetInfo({commit, state}) {return new Promise((resolve, reject) => {getInfo().then(response => {const {data} = responseif (!data) {reject('验证失败,请重新登录。')}const {butt, key, username, avatar, email, realname, department_title, grade_title, rolename} = dataif (!butt || butt.length <= 0) {reject('您权限不足,请联系系统管理员')}commit('SET_BUTTS', butt)commit('SET_ROLES', key)commit('SET_USERNAME', username)commit('SET_AVATAR', avatar)commit('SET_EMAIL', email)commit('SET_REALNAME', realname)commit('SET_DEPARTMENT_TITLE', department_title)commit('SET_GRADE_TITLE', grade_title)commit('SET_ROLENAME', rolename)resolve(key)}).catch(error => {reject(error)})})},// 处理重复登录repeatInfo({commit, state, dispatch}) {return new Promise((resolve, reject) => {succ('账号已在异地登录')commit('SET_TOKEN', '')commit('SET_BUTTS', [])commit('SET_ROLES', [])commit('SET_USERNAME', '')commit('SET_AVATAR', '')commit('SET_EMAIL', '')commit('SET_REALNAME', '')commit('SET_DEPARTMENT_TITLE', '')commit('SET_GRADE_TITLE', '')commit('SET_ROLENAME', '')removeToken()resetRouter()dispatch('tagsView/delAllViews', null, {root: true})resolve()})},// user logoutlogout({commit, state, dispatch}) {return new Promise((resolve, reject) => {logout().then(res => {}).catch(error => {reject(error)})})},// 意外需要重置本地tokenresetToken({commit},infoType) {return new Promise(resolve => {if(infoType.type == 'artificial'){succ('退出成功')}else if(infoType.type == 'expire'){warn('登录过期,自动退出')}else if(infoType.type == 'close'){err('服务断链,强制退出')}else if(infoType.type == 'repeat'){warn('账号已在异地登录')}commit('SET_TOKEN', '')commit('SET_BUTTS', [])commit('SET_ROLES', [])commit('SET_USERNAME', '')commit('SET_AVATAR', '')commit('SET_EMAIL', '')commit('SET_REALNAME', '')commit('SET_DEPARTMENT_TITLE', '')commit('SET_GRADE_TITLE', '')commit('SET_ROLENAME', '')removeToken()resetRouter()resolve()})},// 切换权限async changeRoles({commit, dispatch}, role) {const token = role + '-token'commit('SET_TOKEN', token)setToken(token)const {roles} = await dispatch('getInfo')resetRouter()const accessRoutes = await dispatch('permission/generateRoutes', roles, {root: true})router.addRoutes(accessRoutes)dispatch('tagsView/delAllViews', null, {root: true})}
}export default {namespaced: true,state,mutations,actions
}

http://www.ppmy.cn/embedded/155211.html

相关文章

AI编程工具使用技巧——通义灵码

活动介绍通义灵码1. 理解通义灵码的基本概念示例代码生成 2. 使用明确的描述示例代码生成 3. 巧妙使用注释示例代码生成 4. 注意迭代与反馈原始代码反馈后生成优化代码 5. 结合生成的代码进行调试示例测试代码 其他功能定期优化生成的代码合作与分享结合其他工具 总结 活动介绍…

endnote x9 如何将参考文献和文中的应用格式由annotated变为编码,例[1],[2]

在 EndNote X9 中&#xff0c;将参考文献和文中引用格式更改为编码形式&#xff08;如 [1], [2]&#xff09;需要以下步骤&#xff1a; 1. 选择合适的输出样式 打开 EndNote X9。点击菜单栏的 "Edit" > "Output Styles" > "Open Style Manage…

C# 获取PDF文档中的字体信息(字体名、大小、颜色、样式等

在设计和出版行业中&#xff0c;字体的选择和使用对最终作品的质量有着重要影响。然而&#xff0c;有时我们可能会遇到包含未知字体的PDF文件&#xff0c;这使得我们无法准确地复制或修改文档。获取PDF中的字体信息可以解决这个问题&#xff0c;让我们能够更好地处理这些文件。…

【React】静态组件动态组件

目录 静态组件动态组件创建一个构造函数(类)使用 class 实现组件**使用 function 实现类组件** 静态组件 函数组件是静态组件&#xff1a; 组件第一次渲染完毕后&#xff0c;无法基于内部的某些操作让组件更新「无法实现自更新」&#xff1b;但是&#xff0c;如果调用它的父组…

Tidb集群升级到8.5.0过程中服务器遇到的坑

TiDB 集群升级到8.5.0踩坑记&#xff1a;从 GLIBC_2.15 升级到 GLIBC_2.28YUM 仓库问题的全面解决 1. 引言 作为部门的负责人&#xff0c;我常常觉得自己是个“救火队员”。昨天 TiDB 集群又出问题了&#xff1a;查询卡顿、响应时间变长&#xff0c;重启之后问题依旧。临近下班…

Tesla Free - Fall attack:特斯拉汽车网络安全攻击事件分析

文章目录 一、Tesla Free - Fall attack&#xff1a;特斯拉汽车网络安全事件纪要1. 引言2. 攻击流程2.1 攻击切入点2.2 系统入侵2.3 CAN 总线操控 3. 影响后果4. 特斯拉应对措施5. 研究意义二、安全攻击事件技术分析以及相应的检测和缓解措施 一、Tesla Free - Fall attack&…

AI生成文档——Uni-App CSS 样式开发指南

Uni-App CSS 样式开发指南 目录 基础概念布局与盒模型Flexbox 布局Grid 布局常用样式属性响应式设计UI 样式示例微信小程序样式适配动画与过渡常见问题与解决方案性能优化工具与资源总结高级技巧实战案例社区与学习资源附录 基础概念 1.1 CSS 简介 CSS&#xff08;Cascadin…

你会选择java还是node做后台管理

目前后台开源千千万&#xff0c;但说好用且容易上手的也就那几个。 node和java就看你怎么选了 如果你擅长Java&#xff0c;那RuoYi首选 RuoYI后台管理系统https://gitee.com/y_project/RuoYi-Vue有vue2又有vue3。MIT协议全免费开源&#xff0c;功能齐全&#xff01; 如果你擅…