2023-12-05 19:23:03 +08:00
|
|
|
<template>
|
2023-12-08 16:40:14 +08:00
|
|
|
<div class="host-layout" v-if="render">
|
2023-12-05 19:23:03 +08:00
|
|
|
<!-- 头部区域 -->
|
|
|
|
|
<header class="host-layout-header">
|
2024-01-04 17:10:07 +08:00
|
|
|
<terminal-header />
|
2023-12-05 19:23:03 +08:00
|
|
|
</header>
|
|
|
|
|
<!-- 主体区域 -->
|
|
|
|
|
<main class="host-layout-main">
|
|
|
|
|
<!-- 左侧操作栏 -->
|
|
|
|
|
<div class="host-layout-left">
|
2024-01-04 17:10:07 +08:00
|
|
|
<terminal-left-sidebar />
|
2023-12-05 19:23:03 +08:00
|
|
|
</div>
|
|
|
|
|
<!-- 内容区域 -->
|
|
|
|
|
<div class="host-layout-content">
|
2024-01-04 17:10:07 +08:00
|
|
|
<terminal-content />
|
2023-12-05 19:23:03 +08:00
|
|
|
</div>
|
|
|
|
|
<!-- 右侧操作栏 -->
|
|
|
|
|
<div class="host-layout-right">
|
|
|
|
|
<terminal-right-sidebar />
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
export default {
|
|
|
|
|
name: 'hostTerminal'
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2024-01-05 16:13:34 +08:00
|
|
|
import { ref, onBeforeMount, onUnmounted, onMounted } from 'vue';
|
2024-01-04 17:10:07 +08:00
|
|
|
import { dictKeys } from './types/terminal.const';
|
2023-12-25 19:03:24 +08:00
|
|
|
import { useCacheStore, useDictStore, useTerminalStore } from '@/store';
|
2023-12-05 19:23:03 +08:00
|
|
|
import TerminalHeader from './components/layout/terminal-header.vue';
|
|
|
|
|
import TerminalLeftSidebar from './components/layout/terminal-left-sidebar.vue';
|
|
|
|
|
import TerminalRightSidebar from './components/layout/terminal-right-sidebar.vue';
|
2023-12-08 14:33:24 +08:00
|
|
|
import TerminalContent from './components/layout/terminal-content.vue';
|
2023-12-05 19:23:03 +08:00
|
|
|
import './assets/styles/layout.less';
|
2023-12-13 23:59:31 +08:00
|
|
|
import 'xterm/css/xterm.css';
|
2023-12-05 19:23:03 +08:00
|
|
|
|
2023-12-08 19:05:00 +08:00
|
|
|
const terminalStore = useTerminalStore();
|
2023-12-08 16:40:14 +08:00
|
|
|
const dictStore = useDictStore();
|
2023-12-25 19:03:24 +08:00
|
|
|
const cacheStore = useCacheStore();
|
2023-12-05 19:23:03 +08:00
|
|
|
|
2024-01-10 19:30:25 +08:00
|
|
|
const originTitle = document.title;
|
2023-12-08 16:40:14 +08:00
|
|
|
const render = ref(false);
|
2023-12-08 14:33:24 +08:00
|
|
|
|
2024-01-05 16:13:34 +08:00
|
|
|
// 关闭视口处理
|
|
|
|
|
const handleBeforeUnload = (event: any) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.returnValue = confirm('系统可能不会保存您所做的更改');
|
|
|
|
|
};
|
|
|
|
|
|
2023-12-08 16:40:14 +08:00
|
|
|
// 加载用户终端偏好
|
|
|
|
|
onBeforeMount(async () => {
|
2023-12-08 19:05:00 +08:00
|
|
|
await terminalStore.fetchPreference();
|
2024-01-10 19:30:25 +08:00
|
|
|
// 设置系统主题配色
|
|
|
|
|
const dark = terminalStore.preference.theme.dark;
|
|
|
|
|
document.body.setAttribute('terminal-theme', dark ? 'dark' : 'light');
|
2023-12-08 19:05:00 +08:00
|
|
|
render.value = true;
|
2023-12-08 16:40:14 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 加载字典值
|
|
|
|
|
onBeforeMount(async () => {
|
|
|
|
|
await dictStore.loadKeys([...dictKeys]);
|
2023-12-08 14:33:24 +08:00
|
|
|
});
|
|
|
|
|
|
2024-01-05 16:13:34 +08:00
|
|
|
// 注册关闭视口事件
|
|
|
|
|
onMounted(() => {
|
2024-01-11 19:24:33 +08:00
|
|
|
// FIXME 开发阶段
|
2024-01-05 16:13:34 +08:00
|
|
|
// window.addEventListener('beforeunload', handleBeforeUnload);
|
|
|
|
|
});
|
|
|
|
|
|
2023-12-25 19:03:24 +08:00
|
|
|
onUnmounted(() => {
|
2024-01-05 16:13:34 +08:00
|
|
|
// 卸载时清除 cache
|
2023-12-25 19:03:24 +08:00
|
|
|
cacheStore.reset('authorizedHostKeys', 'authorizedHostIdentities');
|
2024-01-05 16:13:34 +08:00
|
|
|
// 移除关闭视口事件
|
|
|
|
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
2024-01-10 19:30:25 +08:00
|
|
|
// 去除 body style
|
|
|
|
|
document.body.removeAttribute('terminal-theme');
|
|
|
|
|
// 重置 title
|
|
|
|
|
document.title = originTitle;
|
2023-12-25 19:03:24 +08:00
|
|
|
});
|
|
|
|
|
|
2023-12-05 19:23:03 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
.host-layout {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100vh;
|
|
|
|
|
position: relative;
|
2023-12-08 19:05:00 +08:00
|
|
|
color: var(--color-content-text-2);
|
2023-12-05 19:23:03 +08:00
|
|
|
|
|
|
|
|
&-header {
|
|
|
|
|
width: 100%;
|
2024-01-11 16:55:37 +08:00
|
|
|
height: var(--header-height);
|
2023-12-05 19:23:03 +08:00
|
|
|
background: var(--color-bg-header);
|
2023-12-15 19:21:31 +08:00
|
|
|
position: relative;
|
|
|
|
|
z-index: 9999;
|
2023-12-05 19:23:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&-main {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: calc(100% - var(--sidebar-width));
|
|
|
|
|
position: relative;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&-left, &-right {
|
|
|
|
|
width: var(--sidebar-width);
|
|
|
|
|
height: 100%;
|
|
|
|
|
background: var(--color-bg-sidebar);
|
|
|
|
|
border-top: 1px solid var(--color-bg-content);
|
2023-12-08 14:33:24 +08:00
|
|
|
overflow: hidden;
|
2023-12-05 19:23:03 +08:00
|
|
|
}
|
|
|
|
|
|
2024-01-08 19:27:44 +08:00
|
|
|
&-left {
|
|
|
|
|
border-right: 1px solid var(--color-bg-content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&-right {
|
|
|
|
|
border-left: 1px solid var(--color-bg-content);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-05 19:23:03 +08:00
|
|
|
&-content {
|
2023-12-13 23:59:31 +08:00
|
|
|
width: calc(100% - var(--sidebar-width) * 2);
|
2023-12-05 19:23:03 +08:00
|
|
|
height: 100%;
|
|
|
|
|
background: var(--color-bg-content);
|
2023-12-08 14:33:24 +08:00
|
|
|
overflow: auto;
|
2023-12-05 19:23:03 +08:00
|
|
|
}
|
|
|
|
|
}
|
2023-12-08 14:33:24 +08:00
|
|
|
|
2023-12-05 19:23:03 +08:00
|
|
|
</style>
|