refactor: 修改终端布局.
This commit is contained in:
@@ -3,8 +3,11 @@ import { Message } from '@arco-design/web-vue';
|
||||
|
||||
export default function useCopy() {
|
||||
const { isSupported, copy: c, text, copied } = useClipboard();
|
||||
const copy = async (value: string, tips = `${value} 已复制`) => {
|
||||
const copy = async (value: string | undefined, tips = `${value} 已复制`) => {
|
||||
try {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
await c(value);
|
||||
if (tips) {
|
||||
Message.success(tips);
|
||||
|
||||
@@ -192,17 +192,6 @@ body[terminal-theme='dark'] .host-layout {
|
||||
}
|
||||
}
|
||||
|
||||
// tooltip 内容
|
||||
.terminal-tooltip-content {
|
||||
color: var(--color-sidebar-tooltip-text);
|
||||
background: var(--color-sidebar-tooltip-bg);
|
||||
}
|
||||
|
||||
// tooltip 箭头
|
||||
.terminal-tooltip-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// 终端设置容器
|
||||
.terminal-setting-container {
|
||||
padding: 32px 16px 16px 16px;
|
||||
@@ -246,3 +235,14 @@ body[terminal-theme='dark'] .host-layout {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tooltip 内容
|
||||
.terminal-tooltip-content {
|
||||
color: var(--color-sidebar-tooltip-text);
|
||||
background: var(--color-sidebar-tooltip-bg);
|
||||
}
|
||||
|
||||
// tooltip 箭头
|
||||
.terminal-tooltip-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -20,16 +20,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { SidebarAction } from '../../types/terminal.const';
|
||||
import IconActions from './icon-actions.vue';
|
||||
import { computed } from 'vue';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { DarkTheme } from '@/store/modules/terminal';
|
||||
|
||||
const emits = defineEmits(['openSnippet', 'openSftp', 'openTransfer', 'screenshot']);
|
||||
|
||||
const terminalStore = useTerminalStore();
|
||||
|
||||
// 顶部操作
|
||||
const topActions = computed<Array<SidebarAction>>(() => [
|
||||
const topActions = [
|
||||
{
|
||||
icon: 'icon-code-block',
|
||||
content: '打开命令片段',
|
||||
@@ -48,12 +43,7 @@
|
||||
},
|
||||
click: () => emits('openTransfer')
|
||||
},
|
||||
{
|
||||
icon: terminalStore.isDarkTheme ? 'icon-sun-fill' : 'icon-moon-fill',
|
||||
content: terminalStore.isDarkTheme ? '点击切换为亮色模式' : '点击切换为暗色模式',
|
||||
click: () => terminalStore.changeDarkTheme(terminalStore.isDarkTheme ? DarkTheme.LIGHT : DarkTheme.DARK)
|
||||
},
|
||||
]);
|
||||
];
|
||||
|
||||
// 底部操作
|
||||
const bottomActions: Array<SidebarAction> = [
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
:max-length="32"
|
||||
:disabled="item.loading"
|
||||
size="mini"
|
||||
:placeholder="`${item.name} (${item.code})`"
|
||||
:placeholder="item.name"
|
||||
@blur="saveAlias(item)"
|
||||
@pressEnter="saveAlias(item)"
|
||||
@change="saveAlias(item)">
|
||||
@@ -215,10 +215,20 @@
|
||||
|
||||
// 打开终端
|
||||
const openTerminal = (record: HostQueryResponse) => {
|
||||
// 获取 seq
|
||||
const tabSeqArr = tabManager.items
|
||||
.map(s => s.seq)
|
||||
.filter(Boolean)
|
||||
.map(Number);
|
||||
const nextSeq = tabSeqArr.length
|
||||
? Math.max(...tabSeqArr) + 1
|
||||
: 1;
|
||||
// 打开 tab
|
||||
tabManager.openTab({
|
||||
type: TabType.TERMINAL,
|
||||
key: nextSessionId(),
|
||||
title: record.alias || (`${record.name} ${record.address}`),
|
||||
seq: nextSeq,
|
||||
title: `(${nextSeq}) ${record.alias || record.name}`,
|
||||
hostId: record.id,
|
||||
address: record.address
|
||||
});
|
||||
|
||||
@@ -1,11 +1,35 @@
|
||||
<template>
|
||||
<div class="terminal-container">
|
||||
<!-- 头部 -->
|
||||
<div class="terminal-header">
|
||||
终端 {{ tab.key }} {{ tab.title }}
|
||||
<div class="terminal-header"
|
||||
:style="{
|
||||
background: adjustColor(preference.themeSchema.background, -10)
|
||||
}">
|
||||
<!-- 左侧操作 -->
|
||||
<div class="terminal-header-left">
|
||||
<!-- 主机地址 -->
|
||||
<span class="address-wrapper">
|
||||
{{ tab.address }}
|
||||
<span class="address-copy copy-left" title="复制" @click="copy(tab.address as string)">
|
||||
<icon-copy />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- 右侧操作 -->
|
||||
<div class="terminal-header-right">
|
||||
<icon-actions class="bottom-actions"
|
||||
:actions="bottomActions"
|
||||
position="right" />
|
||||
<span @click="pl">
|
||||
粘贴
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 终端 -->
|
||||
<div class="terminal-wrapper">
|
||||
<div class="terminal-wrapper"
|
||||
:style="{
|
||||
background: preference.themeSchema.background
|
||||
}">
|
||||
<div class="terminal-inst" ref="terminalRef" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -21,22 +45,61 @@
|
||||
import type { TerminalTabItem } from '../../types/terminal.type';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import useCopy from '@/hooks/copy';
|
||||
import IconActions from '@/views/host/terminal/components/layout/icon-actions.vue';
|
||||
import { SidebarAction } from '@/views/host/terminal/types/terminal.const';
|
||||
|
||||
const props = defineProps<{
|
||||
tab: TerminalTabItem
|
||||
}>();
|
||||
|
||||
const { sessionManager } = useTerminalStore();
|
||||
const { copy } = useCopy();
|
||||
const { preference, sessionManager } = useTerminalStore();
|
||||
|
||||
const terminalRef = ref();
|
||||
|
||||
// 初始化回话
|
||||
// 底部操作
|
||||
const bottomActions: Array<SidebarAction> = [
|
||||
{
|
||||
icon: 'icon-command',
|
||||
content: '快捷键设置',
|
||||
click: () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: 'icon-palette',
|
||||
content: '外观设置',
|
||||
click: () => {
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
// 调整颜色
|
||||
const adjustColor = (color: string, range: number) => {
|
||||
let newColor = '#';
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let c = parseInt(color.substring(i * 2 + 1, i * 2 + 3), 16);
|
||||
c += range;
|
||||
if (c < 0) {
|
||||
c = 0;
|
||||
} else if (c > 255) {
|
||||
c = 255;
|
||||
}
|
||||
newColor += c.toString(16).padStart(2, '0');
|
||||
}
|
||||
return newColor;
|
||||
};
|
||||
|
||||
const pl = () => {
|
||||
};
|
||||
|
||||
// 初始化会话
|
||||
onMounted(async () => {
|
||||
// 创建终端处理器
|
||||
sessionManager.openSession(props.tab, terminalRef.value);
|
||||
});
|
||||
|
||||
// 关闭回话
|
||||
// 会话
|
||||
onUnmounted(() => {
|
||||
sessionManager.closeSession(props.tab.key);
|
||||
});
|
||||
@@ -44,7 +107,8 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@terminal-header-height: 30px;
|
||||
@terminal-header-height: 32px;
|
||||
|
||||
.terminal-container {
|
||||
width: 100%;
|
||||
height: calc(100vh - var(--header-height));
|
||||
@@ -54,16 +118,54 @@
|
||||
.terminal-header {
|
||||
width: 100%;
|
||||
height: @terminal-header-height;
|
||||
padding: 0 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&-left, &-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&-left:hover {
|
||||
.address-copy {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.address-wrapper:before {
|
||||
content: 'IP:';
|
||||
padding-right: 4px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.address-copy {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.terminal-wrapper {
|
||||
width: 100%;
|
||||
height: calc(100% - @terminal-header-height);
|
||||
position: relative;
|
||||
padding: 6px 0 0 6px;
|
||||
|
||||
.terminal-inst {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.terminal-inst {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user