update
This commit is contained in:
@@ -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>© 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,13 +114,21 @@ 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> <!-- 网格布局图标 -->
|
||||
</button>
|
||||
</div>
|
||||
<!-- 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>
|
||||
<!-- 连接列表弹出窗口 (保持不变) -->
|
||||
<div v-if="showConnectionListPopup" class="connection-list-popup" @click.self="togglePopup">
|
||||
<div class="popup-content">
|
||||
@@ -275,15 +297,38 @@ const openLayoutConfigurator = () => {
|
||||
flex-shrink: 0; /* 防止被压缩 */
|
||||
}
|
||||
|
||||
/* 新增:布局配置器按钮样式 */
|
||||
/* 通用操作按钮样式 */
|
||||
.action-button {
|
||||
background: none;
|
||||
border: none;
|
||||
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 {
|
||||
background: none;
|
||||
border: none;
|
||||
border-left: 1px solid var(--border-color, #bdbdbd); /* 使用变量 */
|
||||
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); /* 确保列表背景 */
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"notifications": "Notifications",
|
||||
"auditLogs": "Audit Logs",
|
||||
"settings": "Settings",
|
||||
"hideLayout": "Hide Layout Elements",
|
||||
"showLayout": "Show Layout Elements",
|
||||
"customizeStyle": "Customize Style"
|
||||
},
|
||||
"styleCustomizer": {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"notifications": "通知管理",
|
||||
"auditLogs": "审计日志",
|
||||
"settings": "设置",
|
||||
"hideLayout": "隐藏布局元素",
|
||||
"showLayout": "显示布局元素",
|
||||
"customizeStyle": "自定义外观"
|
||||
},
|
||||
"styleCustomizer": {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user