bonus-ui/src/layout/index.vue

292 lines
8.1 KiB
Vue
Raw Normal View History

2024-06-26 15:11:05 +08:00
<template>
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<sidebar v-if="!sidebar.hide" class="sidebar-container"/>
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
<div :class="{'fixed-header':fixedHeader}">
<navbar/>
<tags-view v-if="needTagsView"/>
</div>
<app-main/>
<right-panel>
<settings/>
</right-panel>
</div>
2024-09-08 20:13:32 +08:00
<el-dialog :title="title" :visible.sync="showChangePasswordDialog" width="30%" :close-on-click-modal="false"
:show-close="false"
>
<el-form ref="form" :model="user" :rules="rules" label-width="80px">
<el-form-item label="旧密码" prop="oldPassword">
<el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password/>
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password/>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password/>
</el-form-item>
<!-- <el-form-item>
<el-button type="primary" size="mini" @click="submit">保存</el-button>
<el-button type="danger" size="mini" @click="close">关闭</el-button>
</el-form-item>-->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submit"> </el-button>
<el-button @click="close"> </el-button>
</div>
</el-dialog>
2024-06-26 15:11:05 +08:00
</div>
</template>
<script>
import RightPanel from '@/components/RightPanel'
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'
import variables from '@/assets/styles/variables.scss'
2024-09-08 20:13:32 +08:00
import { validateNewPassword } from '@/utils/validate'
import { updateUserPwd, checkPasswordStatus } from '@/api/system/user'
2024-11-10 08:55:36 +08:00
import {MessageBox} from "element-ui";
2024-06-26 15:11:05 +08:00
export default {
name: 'Layout',
2024-09-08 20:13:32 +08:00
data() {
const equalToPassword = (rule, value, callback) => {
if (this.user.newPassword !== value) {
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
}
return {
showChangePasswordDialog: false, // 控制弹窗显示
title: '',
user: {
oldPassword: undefined,
newPassword: undefined,
confirmPassword: undefined
},
// 表单校验规则
rules: {
oldPassword: [
{ required: true, message: '旧密码不能为空', trigger: 'blur' }
],
newPassword: [
{ required: true, message: '新密码不能为空', trigger: 'blur' },
{ validator: validateNewPassword, trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '确认密码不能为空', trigger: 'blur' },
{ required: true, validator: equalToPassword, trigger: 'blur' }
]
2024-11-10 08:55:36 +08:00
},
socket: null,
wsUrl: 'ws://localhost:18082/ws', // WebSocket 端点
isConnected: false, // 连接状态
reconnectInterval: 5000 // 自动重连时间间隔(毫秒
2024-09-08 20:13:32 +08:00
}
},
2024-06-26 15:11:05 +08:00
components: {
AppMain,
Navbar,
RightPanel,
Settings,
Sidebar,
TagsView
},
mixins: [ResizeMixin],
computed: {
...mapState({
theme: state => state.settings.theme,
sideTheme: state => state.settings.sideTheme,
sidebar: state => state.app.sidebar,
device: state => state.app.device,
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() {
2024-09-08 20:13:32 +08:00
return variables
2024-06-26 15:11:05 +08:00
}
},
2024-09-08 20:13:32 +08:00
created() {
this.checkPasswordStatus()
2024-11-10 08:55:36 +08:00
this.connectWebSocket();
2024-09-08 20:13:32 +08:00
},
2024-06-26 15:11:05 +08:00
methods: {
2024-09-08 20:13:32 +08:00
checkPasswordStatus() {
checkPasswordStatus().then(response => {
if (response.code === 200) {
this.showChangePasswordDialog = response.data
this.title = response.msg
}
})
},
2024-06-26 15:11:05 +08:00
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
2024-09-08 20:13:32 +08:00
},
submit() {
this.$refs['form'].validate(valid => {
if (valid) {
updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => {
this.showChangePasswordDialog = false
this.$modal.msgSuccess('修改成功')
})
}
})
},
close() {
this.$store.dispatch('LogOut').then(() => {
location.href = '/index';
})
2024-11-10 08:55:36 +08:00
},
// 连接 WebSocket
connectWebSocket() {
if (this.socket) {
console.log("WebSocket 已连接");
return;
}
this.socket = new WebSocket(this.wsUrl);
// 监听 WebSocket 连接成功事件
this.socket.onopen = () => {
console.log("WebSocket 连接成功");
this.isConnected = true;
};
// 接收消息
this.socket.onmessage = (event) => {
console.log("收到消息:", event.data);
const warning = JSON.parse(event.data);
this.handleWarning(warning);
};
// 监听连接关闭事件
this.socket.onclose = () => {
console.log("WebSocket 连接已关闭");
this.isConnected = false;
this.socket = null;
// 自动重连
this.reconnectWebSocket();
};
// 监听连接错误事件
this.socket.onerror = (error) => {
console.error("WebSocket 错误:", error);
this.isConnected = false;
this.socket = null;
// 自动重连
this.reconnectWebSocket();
};
},
// 自动重连 WebSocket
reconnectWebSocket() {
console.log("尝试重新连接 WebSocket...");
setTimeout(() => {
this.connectWebSocket();
}, this.reconnectInterval);
},
// 处理告警信息并显示弹窗
handleWarning(warning) {
console.log(warning)
2024-11-11 09:49:34 +08:00
// const formattedTime = new Date(warning.warningTime).toLocaleString();
2024-11-10 08:55:36 +08:00
// 弹出告警信息
MessageBox.alert(
`
2024-11-11 09:49:34 +08:00
<p><strong>操作人</strong>${warning.operaUserName}</p>
2024-11-10 08:55:36 +08:00
<p><strong>事件</strong>${warning.warningEvent}</p>
<p><strong>IP</strong>${warning.warningIp}</p>
2024-11-11 09:49:34 +08:00
<p><strong>时间</strong>${warning.warningTime}</p>
2024-11-10 08:55:36 +08:00
`,
'告警通知',
{
dangerouslyUseHTMLString: true,
confirmButtonText: '确认',
callback: () => {
this.notifyBackend(warning.warningId);
}
}
);
},
// 通知后端告警已处理
notifyBackend(warningId) {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
const message = {
warningId,
};
2024-11-11 09:49:34 +08:00
this.socket.send(warningId);
2024-11-10 08:55:36 +08:00
console.log(`已通知后端处理告警: ${warningId}`);
}
2024-06-26 15:11:05 +08:00
}
2024-11-10 08:55:36 +08:00
},
beforeDestroy() {
// 页面销毁时关闭 WebSocket 连接
if (this.socket) {
this.socket.close();
}
2024-06-26 15:11:05 +08:00
}
}
</script>
<style lang="scss" scoped>
2024-09-08 20:13:32 +08:00
@import "~@/assets/styles/mixin.scss";
@import "~@/assets/styles/variables.scss";
2024-06-26 15:11:05 +08:00
2024-09-08 20:13:32 +08:00
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
2024-06-26 15:11:05 +08:00
2024-09-08 20:13:32 +08:00
&.mobile.openSidebar {
2024-06-26 15:11:05 +08:00
position: fixed;
top: 0;
}
2024-09-08 20:13:32 +08:00
}
2024-06-26 15:11:05 +08:00
2024-09-08 20:13:32 +08:00
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
2024-06-26 15:11:05 +08:00
2024-09-08 20:13:32 +08:00
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$base-sidebar-width});
transition: width 0.28s;
}
2024-06-26 15:11:05 +08:00
2024-09-08 20:13:32 +08:00
.hideSidebar .fixed-header {
width: calc(100% - 54px);
}
.sidebarHide .fixed-header {
width: 100%;
}
.mobile .fixed-header {
width: 100%;
}
2024-06-26 15:11:05 +08:00
</style>