refactor: 修改终端布局.
This commit is contained in:
@@ -3,8 +3,11 @@ import { Message } from '@arco-design/web-vue';
|
|||||||
|
|
||||||
export default function useCopy() {
|
export default function useCopy() {
|
||||||
const { isSupported, copy: c, text, copied } = useClipboard();
|
const { isSupported, copy: c, text, copied } = useClipboard();
|
||||||
const copy = async (value: string, tips = `${value} 已复制`) => {
|
const copy = async (value: string | undefined, tips = `${value} 已复制`) => {
|
||||||
try {
|
try {
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await c(value);
|
await c(value);
|
||||||
if (tips) {
|
if (tips) {
|
||||||
Message.success(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 {
|
.terminal-setting-container {
|
||||||
padding: 32px 16px 16px 16px;
|
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>
|
<script lang="ts" setup>
|
||||||
import type { SidebarAction } from '../../types/terminal.const';
|
import type { SidebarAction } from '../../types/terminal.const';
|
||||||
import IconActions from './icon-actions.vue';
|
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 emits = defineEmits(['openSnippet', 'openSftp', 'openTransfer', 'screenshot']);
|
||||||
|
|
||||||
const terminalStore = useTerminalStore();
|
|
||||||
|
|
||||||
// 顶部操作
|
// 顶部操作
|
||||||
const topActions = computed<Array<SidebarAction>>(() => [
|
const topActions = [
|
||||||
{
|
{
|
||||||
icon: 'icon-code-block',
|
icon: 'icon-code-block',
|
||||||
content: '打开命令片段',
|
content: '打开命令片段',
|
||||||
@@ -48,12 +43,7 @@
|
|||||||
},
|
},
|
||||||
click: () => emits('openTransfer')
|
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> = [
|
const bottomActions: Array<SidebarAction> = [
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
:max-length="32"
|
:max-length="32"
|
||||||
:disabled="item.loading"
|
:disabled="item.loading"
|
||||||
size="mini"
|
size="mini"
|
||||||
:placeholder="`${item.name} (${item.code})`"
|
:placeholder="item.name"
|
||||||
@blur="saveAlias(item)"
|
@blur="saveAlias(item)"
|
||||||
@pressEnter="saveAlias(item)"
|
@pressEnter="saveAlias(item)"
|
||||||
@change="saveAlias(item)">
|
@change="saveAlias(item)">
|
||||||
@@ -215,10 +215,20 @@
|
|||||||
|
|
||||||
// 打开终端
|
// 打开终端
|
||||||
const openTerminal = (record: HostQueryResponse) => {
|
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({
|
tabManager.openTab({
|
||||||
type: TabType.TERMINAL,
|
type: TabType.TERMINAL,
|
||||||
key: nextSessionId(),
|
key: nextSessionId(),
|
||||||
title: record.alias || (`${record.name} ${record.address}`),
|
seq: nextSeq,
|
||||||
|
title: `(${nextSeq}) ${record.alias || record.name}`,
|
||||||
hostId: record.id,
|
hostId: record.id,
|
||||||
address: record.address
|
address: record.address
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="terminal-container">
|
<div class="terminal-container">
|
||||||
<!-- 头部 -->
|
<!-- 头部 -->
|
||||||
<div class="terminal-header">
|
<div class="terminal-header"
|
||||||
终端 {{ tab.key }} {{ tab.title }}
|
: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>
|
||||||
<!-- 终端 -->
|
<!-- 终端 -->
|
||||||
<div class="terminal-wrapper">
|
<div class="terminal-wrapper"
|
||||||
|
:style="{
|
||||||
|
background: preference.themeSchema.background
|
||||||
|
}">
|
||||||
<div class="terminal-inst" ref="terminalRef" />
|
<div class="terminal-inst" ref="terminalRef" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,22 +45,61 @@
|
|||||||
import type { TerminalTabItem } from '../../types/terminal.type';
|
import type { TerminalTabItem } from '../../types/terminal.type';
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
import { useTerminalStore } from '@/store';
|
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<{
|
const props = defineProps<{
|
||||||
tab: TerminalTabItem
|
tab: TerminalTabItem
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { sessionManager } = useTerminalStore();
|
const { copy } = useCopy();
|
||||||
|
const { preference, sessionManager } = useTerminalStore();
|
||||||
|
|
||||||
const terminalRef = ref();
|
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 () => {
|
onMounted(async () => {
|
||||||
// 创建终端处理器
|
// 创建终端处理器
|
||||||
sessionManager.openSession(props.tab, terminalRef.value);
|
sessionManager.openSession(props.tab, terminalRef.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 关闭回话
|
// 会话
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
sessionManager.closeSession(props.tab.key);
|
sessionManager.closeSession(props.tab.key);
|
||||||
});
|
});
|
||||||
@@ -44,7 +107,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@terminal-header-height: 30px;
|
@terminal-header-height: 32px;
|
||||||
|
|
||||||
.terminal-container {
|
.terminal-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - var(--header-height));
|
height: calc(100vh - var(--header-height));
|
||||||
@@ -54,16 +118,54 @@
|
|||||||
.terminal-header {
|
.terminal-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: @terminal-header-height;
|
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 {
|
.terminal-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - @terminal-header-height);
|
height: calc(100% - @terminal-header-height);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
padding: 6px 0 0 6px;
|
||||||
|
|
||||||
|
.terminal-inst {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-inst {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user