Files
windows_lock_vue/src/layout/index.vue
2025-07-18 18:07:44 +08:00

225 lines
6.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div :class="classObj" class="app-wrapper" :style="{ '--current-color': $store.state.settings.theme }">
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container"
:style="{ backgroundColor: $store.state.settings.themeStyle === 'dark' ? variables.menuBg : variables.menuLightBg }" />
<div :class="{ hasTagsView: needTagsView }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<navbar />
<tags-view v-if="needTagsView" />
</div>
<app-main />
<right-panel v-if="showSettings">
<settings />
</right-panel>
</div>
<!-- 绑定谷歌验证码弹窗 -->
<set-google-secret :visible.sync="showSetGooleSecret" :otpAuthUrl="needGoolAuthData.otpAuthUrl"
:secret="needGoolAuthData.secret" @success="handleBindSuccess"></set-google-secret>
</div>
</template>
<script>
import RightPanel from '@/components/RightPanel'
import { needGoolAuth, setGoogleAuth } from '@/api/admin/sys-user'
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
import SetGoogleSecret from './SetGoogleSecret'
import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'
import variables from '@/styles/variables.scss'
// import dingSound from '@/assets/tiktok/sisfus.mp3'
import checkPermisAction from '@/utils/permisaction'
export default {
name: 'Layout',
components: {
AppMain,
Navbar,
RightPanel,
Settings,
Sidebar,
TagsView,
SetGoogleSecret
},
data() {
return {
voice: null,
showSetGooleSecret: false,
needGoolAuthData: {}
}
},
mixins: [ResizeMixin],
computed: {
...mapState({
sidebar: state => state.app.sidebar,
device: state => state.app.device,
showSettings: state => state.settings.showSettings,
needTagsView: state => state.settings.tagsView,
fixedHeader: state => state.settings.fixedHeader
}),
classObj() {
return {
hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile'
}
},
variables() {
return variables
}
},
created() {
this.getNeedGoolAuth()
if (checkPermisAction(['admin:mmAlarmLog:notice'])) {
// this.$confirm('是否接收警告?', '提示', {
// distinguishCancelAndClose: true,
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// this.voice = new Audio(dingSound)
this.initWebSocket()
// }).catch(() => {
// console.log('取消')
// });
}
},
destroyed() {
console.log('断开websocket连接')
this.websock.close() // 离开路由之后断开websocket连接
},
methods: {
checkPermisAction,
getNeedGoolAuth() {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
needGoolAuth()
.then(response => {
console.log("needGoogleAuth", response)
if (response.code === 200) {
if (response.data.needGooglAuth) {
this.needGoolAuthData.otpAuthUrl = response.data.otpAuthUrl
this.needGoolAuthData.secret = response.data.secret
this.showSetGooleSecret = true
}
}
})
.finally(() => {
loading.close()
})
},
initWebSocket() { // 初始化weosocket
const wsuri = `ws://${process.env.VUE_APP_WEBSOCKET_URL}/ws?token=${this.$store.state.user.token}`
this.websock = new WebSocket(wsuri)
this.websock.onmessage = this.websocketonmessage
this.websock.onopen = this.websocketonopen
this.websock.onerror = this.websocketonerror
this.websock.onclose = this.websocketclose
},
websocketonopen() { // 连接建立之后执行send方法发送数据
console.log('ws连接打开')
// const actions = { 'test': '12345' }
// this.websocketsend(JSON.stringify(actions))
},
websocketonerror() { // 连接建立失败重连
this.initWebSocket()
},
websocketonmessage(e) { // 数据接收
try {
let data = JSON.parse(e.data)
this.$notify({
title: '钱包警告',
dangerouslyUseHTMLString: true,
message: `<p>设备id${data.machineId}</p><p>设备码:${data.biosId}</p><p style="text-align:left;">内容:${data.content}</p>`,
type: 'warning',
duration: 0
});
// this.playVoice("钱包告警")
} catch (err) {
console.log("接收websocket数据失败:", err)
}
},
playVoice(text) {
this.voice.play().catch(err => {
console.error('音频播放失败:', err)
})
},
websocketsend(Data) { // 数据发送
// this.websock.send(Data)
},
websocketclose(e) { // 关闭
// unWsLogout(this.id, this.group).then(response => {
// console.log(response.data)
// }
// )
// console.log('断开连接', e)
},
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
},
handleBindSuccess() {
this.showSetGooleSecret = false
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
&.mobile.openSidebar {
position: fixed;
top: 0;
}
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.hideSidebar .fixed-header {
width: calc(100% - 54px)
}
.mobile .fixed-header {
width: 100%;
}
</style>