移动端适配

This commit is contained in:
2025-12-09 16:04:36 +08:00
parent 242a263daa
commit a063e9ce32
14 changed files with 811 additions and 50 deletions

View File

@@ -210,10 +210,95 @@ function handleClick(menu: SysMenu) {
}
}
/* 响应式设计 */
/* 移动端响应式设计 - 水平标签栏 */
@media (max-width: 768px) {
.floating-sidebar {
width: 160px;
width: 100%;
height: auto;
flex-direction: row;
border-radius: 0 0 8px 8px; // 顶部圆角移除与main-content连接
}
.sidebar-content {
width: 100%;
flex-direction: row;
}
.sidebar-nav {
flex-direction: row;
padding: 10px 0;
gap: 0;
overflow-x: auto;
overflow-y: hidden;
/* 水平滚动条样式 */
&::-webkit-scrollbar {
height: 4px;
width: auto;
}
}
.sidebar-item {
flex: 1;
min-width: 60px;
height: 44px;
justify-content: center;
&::before {
display: none; // 移动端隐藏左侧指示条
}
&.active::after {
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 3px;
background: #C62828;
border-radius: 2px;
}
// Resource theme 在移动端的特殊样式
&.theme-resource {
padding: 0 5px;
margin: 0;
&.active {
background: transparent;
border-radius: 0;
margin: 0;
height: 44px;
&::after {
right: auto;
top: auto;
width: 20px;
height: 3px;
background: #C62828;
opacity: 1;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
border-radius: 2px;
}
.sidebar-link {
color: #C62828;
}
}
}
}
.sidebar-link {
padding: 0 8px;
font-size: 14px;
justify-content: center;
.theme-resource & {
margin-left: 0; // 移动端取消左边距
}
}
}
</style>

View File

@@ -61,7 +61,7 @@
<!-- 搜索框 -->
<Search @search="handleSearch" />
<Notice />
<UserDropdown :user="userInfo" @logout="handleLogout" />
<UserDropdown :userinfo="userInfo" @logout="handleLogout" />
</div>
</div>
</nav>
@@ -88,7 +88,7 @@ const specialTags = ref<Tag[]>([]); // 特殊标签:专题报告和思政案
// 获取所有菜单
const allMenus = computed(() => store.getters['auth/menuTree']);
const userInfo = computed(() => store.getters['auth/user']);
const userInfo = computed(() => store.getters['auth/userinfo']);
// 加载特殊标签
onMounted(async () => {

View File

@@ -3,8 +3,8 @@
ref="dropdownRef"
class="user-dropdown"
@click="toggleDropdown"
@mouseenter="openDropdown"
@mouseleave="closeDropdown"
@mouseenter="props.disableHover ? undefined : openDropdown"
@mouseleave="props.disableHover ? undefined : closeDropdown"
v-click-outside="forceCloseDropdown"
>
<!-- 未登录状态 -->
@@ -23,10 +23,9 @@
<span class="avatar-placeholder" v-else>{{ avatarText }}</span>
</div>
<div class="user-details" v-if="!collapsed">
<div class="user-name">{{ user?.fullName || user?.username }}</div>
<div class="user-name">{{ user?.username }}</div>
<div class="user-role">{{ primaryRole }}</div>
</div>
<i class="dropdown-icon" :class="{ 'open': dropdownVisible }"></i>
</div>
<!-- 下拉菜单 -->
@@ -36,8 +35,8 @@
:class="{ 'show': dropdownVisible }"
:style="dropdownStyle"
v-if="dropdownVisible"
@mouseenter="openDropdown"
@mouseleave="closeDropdown"
@mouseenter="props.disableHover ? undefined : openDropdown"
@mouseleave="props.disableHover ? undefined : closeDropdown"
>
<!-- 未登录时的菜单 -->
<template v-if="!isLoggedIn">
@@ -65,7 +64,7 @@
</div>
<div class="dropdown-divider" v-if="userMenus.length > 0"></div>
<div class="dropdown-footer">
<div class="dropdown-item info" v-if="isAdmin">
<div class="dropdown-item info" v-if="!props.hideAdmin && isAdmin">
<img class="item-icon icon-logout" src="@/assets/imgs/admin-home.svg" alt="切换页面">
<ChangeHome />
</div>
@@ -95,11 +94,14 @@ const routes = router.getRoutes();
// Props
interface Props {
user?: UserVO | null;
userinfo?: UserVO | null;
collapsed?: boolean;
hideAdmin?: boolean; // 新增:隐藏管理端相关功能
disableHover?: boolean; // 新增禁用hover事件用于移动端
}
const props = defineProps<Props>();
const user = computed(() => store.getters['auth/user']);
// Emits
const emit = defineEmits<{
@@ -121,11 +123,11 @@ const isLoggedIn = computed(() => {
});
const userAvatar = computed(() => {
return props.user?.avatar ? FILE_DOWNLOAD_URL + props.user?.avatar : '';
return props.userinfo?.avatar ? FILE_DOWNLOAD_URL + props.userinfo?.avatar : '';
});
const avatarText = computed(() => {
const name = props.user?.fullName || props.user?.username || '';
const name = props.userinfo?.fullName || props.userinfo?.username || '';
return name.charAt(0).toUpperCase();
});