feat: 终端布局.
This commit is contained in:
@@ -1,3 +1,25 @@
|
||||
// 亮色主题配色常量
|
||||
body[terminal-theme='light'] {
|
||||
--color-bg-header: #232323;
|
||||
--color-bg-sidebar: #F2F3F5;
|
||||
--color-bg-content: #FEFEFE;
|
||||
--color-sidebar-icon: #737070;
|
||||
--color-sidebar-icon-bg: #D7D8DB;
|
||||
--color-sidebar-tooltip-text: rgba(255, 255, 255, .9);
|
||||
--color-sidebar-tooltip-bg: rgb(29, 33, 41);
|
||||
}
|
||||
|
||||
// 暗色主题配色常量
|
||||
body[terminal-theme='dark'] {
|
||||
--color-bg-header: #232323;
|
||||
--color-bg-sidebar: #2C2E31;
|
||||
--color-bg-content: #1A1B1F;
|
||||
--color-sidebar-icon: #C3C8CE;
|
||||
--color-sidebar-icon-bg: #43444C;
|
||||
--color-sidebar-tooltip-text: rgba(255, 255, 255, .9);
|
||||
--color-sidebar-tooltip-bg: var(--color-sidebar-icon-bg);
|
||||
}
|
||||
|
||||
// 布局常量
|
||||
.host-layout {
|
||||
--header-height: 44px;
|
||||
@@ -5,42 +27,17 @@
|
||||
--sidebar-icon-wrapper-size: var(--header-height);
|
||||
--sidebar-icon-size: 32px;
|
||||
--sidebar-icon-font-size: 22px;
|
||||
}
|
||||
|
||||
// 亮色主题配色常量
|
||||
body[terminal-theme='light'] {
|
||||
--color-bg-header: #292B31;
|
||||
--color-bg-sidebar: #F2F3F5;
|
||||
--color-bg-content: #FEFEFE;
|
||||
--color-sidebar-icon: #737070;
|
||||
--color-sidebar-icon-bg: #D7D8DB;
|
||||
--color-text-white: rgba(255, 255, 255, .9);
|
||||
--color-text-black: rgba(0, 0, 0, .9);
|
||||
--color-sidebar-tooltip-text: var(--color-text-white);
|
||||
--color-sidebar-tooltip-bg: rgb(var(--gray-10));
|
||||
--color-host-tabs-bg: var(--color-bg-header);
|
||||
--color-host-tabs-active-bg: var(--color-bg-content);
|
||||
--color-host-tabs-text: rgba(255, 255, 255, .6);
|
||||
--color-host-tabs-hover-text: rgba(255, 255, 255, .8);
|
||||
--color-host-tabs-active-text: var(--color-text-black);
|
||||
}
|
||||
|
||||
// 暗色主题配色常量
|
||||
body[terminal-theme='dark'] {
|
||||
--color-bg-header: #2C2E31;
|
||||
--color-bg-sidebar: #2C2E31;
|
||||
--color-bg-content: #1A1B1F;
|
||||
--color-sidebar-icon: #C3C8CE;
|
||||
--color-sidebar-icon-bg: #43444C;
|
||||
--color-text-white: rgba(255, 255, 255, .9);
|
||||
--color-text-black: rgba(0, 0, 0, .9);
|
||||
--color-sidebar-tooltip-text: var(--color-text-white);
|
||||
--color-sidebar-tooltip-bg: var(--color-sidebar-icon-bg);
|
||||
--color-host-tabs-bg: var(--color-bg-header);
|
||||
--color-host-tabs-active-bg: var(--color-bg-content);
|
||||
--color-host-tabs-text: rgba(255, 255, 255, .6);
|
||||
--color-host-tabs-hover-text: rgba(255, 255, 255, .8);
|
||||
--color-host-tabs-active-text: rgba(255, 255, 255, .9);
|
||||
--color-bg-header-icon-1: #434343;
|
||||
--color-header-tabs-sp: #4B4B4B;
|
||||
--color-header-tabs-bg: var(--color-bg-header);
|
||||
--color-header-tabs-bg-hover: #434343;
|
||||
--color-header-text-1: rgba(255, 255, 255, .9);
|
||||
--color-header-text-2: rgba(255, 255, 255, .75);
|
||||
--color-gradient-start: rgba(46, 46, 46, 1);
|
||||
--color-gradient-end: rgba(46, 46, 46, 0);
|
||||
--color-gradient-hover-start: rgba(88, 88, 88, 1);
|
||||
--color-gradient-hover-end: rgba(88, 88, 88, 0);
|
||||
}
|
||||
|
||||
// 侧栏图标 wrapper
|
||||
@@ -71,128 +68,13 @@ body[terminal-theme='dark'] {
|
||||
}
|
||||
}
|
||||
|
||||
// 侧栏 tooltip 内容
|
||||
.terminal-sidebar-tooltip-content {
|
||||
// tooltip 内容
|
||||
.terminal-tooltip-content {
|
||||
color: var(--color-sidebar-tooltip-text);
|
||||
background: var(--color-sidebar-tooltip-bg);
|
||||
}
|
||||
|
||||
// 侧栏 tooltip 箭头
|
||||
.terminal-sidebar-tooltip-arrow {
|
||||
// tooltip 箭头
|
||||
.terminal-tooltip-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.host-layout.light {
|
||||
--color-white: #FFFFFF;
|
||||
--color-black: #000000;
|
||||
--color-border: rgb(var(--gray-3));
|
||||
--color-bg-popup: var(--color-bg-5);
|
||||
--color-bg-1: #FFFFFF;
|
||||
--color-bg-2: #FFFFFF;
|
||||
--color-bg-3: #FFFFFF;
|
||||
--color-bg-4: #FFFFFF;
|
||||
--color-bg-5: #FFFFFF;
|
||||
--color-bg-white: #FFFFFF;
|
||||
--color-neutral-1: rgb(var(--gray-1));
|
||||
--color-neutral-2: rgb(var(--gray-2));
|
||||
--color-neutral-3: rgb(var(--gray-3));
|
||||
--color-neutral-4: rgb(var(--gray-4));
|
||||
--color-neutral-5: rgb(var(--gray-5));
|
||||
--color-neutral-6: rgb(var(--gray-6));
|
||||
--color-neutral-7: rgb(var(--gray-7));
|
||||
--color-neutral-8: rgb(var(--gray-8));
|
||||
--color-neutral-9: rgb(var(--gray-9));
|
||||
--color-neutral-10: rgb(var(--gray-10));
|
||||
--color-text-1: var(--color-neutral-10);
|
||||
--color-text-2: var(--color-neutral-8);
|
||||
--color-text-3: var(--color-neutral-6);
|
||||
--color-text-4: var(--color-neutral-4);
|
||||
--color-border-1: var(--color-neutral-2);
|
||||
--color-border-2: var(--color-neutral-3);
|
||||
--color-border-3: var(--color-neutral-4);
|
||||
--color-border-4: var(--color-neutral-6);
|
||||
--color-fill-1: var(--color-neutral-1);
|
||||
--color-fill-2: var(--color-neutral-2);
|
||||
--color-fill-3: var(--color-neutral-3);
|
||||
--color-fill-4: var(--color-neutral-4);
|
||||
--color-primary-light-1: rgb(var(--primary-1));
|
||||
--color-primary-light-2: rgb(var(--primary-2));
|
||||
--color-primary-light-3: rgb(var(--primary-3));
|
||||
--color-primary-light-4: rgb(var(--primary-4));
|
||||
--color-link-light-1: rgb(var(--link-1));
|
||||
--color-link-light-2: rgb(var(--link-2));
|
||||
--color-link-light-3: rgb(var(--link-3));
|
||||
--color-link-light-4: rgb(var(--link-4));
|
||||
--color-secondary: var(--color-neutral-2);
|
||||
--color-secondary-hover: var(--color-neutral-3);
|
||||
--color-secondary-active: var(--color-neutral-4);
|
||||
--color-secondary-disabled: var(--color-neutral-1);
|
||||
--color-danger-light-1: rgb(var(--danger-1));
|
||||
--color-danger-light-2: rgb(var(--danger-2));
|
||||
--color-danger-light-3: rgb(var(--danger-3));
|
||||
--color-danger-light-4: rgb(var(--danger-4));
|
||||
--color-success-light-1: rgb(var(--success-1));
|
||||
--color-success-light-2: rgb(var(--success-2));
|
||||
--color-success-light-3: rgb(var(--success-3));
|
||||
--color-success-light-4: rgb(var(--success-4));
|
||||
--color-warning-light-1: rgb(var(--warning-1));
|
||||
--color-warning-light-2: rgb(var(--warning-2));
|
||||
--color-warning-light-3: rgb(var(--warning-3));
|
||||
--color-warning-light-4: rgb(var(--warning-4));
|
||||
--color-sidebar-tooltip-bg: rgb(var(--gray-10));
|
||||
--color-spin-layer-bg: rgba(255, 255, 255, 0.6);
|
||||
--color-menu-dark-bg: #232324;
|
||||
--color-menu-light-bg: #FFFFFF;
|
||||
--color-menu-dark-hover: rgba(255, 255, 255, 0.04);
|
||||
--color-mask-bg: rgba(29, 33, 41, 0.6);
|
||||
}
|
||||
|
||||
.host-layout.dark {
|
||||
--color-white: rgba(255, 255, 255, 0.9);
|
||||
--color-black: #000000;
|
||||
--color-border: #333335;
|
||||
--color-bg-1: #17171A;
|
||||
--color-bg-2: #232324;
|
||||
--color-bg-3: #2A2A2B;
|
||||
--color-bg-4: #313132;
|
||||
--color-bg-5: #373739;
|
||||
--color-bg-white: #F6F6F6;
|
||||
--color-text-1: rgba(255, 255, 255, 0.9);
|
||||
--color-text-2: rgba(255, 255, 255, 0.7);
|
||||
--color-text-3: rgba(255, 255, 255, 0.5);
|
||||
--color-text-4: rgba(255, 255, 255, 0.3);
|
||||
--color-fill-1: rgba(255, 255, 255, 0.04);
|
||||
--color-fill-2: rgba(255, 255, 255, 0.08);
|
||||
--color-fill-3: rgba(255, 255, 255, 0.12);
|
||||
--color-fill-4: rgba(255, 255, 255, 0.16);
|
||||
--color-primary-light-1: rgba(var(--primary-6), 0.2);
|
||||
--color-primary-light-2: rgba(var(--primary-6), 0.35);
|
||||
--color-primary-light-3: rgba(var(--primary-6), 0.5);
|
||||
--color-primary-light-4: rgba(var(--primary-6), 0.65);
|
||||
--color-secondary: rgba(var(--gray-9), 0.08);
|
||||
--color-secondary-hover: rgba(var(--gray-8), 0.16);
|
||||
--color-secondary-active: rgba(var(--gray-7), 0.24);
|
||||
--color-secondary-disabled: rgba(var(--gray-9), 0.08);
|
||||
--color-danger-light-1: rgba(var(--danger-6), 0.2);
|
||||
--color-danger-light-2: rgba(var(--danger-6), 0.35);
|
||||
--color-danger-light-3: rgba(var(--danger-6), 0.5);
|
||||
--color-danger-light-4: rgba(var(--danger-6), 0.65);
|
||||
--color-success-light-1: rgb(var(--success-6), 0.2);
|
||||
--color-success-light-2: rgb(var(--success-6), 0.35);
|
||||
--color-success-light-3: rgb(var(--success-6), 0.5);
|
||||
--color-success-light-4: rgb(var(--success-6), 0.65);
|
||||
--color-warning-light-1: rgb(var(--warning-6), 0.2);
|
||||
--color-warning-light-2: rgb(var(--warning-6), 0.35);
|
||||
--color-warning-light-3: rgb(var(--warning-6), 0.5);
|
||||
--color-warning-light-4: rgb(var(--warning-6), 0.65);
|
||||
--color-link-light-1: rgb(var(--link-6), 0.2);
|
||||
--color-link-light-2: rgb(var(--link-6), 0.35);
|
||||
--color-link-light-3: rgb(var(--link-6), 0.5);
|
||||
--color-link-light-4: rgb(var(--link-6), 0.65);
|
||||
--color-sidebar-tooltip-bg: #373739;
|
||||
--color-spin-layer-bg: rgba(51, 51, 51, 0.6);
|
||||
--color-menu-dark-bg: #232324;
|
||||
--color-menu-light-bg: #232324;
|
||||
--color-menu-dark-hover: var(--color-fill-2);
|
||||
--color-mask-bg: rgba(23, 23, 26, 0.6);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-tooltip v-for="(action, index) in actions"
|
||||
:key="index"
|
||||
:position="position as any"
|
||||
:mini="true"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-arrow"
|
||||
:content="action.content">
|
||||
<div class="terminal-sidebar-icon-wrapper"
|
||||
v-if="action.visible !== false"
|
||||
:style="action?.style">
|
||||
<div class="terminal-sidebar-icon"
|
||||
:class="iconClass"
|
||||
@click="action.click">
|
||||
<component :is="action.icon" />
|
||||
</div>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'icon-actions'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { SidebarAction } from '../../types/terminal.type';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
defineProps({
|
||||
actions: Array as PropType<Array<SidebarAction>>,
|
||||
position: String,
|
||||
iconClass: String,
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
@@ -9,20 +9,23 @@
|
||||
<slot />
|
||||
</div>
|
||||
<!-- 右侧操作 -->
|
||||
<div class="terminal-header-right-actions">
|
||||
<div class="terminal-header-right">
|
||||
<!-- 分享用户 -->
|
||||
<a-avatar-group v-if="false"
|
||||
class="terminal-header-right-avatar-group"
|
||||
:size="28"
|
||||
:max-count="4"
|
||||
:max-style="{background: '#168CFF'}">
|
||||
<a-avatar v-for="i in 8" :key="i"
|
||||
:style="{background: '#168CFF'}">
|
||||
{{ i }}
|
||||
</a-avatar>
|
||||
</a-avatar-group>
|
||||
<!-- 操作按钮 -->
|
||||
<a-tooltip position="left"
|
||||
:mini="true"
|
||||
content-class="terminal-sidebar-tooltip-content"
|
||||
arrow-class="terminal-sidebar-tooltip-arrow"
|
||||
:content="isFullscreen ? '点击退出全屏模式' : '点击切换全屏模式'">
|
||||
<div class="terminal-sidebar-icon-wrapper">
|
||||
<div class="terminal-sidebar-icon" @click="toggleFullScreen">
|
||||
<icon-fullscreen-exit v-if="isFullscreen" />
|
||||
<icon-fullscreen v-else />
|
||||
</div>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<icon-actions class="terminal-header-right-actions"
|
||||
:actions="actions"
|
||||
position="br"
|
||||
icon-class="terminal-header-icon" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -34,21 +37,47 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { SidebarAction } from '../../types/terminal.type';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import { computed } from 'vue';
|
||||
import IconActions from '@/views/host-ops/terminal/components/layout/icon-actions.vue';
|
||||
|
||||
const { isFullscreen, toggle: toggleFullScreen } = useFullscreen();
|
||||
const emits = defineEmits(['split', 'share']);
|
||||
|
||||
// 顶部操作
|
||||
const actions = computed<Array<SidebarAction>>(() => [
|
||||
{
|
||||
icon: 'icon-interaction',
|
||||
content: '分屏',
|
||||
visible: false,
|
||||
click: () => emits('split')
|
||||
},
|
||||
{
|
||||
icon: 'icon-share-alt',
|
||||
content: '分享链接',
|
||||
visible: false,
|
||||
click: () => emits('share')
|
||||
},
|
||||
{
|
||||
icon: isFullscreen.value ? 'icon-fullscreen-exit' : 'icon-fullscreen',
|
||||
content: isFullscreen.value ? '点击退出全屏模式' : '点击切换全屏模式',
|
||||
click: () => toggleFullScreen()
|
||||
},
|
||||
]);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.terminal-header {
|
||||
--logo-width: 150px;
|
||||
--right-action-width: calc(var(--header-height) * 2);
|
||||
--right-avatar-width: calc(28px * 5 - 7px * 4);
|
||||
--right-action-width: calc(var(--header-height) * 3);
|
||||
}
|
||||
|
||||
.terminal-header {
|
||||
height: 100%;
|
||||
color: var(--color-text-white);
|
||||
color: var(--color-header-text-1);
|
||||
display: flex;
|
||||
user-select: none;
|
||||
|
||||
@@ -66,14 +95,35 @@
|
||||
}
|
||||
|
||||
&-tabs {
|
||||
width: calc(100% - var(--logo-width) - var(--right-action-width));
|
||||
width: calc(100% - var(--logo-width) - var(--right-avatar-width) - var(--right-action-width));
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-right-actions {
|
||||
width: var(--right-action-width);
|
||||
&-right {
|
||||
width: calc(var(--right-avatar-width) + var(--right-action-width));
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
&-avatar-group {
|
||||
width: var(--right-avatar-width);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
&-actions {
|
||||
width: var(--right-action-width);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
&-icon {
|
||||
color: var(--color-header-text-1);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-bg-header-icon-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,26 +133,22 @@
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-nav-tab) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-nav-ink) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-tab-close-btn) {
|
||||
margin-left: -12px;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-text-black);
|
||||
&-tab {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-nav-button .arco-icon-hover:hover) {
|
||||
color: var(--color-text-black);
|
||||
&-ink {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-button .arco-icon-hover:hover {
|
||||
color: var(--color-header-text-1);
|
||||
|
||||
&::before {
|
||||
background: var(--color-bg-header-icon-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-nav-type-line .arco-tabs-tab:hover .arco-tabs-tab-title::before) {
|
||||
@@ -112,33 +158,85 @@
|
||||
:deep(.arco-tabs-tab) {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 8px 12px;
|
||||
color: var(--color-host-tabs-text);
|
||||
background: var(--color-host-tabs-bg);
|
||||
padding: 0;
|
||||
color: var(--color-header-text-2);
|
||||
background: var(--color-header-tabs-bg);
|
||||
position: relative;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-left: 1px solid var(--color-header-tabs-sp);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-host-tabs-hover-text);
|
||||
color: var(--color-header-text-1);
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 54px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&:hover::after {
|
||||
background: linear-gradient(270deg, var(--color-gradient-start) 45%, var(--color-gradient-end) 120%);
|
||||
}
|
||||
|
||||
.arco-tabs-tab-title {
|
||||
padding: 0 16px 0 0;
|
||||
background: var(--color-host-tabs-bg);
|
||||
z-index: 100;
|
||||
padding: 11px 16px;
|
||||
background: var(--color-header-tabs-bg);
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .arco-tabs-tab-close-btn {
|
||||
display: unset;
|
||||
}
|
||||
|
||||
&-close-btn {
|
||||
margin: 0 8px 0 0;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
z-index: 4;
|
||||
display: none;
|
||||
color: var(--color-header-text-1);
|
||||
|
||||
&:hover {
|
||||
z-index: 0;
|
||||
transition: .2s;
|
||||
background: var(--color-bg-header-icon-1);
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-tabs-tab-active) {
|
||||
background: var(--color-host-tabs-active-bg);
|
||||
color: var(--color-host-tabs-active-text) !important;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||
background: var(--color-header-tabs-bg-hover);
|
||||
color: var(--color-header-text-1) !important;
|
||||
|
||||
.arco-tabs-tab-title {
|
||||
background: var(--color-host-tabs-active-bg);
|
||||
background: var(--color-header-tabs-bg-hover);
|
||||
}
|
||||
|
||||
&:hover::after {
|
||||
background: linear-gradient(270deg, var(--color-gradient-hover-start) 45%, var(--color-gradient-hover-end) 120%);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
<template>
|
||||
<div class="terminal-left-sidebar">
|
||||
<!-- 操作按钮 -->
|
||||
<a-tooltip v-for="(action, index) in actions"
|
||||
:key="index"
|
||||
position="right"
|
||||
:mini="true"
|
||||
content-class="terminal-sidebar-tooltip-content"
|
||||
arrow-class="terminal-sidebar-tooltip-arrow"
|
||||
:content="action.content">
|
||||
<div class="terminal-sidebar-icon-wrapper" :style="action?.style">
|
||||
<div class="terminal-sidebar-icon" @click="action.event">
|
||||
<component :is="action.icon" />
|
||||
</div>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<!-- 顶部操作按钮 -->
|
||||
<icon-actions class="top-actions"
|
||||
:actions="topActions"
|
||||
position="left" />
|
||||
<!-- 底部操作按钮 -->
|
||||
<icon-actions class="bottom-actions"
|
||||
:actions="bottomActions"
|
||||
position="right" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,21 +19,41 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SidebarAction } from '../../types/terminal.type';
|
||||
import IconActions from './icon-actions.vue';
|
||||
|
||||
const emits = defineEmits(['openAdd', 'openSetting']);
|
||||
const emits = defineEmits(['openAdd', 'copyAddress', 'openShortcutSetting', 'openViewSetting', 'openThemeSetting']);
|
||||
|
||||
// 操作
|
||||
const actions: Array<SidebarAction> = [
|
||||
// 顶部操作
|
||||
const topActions: Array<SidebarAction> = [
|
||||
{
|
||||
icon: 'icon-plus',
|
||||
content: '新建连接',
|
||||
event: () => emits('openAdd')
|
||||
click: () => emits('openAdd')
|
||||
},
|
||||
{
|
||||
icon: 'icon-settings',
|
||||
content: '设置',
|
||||
event: () => emits('openSetting')
|
||||
}
|
||||
icon: 'icon-copy',
|
||||
content: '复制主机IP',
|
||||
click: () => emits('copyAddress')
|
||||
},
|
||||
];
|
||||
|
||||
// 底部操作
|
||||
const bottomActions: Array<SidebarAction> = [
|
||||
{
|
||||
icon: 'icon-command',
|
||||
content: '快捷键设置',
|
||||
click: () => emits('openShortcutSetting')
|
||||
},
|
||||
{
|
||||
icon: 'icon-palette',
|
||||
content: '主题设置',
|
||||
click: () => emits('openThemeSetting')
|
||||
},
|
||||
{
|
||||
icon: 'icon-tool',
|
||||
content: '显示设置',
|
||||
click: () => emits('openViewSetting')
|
||||
},
|
||||
];
|
||||
|
||||
</script>
|
||||
@@ -47,5 +61,8 @@
|
||||
<style lang="less" scoped>
|
||||
.terminal-left-sidebar {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
<template>
|
||||
<div class="terminal-right-sidebar">
|
||||
<!-- 操作按钮 -->
|
||||
<a-tooltip v-for="(action, index) in actions"
|
||||
:key="index"
|
||||
position="left"
|
||||
:mini="true"
|
||||
content-class="terminal-sidebar-tooltip-content"
|
||||
arrow-class="terminal-sidebar-tooltip-arrow"
|
||||
:content="action.content">
|
||||
<div class="terminal-sidebar-icon-wrapper" :style="action?.style">
|
||||
<div class="terminal-sidebar-icon" @click="action.event">
|
||||
<component :is="action.icon" />
|
||||
</div>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<icon-actions class="terminal-actions"
|
||||
:actions="actions"
|
||||
position="left" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,6 +15,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SidebarAction } from '../../types/terminal.type';
|
||||
import IconActions from './icon-actions.vue';
|
||||
|
||||
const emits = defineEmits(['openSnippet', 'openSftp', 'openTransfer', 'openHistory']);
|
||||
|
||||
@@ -34,13 +25,13 @@
|
||||
icon: 'icon-code-block',
|
||||
content: '打开命令片段',
|
||||
style: {},
|
||||
event: () => emits('openSnippet')
|
||||
click: () => emits('openSnippet')
|
||||
},
|
||||
{
|
||||
icon: 'icon-folder',
|
||||
content: '打开 SFTP',
|
||||
style: {},
|
||||
event: () => emits('openSftp')
|
||||
click: () => emits('openSftp')
|
||||
},
|
||||
{
|
||||
icon: 'icon-swap',
|
||||
@@ -48,12 +39,13 @@
|
||||
style: {
|
||||
transform: 'rotate(90deg)'
|
||||
},
|
||||
event: () => emits('openTransfer')
|
||||
click: () => emits('openTransfer')
|
||||
},
|
||||
{
|
||||
icon: 'icon-history',
|
||||
content: '历史命令',
|
||||
event: () => emits('openHistory')
|
||||
visible: false,
|
||||
click: () => emits('openHistory')
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
<header class="host-layout-header">
|
||||
<terminal-header>
|
||||
<!-- 主机 tabs -->
|
||||
<a-tabs :editable="true" :hide-content="true">
|
||||
<a-tabs :editable="true"
|
||||
:hide-content="true"
|
||||
@tab-click="clickTab"
|
||||
@delete="deleteTab">
|
||||
<a-tab-pane v-for="i in 30"
|
||||
:key="i"
|
||||
:title="'主机主机主机'+i+''" />
|
||||
@@ -64,6 +67,14 @@
|
||||
darkTheme.value = !darkTheme.value;
|
||||
};
|
||||
|
||||
const clickTab = (v: any) => {
|
||||
console.log('click', v);
|
||||
};
|
||||
|
||||
const deleteTab = (v: any) => {
|
||||
console.log('delete', v);
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { CSSProperties } from 'vue';
|
||||
|
||||
// Sidebar 操作类型
|
||||
// sidebar 操作类型
|
||||
export interface SidebarAction {
|
||||
icon: string,
|
||||
content: string,
|
||||
style?: CSSProperties
|
||||
event: () => void,
|
||||
icon: string;
|
||||
content: string;
|
||||
style?: CSSProperties;
|
||||
visible?: boolean;
|
||||
click: () => void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user