feat: 终端承载页.
This commit is contained in:
2
orion-ops-ui/components.d.ts
vendored
2
orion-ops-ui/components.d.ts
vendored
@@ -3,7 +3,7 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
// Generated by unplugin-vue-components
|
// Generated by unplugin-vue-components
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
import '@vue/runtime-core'
|
import '@vue/runtime-core';
|
||||||
|
|
||||||
export {}
|
export {}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<div class="terminal-setting-container">
|
||||||
|
<div class="terminal-setting-wrapper">
|
||||||
|
<!-- 组合容器 -->
|
||||||
|
<div class="combined-container">
|
||||||
|
<!-- 新建连接 -->
|
||||||
|
<div class="combined-handler">
|
||||||
|
<!-- 图标 -->
|
||||||
|
<div class="combined-handler-icon">
|
||||||
|
<icon-plus />
|
||||||
|
</div>
|
||||||
|
<!-- 内容 -->
|
||||||
|
<div class="combined-handler-text">
|
||||||
|
新建连接
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 主机列表 -->
|
||||||
|
<div class="combined-handler">
|
||||||
|
<!-- 图标 -->
|
||||||
|
<div class="combined-handler-icon">
|
||||||
|
<icon-desktop />
|
||||||
|
</div>
|
||||||
|
<!-- 内容 -->
|
||||||
|
<div class="combined-handler-text">
|
||||||
|
历史1
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'emptyRecommend'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import { useTerminalStore } from '@/store';
|
||||||
|
|
||||||
|
const { tabManager, hosts } = useTerminalStore();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@handler-height: 48px;
|
||||||
|
|
||||||
|
.combined-container {
|
||||||
|
padding: 8px;
|
||||||
|
margin: 64px auto;
|
||||||
|
width: 448px;
|
||||||
|
height: 448px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.combined-handler {
|
||||||
|
width: 100%;
|
||||||
|
height: @handler-height;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
background-color: var(--color-fill-2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--color-content-text-1);
|
||||||
|
|
||||||
|
&-icon {
|
||||||
|
width: @handler-height;
|
||||||
|
height: @handler-height;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-text {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div class="terminal-setting-container">
|
||||||
|
<div class="terminal-setting-wrapper terminal-skeleton">
|
||||||
|
<!-- 加载骨架 -->
|
||||||
|
<a-skeleton class="full"
|
||||||
|
:animation="true">
|
||||||
|
<a-skeleton-line :rows="6"
|
||||||
|
:line-height="42"
|
||||||
|
:line-spacing="24" />
|
||||||
|
</a-skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'loadingSkeleton'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.terminal-skeleton {
|
||||||
|
margin: 32px auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="terminal-content">
|
<div class="terminal-content">
|
||||||
<!-- 内容 tabs -->
|
<!-- 内容 tabs -->
|
||||||
<a-tabs v-model:active-key="tabManager.active">
|
<a-tabs v-if="tabManager.active"
|
||||||
|
v-model:active-key="tabManager.active">
|
||||||
<a-tab-pane v-for="tab in tabManager.items"
|
<a-tab-pane v-for="tab in tabManager.items"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
:title="tab.title">
|
:title="tab.title">
|
||||||
@@ -22,6 +23,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
|
<!-- 承载页推荐 -->
|
||||||
|
<empty-recommend v-else />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -35,6 +38,7 @@
|
|||||||
import { TabType, InnerTabs } from '../../types/terminal.const';
|
import { TabType, InnerTabs } from '../../types/terminal.const';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
|
import EmptyRecommend from './empty-recommend.vue';
|
||||||
import NewConnectionView from '../new-connection/new-connection-view.vue';
|
import NewConnectionView from '../new-connection/new-connection-view.vue';
|
||||||
import TerminalDisplaySetting from '../view-setting/terminal-display-setting.vue';
|
import TerminalDisplaySetting from '../view-setting/terminal-display-setting.vue';
|
||||||
import TerminalThemeSetting from '../view-setting/terminal-theme-setting.vue';
|
import TerminalThemeSetting from '../view-setting/terminal-theme-setting.vue';
|
||||||
@@ -46,6 +50,8 @@
|
|||||||
// 监听 tab 修改
|
// 监听 tab 修改
|
||||||
watch(() => tabManager.active, active => {
|
watch(() => tabManager.active, active => {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
|
// 修改标题
|
||||||
|
document.title = '主机终端';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 获取 tab
|
// 获取 tab
|
||||||
|
|||||||
@@ -40,16 +40,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<div class="terminal-setting-body body-container">
|
<div class="terminal-setting-body body-container">
|
||||||
<!-- 加载中 -->
|
|
||||||
<a-skeleton v-if="loading"
|
|
||||||
class="hosts-skeleton"
|
|
||||||
:animation="true">
|
|
||||||
<a-skeleton-line :rows="6"
|
|
||||||
:line-height="40"
|
|
||||||
:line-spacing="20" />
|
|
||||||
</a-skeleton>
|
|
||||||
<!-- 无数据 -->
|
<!-- 无数据 -->
|
||||||
<a-empty v-else-if="!hosts.hostList?.length">
|
<a-empty v-if="!hosts.hostList?.length">
|
||||||
<template #image>
|
<template #image>
|
||||||
<icon-desktop />
|
<icon-desktop />
|
||||||
</template>
|
</template>
|
||||||
@@ -77,16 +69,14 @@
|
|||||||
import type { SelectOptionData } from '@arco-design/web-vue';
|
import type { SelectOptionData } from '@arco-design/web-vue';
|
||||||
import { onBeforeMount, ref } from 'vue';
|
import { onBeforeMount, ref } from 'vue';
|
||||||
import { NewConnectionType, newConnectionTypeKey } from '../../types/terminal.const';
|
import { NewConnectionType, newConnectionTypeKey } from '../../types/terminal.const';
|
||||||
import useLoading from '@/hooks/loading';
|
|
||||||
import { useDictStore, useTerminalStore } from '@/store';
|
import { useDictStore, useTerminalStore } from '@/store';
|
||||||
import { PreferenceItem } from '@/store/modules/terminal';
|
import { PreferenceItem } from '@/store/modules/terminal';
|
||||||
import { dataColor } from '@/utils';
|
import { dataColor } from '@/utils';
|
||||||
import { tagColor } from '@/views/asset/host-list/types/const';
|
import { tagColor } from '@/views/asset/host-list/types/const';
|
||||||
import HostsView from './hosts-view.vue';
|
import HostsView from './hosts-view.vue';
|
||||||
|
|
||||||
const { loading, setLoading } = useLoading();
|
|
||||||
const { toRadioOptions } = useDictStore();
|
const { toRadioOptions } = useDictStore();
|
||||||
const { preference, updateTerminalPreference, hosts, loadHosts } = useTerminalStore();
|
const { preference, updateTerminalPreference, hosts } = useTerminalStore();
|
||||||
|
|
||||||
const newConnectionType = ref(preference.newConnectionType || NewConnectionType.GROUP);
|
const newConnectionType = ref(preference.newConnectionType || NewConnectionType.GROUP);
|
||||||
const filterValue = ref('');
|
const filterValue = ref('');
|
||||||
@@ -123,21 +113,8 @@
|
|||||||
}).forEach(s => filterOptions.value.push(s));
|
}).forEach(s => filterOptions.value.push(s));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载主机信息
|
// 初始化过滤器项
|
||||||
const initHosts = async () => {
|
onBeforeMount(initFilterOptions);
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
// 加载主机信息
|
|
||||||
await loadHosts();
|
|
||||||
// 初始化过滤项
|
|
||||||
initFilterOptions();
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 加载主机信息
|
|
||||||
onBeforeMount(initHosts);
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -155,10 +132,6 @@
|
|||||||
.body-container {
|
.body-container {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.hosts-skeleton {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.host-view-container {
|
.host-view-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 240px);
|
height: calc(100vh - 240px);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ export default class TerminalTabManager implements ITerminalTabManager {
|
|||||||
public items: Array<TerminalTabItem>;
|
public items: Array<TerminalTabItem>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.active = InnerTabs.NEW_CONNECTION.key;
|
// fixme
|
||||||
|
// this.active = InnerTabs.NEW_CONNECTION.key;
|
||||||
|
this.active = undefined as unknown as string;
|
||||||
this.items = [InnerTabs.NEW_CONNECTION];
|
this.items = [InnerTabs.NEW_CONNECTION];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ export default class TerminalTabManager implements ITerminalTabManager {
|
|||||||
if (key === this.active && this.items.length !== 0) {
|
if (key === this.active && this.items.length !== 0) {
|
||||||
// 切换为前一个 tab
|
// 切换为前一个 tab
|
||||||
this.active = this.items[Math.max(tabIndex - 1, 0)].key;
|
this.active = this.items[Math.max(tabIndex - 1, 0)].key;
|
||||||
|
} else {
|
||||||
|
this.active = undefined as unknown as string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<div class="host-layout-content">
|
<div class="host-layout-content">
|
||||||
<terminal-content />
|
<!-- 主机加载中骨架 -->
|
||||||
|
<loading-skeleton v-if="contentLoading" />
|
||||||
|
<!-- 终端内容区域 -->
|
||||||
|
<terminal-content v-else />
|
||||||
</div>
|
</div>
|
||||||
<!-- 右侧操作栏 -->
|
<!-- 右侧操作栏 -->
|
||||||
<div class="host-layout-right">
|
<div class="host-layout-right">
|
||||||
@@ -36,12 +39,15 @@
|
|||||||
import TerminalLeftSidebar from './components/layout/terminal-left-sidebar.vue';
|
import TerminalLeftSidebar from './components/layout/terminal-left-sidebar.vue';
|
||||||
import TerminalRightSidebar from './components/layout/terminal-right-sidebar.vue';
|
import TerminalRightSidebar from './components/layout/terminal-right-sidebar.vue';
|
||||||
import TerminalContent from './components/layout/terminal-content.vue';
|
import TerminalContent from './components/layout/terminal-content.vue';
|
||||||
|
import LoadingSkeleton from './components/layout/loading-skeleton.vue';
|
||||||
import './assets/styles/layout.less';
|
import './assets/styles/layout.less';
|
||||||
import 'xterm/css/xterm.css';
|
import 'xterm/css/xterm.css';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
|
||||||
const terminalStore = useTerminalStore();
|
const terminalStore = useTerminalStore();
|
||||||
const dictStore = useDictStore();
|
const dictStore = useDictStore();
|
||||||
const cacheStore = useCacheStore();
|
const cacheStore = useCacheStore();
|
||||||
|
const { loading: contentLoading, setLoading: setContentLoading } = useLoading(true);
|
||||||
|
|
||||||
const originTitle = document.title;
|
const originTitle = document.title;
|
||||||
const render = ref(false);
|
const render = ref(false);
|
||||||
@@ -66,6 +72,16 @@
|
|||||||
await dictStore.loadKeys([...dictKeys]);
|
await dictStore.loadKeys([...dictKeys]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 加载主机信息
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
await terminalStore.loadHosts();
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
setContentLoading(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 注册关闭视口事件
|
// 注册关闭视口事件
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// FIXME 开发阶段
|
// FIXME 开发阶段
|
||||||
|
|||||||
Reference in New Issue
Block a user