|
|
@@ -8,19 +8,35 @@
|
|
|
'--current-color-dark-bg': theme + '33',
|
|
|
}"
|
|
|
>
|
|
|
- <!-- 顶部一级菜单栏 -->
|
|
|
- <top-navbar
|
|
|
- v-if="!sidebar.hide"
|
|
|
- :active-menu="activeTopMenu"
|
|
|
- @menu-click="handleTopMenuClick"
|
|
|
- @setLayout="openSettings"
|
|
|
- />
|
|
|
+ <!-- 顶部栏(系统名 + 用户信息) -->
|
|
|
+ <div class="top-bar">
|
|
|
+ <div class="logo-area">
|
|
|
+ <span class="logo-text" style="cursor:pointer" @click="router.push('/index')">水利安全生产监管信息系统</span>
|
|
|
+ </div>
|
|
|
+ <div class="top-right-menu">
|
|
|
+ <el-dropdown @command="handleCommand" class="avatar-container" trigger="hover">
|
|
|
+ <div class="avatar-wrapper">
|
|
|
+ <svg-icon icon-class="user" class="user-icon" />
|
|
|
+ <span class="user-nickname">{{ userStore.nickName || userStore.name }}</span>
|
|
|
+ <el-icon class="dropdown-icon"><ArrowDown /></el-icon>
|
|
|
+ </div>
|
|
|
+ <template #dropdown>
|
|
|
+ <el-dropdown-menu>
|
|
|
+ <router-link to="/user/profile">
|
|
|
+ <el-dropdown-item>个人中心</el-dropdown-item>
|
|
|
+ </router-link>
|
|
|
+ <el-dropdown-item divided command="logout">退出登录</el-dropdown-item>
|
|
|
+ </el-dropdown-menu>
|
|
|
+ </template>
|
|
|
+ </el-dropdown>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
<!-- 下方区域:左右结构 -->
|
|
|
<div class="main-layout">
|
|
|
<!-- 左侧二三级菜单 -->
|
|
|
<div class="sidebar-wrapper" :class="{ collapsed: isCollapse }">
|
|
|
- <sidebar v-if="!sidebar.hide" :top-menu-key="activeTopMenu" />
|
|
|
+ <sidebar v-if="!sidebar.hide" />
|
|
|
</div>
|
|
|
|
|
|
<!-- 右侧内容区域 -->
|
|
|
@@ -33,108 +49,112 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { computed, ref, watch, onMounted } from "vue";
|
|
|
-import { useRoute, useRouter } from "vue-router";
|
|
|
-import TopNavbar from "./components/TopNavbar/index.vue";
|
|
|
+import { computed, ref } from "vue";
|
|
|
+import { useRouter } from "vue-router";
|
|
|
+import { ElMessageBox } from "element-plus";
|
|
|
+import { ArrowDown } from "@element-plus/icons-vue";
|
|
|
import Sidebar from "./components/Sidebar/index.vue";
|
|
|
import { AppMain, Settings } from "./components";
|
|
|
import useAppStore from "@/store/modules/app";
|
|
|
import useSettingsStore from "@/store/modules/settings";
|
|
|
-import usePermissionStore from "@/store/modules/permission";
|
|
|
+import useUserStore from "@/store/modules/user";
|
|
|
|
|
|
const settingsStore = useSettingsStore();
|
|
|
-const permissionStore = usePermissionStore();
|
|
|
const appStore = useAppStore();
|
|
|
-const route = useRoute();
|
|
|
+const userStore = useUserStore();
|
|
|
const router = useRouter();
|
|
|
|
|
|
-// 首页路径
|
|
|
-const HOME_PATH = "/index";
|
|
|
-
|
|
|
-// 计算属性
|
|
|
const theme = computed(() => settingsStore.theme);
|
|
|
const sidebar = computed(() => appStore.sidebar);
|
|
|
const isCollapse = computed(() => appStore.sidebar.isCollapse);
|
|
|
|
|
|
-// 当前选中的顶级菜单
|
|
|
-const activeTopMenu = ref("");
|
|
|
-
|
|
|
-// 获取当前选中的顶级菜单
|
|
|
-const getCurrentTopMenu = () => {
|
|
|
- const currentPath = route.path;
|
|
|
+const settingRef = ref(null);
|
|
|
|
|
|
- // 如果是首页,选中首页菜单
|
|
|
- if (currentPath === HOME_PATH) {
|
|
|
- return HOME_PATH;
|
|
|
+function handleCommand(command) {
|
|
|
+ switch (command) {
|
|
|
+ case "logout":
|
|
|
+ ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ }).then(() => {
|
|
|
+ userStore.logOut().then(() => {
|
|
|
+ location.href = "/index";
|
|
|
+ });
|
|
|
+ }).catch(() => {});
|
|
|
+ break;
|
|
|
}
|
|
|
+}
|
|
|
+</script>
|
|
|
|
|
|
- try {
|
|
|
- const routes = permissionStore.topbarRouters || [];
|
|
|
- const firstLevel = "/" + currentPath.split("/")[1];
|
|
|
- const matched = routes.find((r) => r.path === firstLevel);
|
|
|
- return matched?.path || HOME_PATH;
|
|
|
- } catch (error) {
|
|
|
- return HOME_PATH;
|
|
|
- }
|
|
|
-};
|
|
|
+<style scoped>
|
|
|
+.app-wrapper {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
|
|
|
-// 处理顶级菜单点击
|
|
|
-function handleTopMenuClick(menuPath) {
|
|
|
- activeTopMenu.value = menuPath;
|
|
|
+.top-bar {
|
|
|
+ height: 60px;
|
|
|
+ background: #217ff4;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 0 30px;
|
|
|
+ box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
|
|
|
- // 如果点击的是首页,直接跳转
|
|
|
- if (menuPath === HOME_PATH) {
|
|
|
- router.push(HOME_PATH);
|
|
|
- return;
|
|
|
- }
|
|
|
+.logo-text {
|
|
|
+ color: #fff;
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
|
|
|
- // 其他菜单:跳转到第一个子路由
|
|
|
- const routes = permissionStore.topbarRouters || [];
|
|
|
- const targetRoute = routes.find((r) => r.path === menuPath);
|
|
|
-
|
|
|
- if (targetRoute && targetRoute.children && targetRoute.children.length > 0) {
|
|
|
- const firstChild = targetRoute.children.find((child) => !child.hidden);
|
|
|
- if (firstChild) {
|
|
|
- let fullPath = firstChild.path;
|
|
|
- if (!fullPath.startsWith("/")) {
|
|
|
- fullPath = menuPath + "/" + fullPath;
|
|
|
- }
|
|
|
- router.push(fullPath);
|
|
|
- }
|
|
|
- }
|
|
|
+.top-right-menu {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
|
|
|
-// 打开设置面板
|
|
|
-const settingRef = ref(null);
|
|
|
-function openSettings() {
|
|
|
- if (settingRef.value) {
|
|
|
- settingRef.value.openSetting();
|
|
|
- }
|
|
|
+.avatar-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 0 12px;
|
|
|
+ height: 60px;
|
|
|
+ max-width: 200px;
|
|
|
}
|
|
|
|
|
|
-// 监听路由变化,更新选中的顶级菜单
|
|
|
-watch(
|
|
|
- () => route.path,
|
|
|
- () => {
|
|
|
- activeTopMenu.value = getCurrentTopMenu();
|
|
|
- },
|
|
|
- { immediate: true },
|
|
|
-);
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- // 如果当前是根路径,跳转到首页
|
|
|
- if (route.path === "/") {
|
|
|
- router.push(HOME_PATH);
|
|
|
- }
|
|
|
- activeTopMenu.value = getCurrentTopMenu();
|
|
|
-});
|
|
|
-</script>
|
|
|
+.avatar-wrapper:hover {
|
|
|
+ background: rgba(255, 255, 255, 0.15);
|
|
|
+}
|
|
|
|
|
|
-<style scoped>
|
|
|
-.app-wrapper {
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
+.user-icon {
|
|
|
+ width: 18px;
|
|
|
+ height: 18px;
|
|
|
+ color: #fff;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.user-nickname {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #fff;
|
|
|
+ max-width: 120px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ flex-shrink: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.dropdown-icon {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #fff;
|
|
|
+ transition: transform 0.3s;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-wrapper:hover .dropdown-icon {
|
|
|
+ transform: rotate(180deg);
|
|
|
}
|
|
|
|
|
|
.main-layout {
|