This commit is contained in:
Baobhan Sith
2025-04-19 17:47:30 +08:00
parent d993426a08
commit 75b6bd9f90
5 changed files with 87 additions and 28 deletions
+13 -7
View File
@@ -1,10 +1,11 @@
<script setup lang="ts">
import { RouterLink, RouterView, useRoute } from 'vue-router';
import { ref, onMounted, watch, nextTick } from 'vue';
import { ref, onMounted, watch, nextTick, computed } from 'vue'; // *** 导入 computed ***
import { useI18n } from 'vue-i18n';
import { useAuthStore } from './stores/auth.store';
import { useSettingsStore } from './stores/settings.store';
import { useAppearanceStore } from './stores/appearance.store'; // 导入外观 Store
import { useAppearanceStore } from './stores/appearance.store';
import { useLayoutStore } from './stores/layout.store'; // *** 导入布局 Store ***
import { storeToRefs } from 'pinia';
// 导入通知显示组件
import UINotificationDisplay from './components/UINotificationDisplay.vue';
@@ -16,10 +17,12 @@ import StyleCustomizer from './components/StyleCustomizer.vue';
const { t } = useI18n();
const authStore = useAuthStore();
const settingsStore = useSettingsStore();
const appearanceStore = useAppearanceStore(); // 实例化外观 Store
const appearanceStore = useAppearanceStore();
const layoutStore = useLayoutStore(); // *** 实例化布局 Store ***
const { isAuthenticated } = storeToRefs(authStore);
const { showPopupFileEditorBoolean } = storeToRefs(settingsStore);
const { isStyleCustomizerVisible } = storeToRefs(appearanceStore); // 从外观 store 获取可见性状态
const { isStyleCustomizerVisible } = storeToRefs(appearanceStore);
const { isLayoutVisible } = storeToRefs(layoutStore); // *** 获取布局可见性状态 ***
const route = useRoute();
const navRef = ref<HTMLElement | null>(null);
@@ -45,9 +48,12 @@ onMounted(() => {
setTimeout(updateUnderline, 100);
});
// *** 新增:计算属性,判断是否在 workspace 路由 ***
const isWorkspaceRoute = computed(() => route.path === '/workspace');
watch(route, () => {
updateUnderline();
});
}, { immediate: true }); // *** 确保 immediate: true 存在 ***
const handleLogout = () => {
@@ -67,7 +73,7 @@ const closeStyleCustomizer = () => {
<template>
<div id="app-container">
<header>
<header v-if="!isWorkspaceRoute || isLayoutVisible"> <!-- *** 添加 v-if *** -->
<nav ref="navRef">
<div class="nav-left"> <!-- Group left-aligned links -->
<RouterLink to="/">{{ t('nav.dashboard') }}</RouterLink>
@@ -101,7 +107,7 @@ const closeStyleCustomizer = () => {
<!-- 条件渲染样式自定义器使用 store 的状态和方法 -->
<StyleCustomizer v-if="isStyleCustomizerVisible" @close="closeStyleCustomizer" />
<footer>
<footer v-if="!isWorkspaceRoute || isLayoutVisible"> <!-- *** 添加 v-if *** -->
<!-- 使用 t 函数获取应用名称 -->
<p>&copy; 2025 {{ t('appName') }}</p>
</footer>
@@ -1,7 +1,8 @@
<script setup lang="ts">
import { ref, computed, PropType } from 'vue'; // 导入 ref 和 computed
import { useI18n } from 'vue-i18n'; // 导入 i18n
// import { storeToRefs } from 'pinia'; // 移除 storeToRefs 导入,因为 paneVisibility 不再使用
import { useRoute } from 'vue-router'; // *** 导入 useRoute ***
import { storeToRefs } from 'pinia'; // *** 重新导入 storeToRefs ***
import WorkspaceConnectionListComponent from './WorkspaceConnectionList.vue'; // 导入连接列表组件
import { useSessionStore } from '../stores/session.store'; // 导入 session store
import { useLayoutStore, type PaneName } from '../stores/layout.store'; // 导入布局 store 和类型
@@ -11,7 +12,8 @@ import type { SessionTabInfoWithStatus } from '../stores/session.store'; // 导
// --- Setup ---
const { t } = useI18n(); // 初始化 i18n
const layoutStore = useLayoutStore(); // 初始化布局 store
// const { paneVisibility } = storeToRefs(layoutStore); // 移除:paneVisibility 不再存在
const { isLayoutVisible } = storeToRefs(layoutStore); // *** 获取 isLayoutVisible ***
const route = useRoute(); // *** 获取路由信息 ***
// 定义 Props
const props = defineProps({
@@ -74,6 +76,18 @@ const openLayoutConfigurator = () => {
emit('open-layout-configurator'); // 发出事件
};
// --- Layout Visibility Logic ---
// Show the toggle button only on the workspace route
const showLayoutToggleButton = computed(() => route.path === '/workspace');
const toggleLayout = () => {
layoutStore.toggleLayoutVisibility();
};
const layoutToggleIcon = computed(() => isLayoutVisible.value ? 'fa-eye' : 'fa-eye-slash');
const layoutToggleTitle = computed(() => isLayoutVisible.value ? t('nav.hideLayout', '隐藏布局元素') : t('nav.showLayout', '显示布局元素')); // 添加默认值
// --- End Layout Visibility Logic ---
</script>
<template>
@@ -100,11 +114,19 @@ const openLayoutConfigurator = () => {
<i class="fas fa-plus"></i>
</button>
</div>
<!-- 按钮容器推到最右侧 -->
<div class="action-buttons-container">
<!-- 新增布局配置器按钮 -->
<button class="layout-config-button" @click="openLayoutConfigurator" title="配置工作区布局">
<i class="fas fa-th-large"></i> <!-- 网格布局图标 -->
<!-- Layout Visibility Toggle Button -->
<button
v-if="showLayoutToggleButton"
@click="toggleLayout"
class="action-button layout-toggle-button"
:title="layoutToggleTitle"
>
<i :class="['fas', layoutToggleIcon]"></i>
</button>
<!-- Layout Configurator Button -->
<button class="action-button layout-config-button" @click="openLayoutConfigurator" :title="t('layout.configure', '配置布局')"> <!-- 使用 t 函数 -->
<i class="fas fa-palette"></i> <!-- 更新图标为调色板 -->
</button>
</div>
<!-- 连接列表弹出窗口 (保持不变) -->
@@ -275,15 +297,38 @@ const openLayoutConfigurator = () => {
flex-shrink: 0; /* 防止被压缩 */
}
/* 新增:布局配置器按钮样式 */
.layout-config-button {
/* 通用操作按钮样式 */
.action-button {
background: none;
border: none;
border-left: 1px solid var(--border-color, #bdbdbd); /* 使用变量 */
border-left: 1px solid var(--border-color, #bdbdbd); /* 左侧边框作为分隔 */
padding: 0 0.8rem;
cursor: pointer;
font-size: 1.1em;
color: var(--text-color-secondary, #616161);
display: flex;
align-items: center;
justify-content: center;
height: 100%;
flex-shrink: 0;
transition: background-color 0.2s, color 0.2s;
}
.action-button:hover {
background-color: var(--header-bg-color, #d0d0d0);
color: var(--text-color, #333);
}
.action-button i {
line-height: 1;
}
.layout-config-button {
padding: 0 0.8rem;
cursor: pointer;
font-size: 1.1em; /* 与其他按钮一致 */
color: var(--text-color-secondary, #616161); /* 使用变量 */
color: var(--text-color-secondary, #616161);
display: flex;
align-items: center;
justify-content: center;
@@ -297,8 +342,6 @@ const openLayoutConfigurator = () => {
line-height: 1;
}
/* 弹出窗口样式 */
.connection-list-popup {
position: fixed; /* 固定定位,覆盖整个屏幕 */
top: 0;
@@ -354,10 +397,7 @@ const openLayoutConfigurator = () => {
border: 1px solid var(--border-color); /* Use theme variable */
border-radius: 4px;
}
/* 覆盖 WorkspaceConnectionList 内部样式(如果需要) */
/* :deep(.popup-connection-list .search-add-bar) { */
/* display: none; */ /* 不再隐藏搜索栏 */
/* } */
:deep(.popup-connection-list .connection-list-area) {
padding: 0; /* 保持移除内边距 */
background-color: var(--app-bg-color); /* 确保列表背景 */
+2
View File
@@ -11,6 +11,8 @@
"notifications": "Notifications",
"auditLogs": "Audit Logs",
"settings": "Settings",
"hideLayout": "Hide Layout Elements",
"showLayout": "Show Layout Elements",
"customizeStyle": "Customize Style"
},
"styleCustomizer": {
+2
View File
@@ -11,6 +11,8 @@
"notifications": "通知管理",
"auditLogs": "审计日志",
"settings": "设置",
"hideLayout": "隐藏布局元素",
"showLayout": "显示布局元素",
"customizeStyle": "自定义外观"
},
"styleCustomizer": {
+10 -1
View File
@@ -92,6 +92,8 @@ export const useLayoutStore = defineStore('layout', () => {
'connections', 'terminal', 'commandBar', 'fileManager',
'editor', 'statusMonitor', 'commandHistory', 'quickCommands'
]);
// 新增:控制布局(Header/Footer)可见性的状态
const isLayoutVisible: Ref<boolean> = ref(true);
// --- 计算属性 ---
// 计算当前布局中正在使用的面板
@@ -170,7 +172,11 @@ export const useLayoutStore = defineStore('layout', () => {
}
}
// 新增 Action: 切换布局(Header/Footer)的可见性
function toggleLayoutVisibility() {
isLayoutVisible.value = !isLayoutVisible.value;
console.log(`[Layout Store] 布局可见性切换为: ${isLayoutVisible.value}`);
}
// --- 持久化 ---
// 监听 layoutTree 的变化,并自动保存到 localStorage
watch(
@@ -208,5 +214,8 @@ export const useLayoutStore = defineStore('layout', () => {
generateId,
// 暴露 allPossiblePanes 供配置器显示所有选项
allPossiblePanes,
// 新增:暴露布局可见性状态和切换方法
isLayoutVisible,
toggleLayoutVisibility,
};
});