移动端header用户信息部分增加向下箭头及点击下拉弹窗功能
This commit is contained in:
parent
d49d265472
commit
fe4e3a0b25
@ -26,28 +26,41 @@
|
||||
<AppSidebar :collapsed="sidebarCollapsed" @menu-select="handleMenuSelect" />
|
||||
</n-layout-sider>
|
||||
<n-layout class="h-full">
|
||||
<!-- 移动端顶部导航栏 -->
|
||||
<div
|
||||
v-if="isMobile && !isSignupFlow && !isHideSidebar && session.user"
|
||||
class="mobile-header"
|
||||
>
|
||||
<div class="mobile-header-content">
|
||||
<JLogo class="mobile-logo" />
|
||||
<div class="mobile-user-info">
|
||||
{{ teamUserText }}
|
||||
<!-- 移动端顶部导航栏 -->
|
||||
<div
|
||||
v-if="isMobile && !isSignupFlow && !isHideSidebar && session.user"
|
||||
class="mobile-header"
|
||||
>
|
||||
<div class="mobile-header-content">
|
||||
<JLogo class="mobile-logo" />
|
||||
<n-dropdown
|
||||
:options="mobileDropdownOptions"
|
||||
:show-arrow="true"
|
||||
trigger="click"
|
||||
@select="handleMobileDropdownSelect"
|
||||
placement="bottom-start"
|
||||
>
|
||||
<div class="mobile-user-info-wrapper">
|
||||
<div class="mobile-user-info">
|
||||
{{ teamUserText }}
|
||||
</div>
|
||||
<n-icon class="mobile-chevron-icon">
|
||||
<ChevronDown />
|
||||
</n-icon>
|
||||
</div>
|
||||
<n-button
|
||||
quaternary
|
||||
circle
|
||||
@click="sidebarCollapsed = false"
|
||||
class="mobile-menu-button"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon><MenuIcon /></n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
<n-button
|
||||
quaternary
|
||||
circle
|
||||
@click="sidebarCollapsed = false"
|
||||
class="mobile-menu-button"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon><MenuIcon /></n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full h-full overflow-auto" id="scrollContainer">
|
||||
<div
|
||||
v-if="
|
||||
@ -68,13 +81,15 @@
|
||||
</n-layout>
|
||||
<Toaster position="top-right" />
|
||||
<component v-for="dialog in dialogs" :is="dialog" :key="dialog.id" />
|
||||
<!-- 切换团队对话框 -->
|
||||
<SwitchTeamDialog v-model="showTeamSwitcher" />
|
||||
</div>
|
||||
</n-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineAsyncComponent, computed, watch, ref, provide, onMounted, onUnmounted } from 'vue';
|
||||
import { NLayout, NLayoutSider, NConfigProvider, NButton, NIcon } from 'naive-ui';
|
||||
import { defineAsyncComponent, computed, watch, ref, provide, onMounted, onUnmounted, h, getCurrentInstance } from 'vue';
|
||||
import { NLayout, NLayoutSider, NConfigProvider, NButton, NIcon, NDropdown } from 'naive-ui';
|
||||
import { Toaster } from 'vue-sonner';
|
||||
import { dialogs } from './utils/components';
|
||||
import { useRoute } from 'vue-router';
|
||||
@ -82,13 +97,20 @@ import { getTeam } from './data/team';
|
||||
import { session } from './data/session.js';
|
||||
import JLogo from '@/components/icons/JLogo.vue';
|
||||
import MenuIcon from '~icons/lucide/menu';
|
||||
import ChevronDown from '~icons/lucide/chevron-down';
|
||||
|
||||
const AppSidebar = defineAsyncComponent(
|
||||
() => import('./components/AppSidebar.vue'),
|
||||
);
|
||||
|
||||
const SwitchTeamDialog = defineAsyncComponent(
|
||||
() => import('./components/SwitchTeamDialog.vue'),
|
||||
);
|
||||
|
||||
const route = useRoute();
|
||||
const team = getTeam();
|
||||
const instance = getCurrentInstance();
|
||||
const showTeamSwitcher = ref(false);
|
||||
|
||||
// Naive UI 主题配置 - 使用标准方式配置 tooltip 和 menu
|
||||
const themeOverrides = {
|
||||
@ -159,6 +181,39 @@ const handleMenuSelect = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 移动端下拉菜单选项
|
||||
const mobileDropdownOptions = computed(() => {
|
||||
const options = [];
|
||||
const teamData = team?.pg;
|
||||
if (
|
||||
teamData &&
|
||||
(teamData.valid_teams?.length > 1 || teamData.is_desk_user)
|
||||
) {
|
||||
options.push({
|
||||
label: '切换团队',
|
||||
key: 'switch-team',
|
||||
icon: () => h('i', { class: 'i-lucide-command h-4 w-4' }),
|
||||
});
|
||||
}
|
||||
options.push({
|
||||
label: '退出登录',
|
||||
key: 'logout',
|
||||
icon: () => h('i', { class: 'i-lucide-log-out h-4 w-4' }),
|
||||
});
|
||||
return options;
|
||||
});
|
||||
|
||||
// 处理移动端下拉菜单选择
|
||||
const handleMobileDropdownSelect = (key) => {
|
||||
if (key === 'switch-team') {
|
||||
showTeamSwitcher.value = true;
|
||||
} else if (key === 'logout') {
|
||||
if (session) {
|
||||
session.logout.submit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const isHideSidebar = computed(() => {
|
||||
const alwaysHideSidebarRoutes = [
|
||||
'Site Login',
|
||||
@ -298,6 +353,26 @@ provide('session', session);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mobile-user-info-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
padding: 6px 8px;
|
||||
border-radius: 6px;
|
||||
transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-user-info-wrapper:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.mobile-user-info-wrapper:active {
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.mobile-user-info {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
@ -306,6 +381,18 @@ provide('session', session);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-chevron-icon {
|
||||
font-size: 16px;
|
||||
color: #8b8e95;
|
||||
flex-shrink: 0;
|
||||
transition: color 0.2s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.mobile-user-info-wrapper:hover .mobile-chevron-icon {
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.mobile-menu-button {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user