20260807173051

This commit is contained in:
oneao committed 2026-08-07 17:30:51 +08:00
1 parent 6938deef39
commit a07b1b6fdb
14 files changed
+441 -270

No files matched your search

@@ -81,12 +81,11 @@ const routeInstanceKey = computed(
}
.app-content {
width: 100%;
flex: 1 1 auto;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
padding: 6px 0;
padding: 12px 0;
background: #ffffff;
}
@@ -1,5 +1,5 @@
<script setup>
import { computed, onMounted, ref, watch } from "vue";
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ChevronDown, House } from "@lucide/vue";
import { useAppStore } from "@/stores/app";
@@ -16,6 +16,41 @@ const permissionStore = usePermissionStore();
const openKeys = ref([]);
const effectiveCollapsed = computed(() => appStore.sidebarCollapsed);
/* ---- 拖拽调整宽度 ---- */
const MIN_WIDTH = 180;
const MAX_WIDTH = 400;
const sidebarWidth = ref(220);
const isResizing = ref(false);
function onResizeStart(e) {
e.preventDefault();
isResizing.value = true;
document.body.style.cursor = "col-resize";
document.body.style.userSelect = "none";
}
function onResizeMove(e) {
if (!isResizing.value) return;
sidebarWidth.value = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, e.clientX));
}
function onResizeEnd() {
if (!isResizing.value) return;
isResizing.value = false;
document.body.style.cursor = "";
document.body.style.userSelect = "";
}
onMounted(() => {
document.addEventListener("mousemove", onResizeMove);
document.addEventListener("mouseup", onResizeEnd);
});
onBeforeUnmount(() => {
document.removeEventListener("mousemove", onResizeMove);
document.removeEventListener("mouseup", onResizeEnd);
});
function resolveIcon(iconName, fallback) {
return getIcon(iconName) || fallback;
}
@@ -174,16 +209,16 @@ onMounted(() => {
</script>
<template>
<a-layout-sider
class="app-sider"
:collapsed="effectiveCollapsed"
:trigger="null"
:collapsed-width="56"
collapsible
resizable
theme="light"
width="220"
>
<div class="sidebar-outer" :style="{ width: effectiveCollapsed ? '56px' : sidebarWidth + 'px' }">
<a-layout-sider
class="app-sider"
:collapsed="effectiveCollapsed"
:trigger="null"
:collapsed-width="56"
collapsible
theme="light"
width="100%"
>
<!-- 品牌区 -->
<div class="sidebar-header" :class="{ collapsed: effectiveCollapsed }">
<div class="sidebar-brand">
@@ -263,22 +298,54 @@ onMounted(() => {
</template>
</nav>
</a-layout-sider>
<div
v-if="!effectiveCollapsed"
class="sidebar-resize-handle"
@mousedown="onResizeStart"
/>
</div>
</template>
<style scoped lang="scss">
/* ============================================================
* Sidebar 外层容器(控制宽度)
* ============================================================ */
.sidebar-outer {
position: relative;
display: flex;
flex: none;
height: 100%;
}
/* ---- 拖拽手柄 ---- */
.sidebar-resize-handle {
position: absolute;
top: 0;
right: -2px;
bottom: 0;
width: 4px;
z-index: 20;
cursor: col-resize;
background: transparent;
transition: background-color 0.15s ease;
&:hover {
background: rgb(0 0 0 / 6%);
}
}
/* ============================================================
* Sidebar 容器
* ============================================================ */
.app-sider {
width: 100% !important;
max-width: none !important;
min-width: 0 !important;
flex: none !important;
height: 100%;
overflow: hidden;
border-right: 1px solid transparent;
background: #ffffff;
transition: border-color 0.2s ease;
&:hover {
border-right-color: var(--border, #e4e4e7);
}
:deep(.ant-layout-sider-children) {
display: flex;
@@ -387,8 +454,8 @@ onMounted(() => {
color: #3f3f46;
font-weight: 500;
box-shadow:
0 1px 3px rgb(0 0 0 / 8%),
0 2px 4px rgb(0 0 0 / 6%);
0 1px 3px rgb(0 0 0 / 4%),
0 2px 4px rgb(0 0 0 / 3%);
}
&.collapsed {
@@ -212,17 +212,18 @@ function handleTabKeydown(event, index) {
<style lang="scss" scoped>
.tab-header {
position: relative;
z-index: 15;
display: flex;
flex: none;
height: 34px;
height: 38px;
align-items: center;
gap: 4px;
padding: 3px 0;
background: #ffffff;
gap: 2px;
padding: 4px 0;
background: transparent;
}
/* ---- 通用小按钮 ---- */
/* ---- 滚动按钮(ghost 风格) ---- */
.tab-btn {
display: grid;
flex: none;
@@ -230,7 +231,7 @@ function handleTabKeydown(event, index) {
height: 28px;
padding: 0;
place-items: center;
border: 1px solid #e4e4e7;
border: 0;
border-radius: 6px;
color: #71717a;
background: transparent;
@@ -262,8 +263,7 @@ function handleTabKeydown(event, index) {
flex: 1;
min-width: 0;
gap: 6px;
padding: 2px 0;
margin: -2px 0;
padding: 0;
overflow-x: auto;
overflow-y: visible;
overscroll-behavior-inline: contain;
@@ -274,35 +274,41 @@ function handleTabKeydown(event, index) {
}
}
/* ---- 标签项 ---- */
/* ---- 标签项(应用 tab 药丸式) ---- */
.tab-item {
display: flex;
flex: none;
min-width: 64px;
height: 28px;
min-width: 72px;
height: 30px;
align-items: center;
overflow: hidden;
border-radius: 6px;
background: #f4f4f5;
border-radius: 8px;
background: transparent;
color: #71717a;
transition:
background-color 0.15s ease,
color 0.15s ease;
background: #f4f4f5;
&:hover {
background: #f4f4f5;
background: #ebebeb;
color: #3f3f46;
}
/* 选中态:实心深色药丸,应用 tab 的醒目语言 */
&--active {
background: #f4f4f5;
color: #3f3f46;
color: #ffffff;
font-weight: 500;
box-shadow: 0 1px 3px rgb(0 0 0 / 6%), 0 1px 2px rgb(0 0 0 / 4%);
background: #18181b;
&:hover {
background: #f4f4f5;
color: #3f3f46;
background: #27272a;
color: #ffffff;
}
.tab-item__close:hover {
background: rgb(255 255 255 / 12%);
}
}
@@ -323,27 +329,30 @@ function handleTabKeydown(event, index) {
justify-content: center;
padding: 0 8px;
font-size: 13px;
overflow: hidden;
span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
&__close {
display: grid;
width: 18px;
flex: none;
width: 22px;
padding: 0;
place-items: center;
border-radius: 4px;
&:hover {
background: rgb(0 0 0 / 6%);
background: rgb(0 0 0 / 8%);
}
.lucide {
width: 10px;
height: 10px;
width: 12px;
height: 12px;
stroke-width: 2;
}
}
@@ -89,7 +89,7 @@ function handleClick() {
background: #f4f4f5;
color: #3f3f46;
font-weight: 500;
box-shadow: 0 1px 3px rgb(0 0 0 / 8%), 0 2px 4px rgb(0 0 0 / 6%);
box-shadow: 0 1px 3px rgb(0 0 0 / 4%), 0 2px 4px rgb(0 0 0 / 3%);
}
/* ---- 可展开的父级按钮 ---- */