20260806173205

This commit is contained in:
oneao committed 2026-08-06 17:32:07 +08:00
1 parent 74cdb7f306
commit 6baa339efa
14 files changed
+804 -324

No files matched your search

@@ -1,17 +1,7 @@
<script setup>
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import {
ArrowLeft,
ChevronLeft,
ChevronRight,
House,
Maximize2,
Minimize2,
RotateCw,
X,
} from "@lucide/vue";
import { theme } from "antdv-next";
import { ChevronLeft, ChevronRight, X } from "@lucide/vue";
import { useAppStore } from "@/stores/app";
import { usePermissionStore } from "@/stores/permissions";
@@ -19,7 +9,6 @@ const route = useRoute();
const router = useRouter();
const appStore = useAppStore();
const permissionStore = usePermissionStore();
const { token } = theme.useToken();
const headerRef = ref(null);
const trackRef = ref(null);
const overflowed = ref(false);
@@ -161,62 +150,15 @@ function handleTabKeydown(event, index) {
focusAdjacentTab(index, event.key === "ArrowLeft" ? -1 : 1);
}
function goConsole() {
router.push("/dashboard");
}
function goBack() {
router.back();
}
function refreshCurrentRoute() {
appStore.refreshRoute(route.fullPath);
}
function toggleMaximize() {
appStore.toggleContentMaximized();
}
</script>
<template>
<header
ref="headerRef"
class="tab-header"
:style="{
'--tabs-active-bg': token.colorPrimaryBg,
'--tabs-active-color': token.colorPrimary,
'--tabs-idle-bg': token.colorFillQuaternary,
}"
>
<div class="tab-actions">
<a-tooltip title="返回上一页" placement="bottom">
<button type="button" class="tab-action" aria-label="返回上一页" @click="goBack">
<ArrowLeft />
</button>
</a-tooltip>
<a-tooltip title="刷新当前页" placement="bottom">
<button
type="button"
class="tab-action"
aria-label="刷新当前页"
@click="refreshCurrentRoute"
>
<RotateCw />
</button>
</a-tooltip>
<a-tooltip title="返回控制台" placement="bottom">
<button type="button" class="tab-action" aria-label="返回控制台" @click="goConsole">
<House />
</button>
</a-tooltip>
</div>
<header ref="headerRef" class="tab-header">
<!-- 滚动按钮 -->
<button
v-if="overflowed"
type="button"
class="tab-nav-button"
class="tab-btn"
aria-label="向左滚动页签"
:disabled="!canScrollLeft"
@click="scrollTabs(-1)"
@@ -224,6 +166,7 @@ function toggleMaximize() {
<ChevronLeft />
</button>
<!-- 标签轨道 -->
<div ref="trackRef" class="tab-track" role="tablist" @scroll.passive="updateScrollState">
<div
v-for="(item, index) in tabItems"
@@ -258,28 +201,13 @@ function toggleMaximize() {
<button
v-if="overflowed"
type="button"
class="tab-nav-button"
class="tab-btn"
aria-label="向右滚动页签"
:disabled="!canScrollRight"
@click="scrollTabs(1)"
>
<ChevronRight />
</button>
<a-tooltip
:title="appStore.contentMaximized ? '退出最大化' : '应用内最大化'"
placement="bottom"
>
<button
type="button"
class="tab-nav-button tab-maximize"
aria-label="应用内最大化"
@click="toggleMaximize"
>
<Minimize2 v-if="appStore.contentMaximized" />
<Maximize2 v-else />
</button>
</a-tooltip>
</header>
</template>
@@ -292,16 +220,53 @@ function toggleMaximize() {
align-items: center;
gap: 4px;
padding: 3px 8px;
background: var(--fms-surface);
background: #ffffff;
}
/* ---- 通用小按钮 ---- */
.tab-btn {
display: grid;
flex: none;
width: 28px;
height: 28px;
padding: 0;
place-items: center;
border: 0;
border-radius: 6px;
color: #71717a;
background: transparent;
cursor: pointer;
transition:
color 0.15s ease,
background-color 0.15s ease;
&:hover:not(:disabled) {
color: #3f3f46;
background: #f4f4f5;
}
&:disabled {
cursor: default;
opacity: 0.35;
}
.lucide {
width: 14px;
height: 14px;
stroke-width: 1.8;
}
}
/* ---- 标签轨道 ---- */
.tab-track {
display: flex;
flex: 1;
min-width: 0;
gap: 6px;
padding: 2px 0;
margin: -2px 0;
overflow-x: auto;
overflow-y: hidden;
overflow-y: visible;
overscroll-behavior-inline: contain;
scrollbar-width: none;
@@ -310,6 +275,7 @@ function toggleMaximize() {
}
}
/* ---- 标签项 ---- */
.tab-item {
display: flex;
flex: none;
@@ -317,17 +283,28 @@ function toggleMaximize() {
height: 28px;
align-items: center;
overflow: hidden;
border-radius: 4px;
background: var(--tabs-idle-bg);
color: var(--fms-text-secondary);
border-radius: 6px;
background: #f4f4f5;
color: #71717a;
transition:
background-color 0.15s ease,
color 0.15s ease;
&:hover {
color: var(--tabs-active-color);
background: #f4f4f5;
color: #3f3f46;
}
&--active {
background: var(--tabs-active-bg);
color: var(--tabs-active-color);
background: #f4f4f5;
color: #3f3f46;
font-weight: 500;
box-shadow: 0 1px 3px rgb(0 0 0 / 6%), 0 1px 2px rgb(0 0 0 / 4%);
&:hover {
background: #f4f4f5;
color: #3f3f46;
}
}
&__select,
@@ -345,8 +322,8 @@ function toggleMaximize() {
flex: 1;
align-items: center;
justify-content: center;
padding: 0 7px;
font-size: 12px;
padding: 0 8px;
font-size: 13px;
span {
white-space: nowrap;
@@ -359,6 +336,7 @@ function toggleMaximize() {
flex: none;
padding: 0;
place-items: center;
border-radius: 4px;
&:hover {
background: rgb(0 0 0 / 6%);
@@ -367,70 +345,8 @@ function toggleMaximize() {
.lucide {
width: 10px;
height: 10px;
stroke-width: 2;
}
}
}
.tab-nav-button {
display: grid;
flex: none;
width: 28px;
height: 28px;
padding: 0;
place-items: center;
border: 0;
border-radius: 4px;
color: var(--fms-text-secondary);
background: var(--tabs-idle-bg);
cursor: pointer;
&:hover:not(:disabled) {
color: var(--tabs-active-color);
background: var(--tabs-active-bg);
}
&:disabled {
cursor: default;
opacity: 0.35;
}
.lucide {
width: 14px;
height: 14px;
}
}
.tab-actions {
display: flex;
flex: none;
align-items: center;
gap: 4px;
}
.tab-action {
display: grid;
flex: none;
width: 28px;
height: 28px;
padding: 0;
place-items: center;
border: 0;
border-radius: 4px;
color: var(--fms-text-secondary);
background: var(--tabs-idle-bg);
cursor: pointer;
transition:
color 0.15s ease,
background-color 0.15s ease;
&:hover:not(:disabled) {
color: var(--tabs-active-color);
background: var(--tabs-active-bg);
}
.lucide {
width: 14px;
height: 14px;
}
}
</style>