批量更新
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-aside :width="width" class="common-aside">
|
||||
<el-aside :width="width" :class="['common-aside', { 'mobile-open': isMobile && !isCollapse }]">
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="loading" class="loading-spinner">
|
||||
<i class="el-icon-loading" style="font-size: 24px; color: #fff"></i>
|
||||
@@ -143,13 +143,19 @@
|
||||
</el-sub-menu>
|
||||
</template>
|
||||
</el-menu>
|
||||
|
||||
<div v-if="!loading && !hasError && !isCollapse" class="aside-toggle-bottom">
|
||||
<el-button class="aside-toggle-btn" size="small" @click="handleCollapse">
|
||||
<el-icon><Fold /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-aside>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted, watch } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { Document, Warning } from "@element-plus/icons-vue";
|
||||
import { Document, Warning, Fold } from "@element-plus/icons-vue";
|
||||
import { useAllDataStore, useMenuStore } from "@/stores";
|
||||
|
||||
const emit = defineEmits(["menu-click"]);
|
||||
@@ -163,7 +169,13 @@ const errorMsg = computed(() => menuStore.error || "加载菜单失败");
|
||||
|
||||
const store = useAllDataStore();
|
||||
const isCollapse = computed(() => store.state.isCollapse);
|
||||
const width = computed(() => (store.state.isCollapse ? "64px" : "200px"));
|
||||
const isMobile = ref(false);
|
||||
const width = computed(() => {
|
||||
if (isMobile.value) {
|
||||
return store.state.isCollapse ? "0px" : "220px";
|
||||
}
|
||||
return store.state.isCollapse ? "64px" : "200px";
|
||||
});
|
||||
|
||||
const asideBgColor = ref("#304156");
|
||||
const asideTextColor = ref("#bfcbd9");
|
||||
@@ -171,6 +183,13 @@ const activeColor = ref("#3973FF");
|
||||
const activeBgColor = ref("#3973FF");
|
||||
|
||||
const currentModuleId = ref(null);
|
||||
const updateDeviceType = () => {
|
||||
isMobile.value = window.innerWidth <= 768;
|
||||
// 手机端默认收起侧边栏
|
||||
if (isMobile.value) {
|
||||
store.state.isCollapse = true;
|
||||
}
|
||||
};
|
||||
|
||||
const findMenuItem = (menus, targetIndex) => {
|
||||
for (const menu of menus) {
|
||||
@@ -328,6 +347,9 @@ const handleMenuSelect = (index) => {
|
||||
const menuItem = findMenuItem(list.value, index);
|
||||
if (menuItem) {
|
||||
emit("menu-click", menuItem);
|
||||
if (isMobile.value) {
|
||||
store.state.isCollapse = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -337,6 +359,10 @@ const fetchMenus = async () => {
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const handleCollapse = () => {
|
||||
store.state.isCollapse = !store.state.isCollapse;
|
||||
};
|
||||
|
||||
const handleMenuRefresh = () => {
|
||||
fetchMenus();
|
||||
};
|
||||
@@ -350,6 +376,9 @@ watch(
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
updateDeviceType();
|
||||
window.addEventListener("resize", updateDeviceType);
|
||||
|
||||
if (!menuStore.menus || menuStore.menus.length === 0) {
|
||||
setTimeout(() => {
|
||||
fetchMenus();
|
||||
@@ -360,6 +389,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("resize", updateDeviceType);
|
||||
window.removeEventListener("menu-cache-refreshed", handleMenuRefresh);
|
||||
});
|
||||
</script>
|
||||
@@ -386,6 +416,10 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.common-aside.mobile-open {
|
||||
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.35), 2px 0 12px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -422,7 +456,7 @@ h3 {
|
||||
// 菜单样式
|
||||
:deep(.el-menu) {
|
||||
border-right: none;
|
||||
height: calc(100% - 80px);
|
||||
height: calc(100% - 128px);
|
||||
padding: 16px 8px;
|
||||
background: transparent;
|
||||
|
||||
@@ -519,14 +553,48 @@ h3 {
|
||||
}
|
||||
}
|
||||
|
||||
.aside-toggle-bottom {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 12px 8px 14px;
|
||||
background: linear-gradient(to top, rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
.aside-toggle-btn {
|
||||
width: 100%;
|
||||
max-width: 180px;
|
||||
background-color: rgba(255, 255, 255, 0.18);
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.aside-toggle-btn:hover {
|
||||
background-color: rgba(255, 255, 255, 0.28);
|
||||
border-color: rgba(255, 255, 255, 0.45);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.common-aside {
|
||||
width: 100% !important;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1200;
|
||||
max-width: 80vw;
|
||||
}
|
||||
|
||||
:deep(.el-menu) {
|
||||
padding: 12px 4px;
|
||||
}
|
||||
|
||||
.aside-toggle-bottom {
|
||||
padding: 10px 8px 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="header">
|
||||
<div class="l-content">
|
||||
<el-button size="small" @click="handleCollapse">
|
||||
<i class="fa fa-bars"></i>
|
||||
<el-button v-if="showTopToggle" size="small" @click="handleCollapse">
|
||||
<el-icon><Expand /></el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="r-content">
|
||||
@@ -75,7 +75,7 @@ import { useRouter, useRoute } from "vue-router";
|
||||
import { useAllDataStore, useMenuStore, useTabsStore } from "@/stores";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { logout, getCurrentUser } from "@/api/login";
|
||||
import { User, SwitchButton, Sunny, Moon, Refresh, Bell, HomeFilled } from '@element-plus/icons-vue';
|
||||
import { User, SwitchButton, Sunny, Moon, Refresh, Bell, HomeFilled, Expand } from '@element-plus/icons-vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const router = useRouter();
|
||||
@@ -201,6 +201,8 @@ const handleCollapse = () => {
|
||||
store.state.isCollapse = !store.state.isCollapse;
|
||||
};
|
||||
|
||||
const showTopToggle = computed(() => store.state.isCollapse);
|
||||
|
||||
const goHome = () => {
|
||||
tabsStore.closeAll();
|
||||
router.push('/home');
|
||||
@@ -457,6 +459,46 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
padding: 0 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.l-content .el-button {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.r-content {
|
||||
gap: 6px;
|
||||
|
||||
.refresh-cache-btn,
|
||||
.home-btn,
|
||||
.theme-toggle-btn,
|
||||
.message-btn {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
min-height: 30px;
|
||||
min-width: 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.el-dropdown-link {
|
||||
gap: 6px;
|
||||
|
||||
.user {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.user-name,
|
||||
.user-role-tag {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 下拉菜单样式 - 使用全局样式覆盖
|
||||
:deep(.el-dropdown) {
|
||||
.el-dropdown__popper {
|
||||
|
||||
Reference in New Issue
Block a user