feat: 终端操作栏配置化.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { TerminalDisplaySetting, TerminalPreference, TerminalState } from './types';
|
||||
import type { TerminalActionBarSetting, TerminalDisplaySetting, TerminalPreference, TerminalState } from './types';
|
||||
import type { TerminalTheme } from '@/api/asset/host-terminal';
|
||||
import { getTerminalThemes } from '@/api/asset/host-terminal';
|
||||
import { defineStore } from 'pinia';
|
||||
@@ -15,14 +15,17 @@ export const PreferenceItem = {
|
||||
THEME: 'theme',
|
||||
// 显示设置
|
||||
DISPLAY_SETTING: 'displaySetting',
|
||||
// 操作栏设置
|
||||
ACTION_BAR_SETTING: 'actionBarSetting',
|
||||
};
|
||||
|
||||
export default defineStore('terminal', {
|
||||
state: (): TerminalState => ({
|
||||
preference: {
|
||||
newConnectionType: 'group',
|
||||
theme: {} as TerminalTheme,
|
||||
displaySetting: {} as TerminalDisplaySetting,
|
||||
theme: {} as TerminalTheme
|
||||
actionBarSetting: {} as TerminalActionBarSetting,
|
||||
},
|
||||
tabManager: new TerminalTabManager(),
|
||||
sessionManager: new TerminalSessionManager()
|
||||
|
||||
@@ -10,8 +10,9 @@ export interface TerminalState {
|
||||
// 终端配置
|
||||
export interface TerminalPreference {
|
||||
newConnectionType: string;
|
||||
displaySetting: TerminalDisplaySetting;
|
||||
theme: TerminalTheme;
|
||||
displaySetting: TerminalDisplaySetting;
|
||||
actionBarSetting: TerminalActionBarSetting;
|
||||
}
|
||||
|
||||
// 显示设置
|
||||
@@ -25,3 +26,11 @@ export interface TerminalDisplaySetting {
|
||||
cursorBlink?: boolean;
|
||||
}
|
||||
|
||||
// 操作栏设置
|
||||
export interface TerminalActionBarSetting {
|
||||
commandInput?: boolean;
|
||||
connectStatus?: boolean;
|
||||
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
|
||||
@@ -192,11 +192,14 @@ body[terminal-theme='dark'] .arco-modal-container {
|
||||
background: var(--color-sidebar-icon-bg);
|
||||
}
|
||||
|
||||
&.checked-item {
|
||||
background: var(--color-sidebar-icon-bg);
|
||||
}
|
||||
|
||||
&.disabled-item {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 终端设置容器
|
||||
@@ -239,6 +242,14 @@ body[terminal-theme='dark'] .arco-modal-container {
|
||||
|
||||
.terminal-setting-body {
|
||||
display: flex;
|
||||
|
||||
&.block-body {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--color-fill-4);
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
:content="action.content">
|
||||
<div class="terminal-sidebar-icon-wrapper" v-if="action.visible !== false">
|
||||
<div class="terminal-sidebar-icon"
|
||||
:class="[iconClass, action.disabled !== false ? '' : 'disabled-item']"
|
||||
:class="[
|
||||
iconClass,
|
||||
action.disabled !== false ? '' : 'disabled-item',
|
||||
action.checked === true ? 'checked-item' : '',
|
||||
]"
|
||||
@click="action.disabled !== false ? action.click() : false">
|
||||
<component :is="action.icon" :style="action?.iconStyle" />
|
||||
</div>
|
||||
|
||||
@@ -85,12 +85,13 @@
|
||||
}
|
||||
|
||||
&-logo-text {
|
||||
height: var(--header-height);
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
font-size: 16px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&-tabs {
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="terminal-setting-block">
|
||||
<!-- 顶部 -->
|
||||
<div class="terminal-setting-subtitle-wrapper">
|
||||
<h3 class="terminal-setting-subtitle">
|
||||
操作栏设置
|
||||
</h3>
|
||||
</div>
|
||||
<!-- 提示 -->
|
||||
<a-alert class="mb16">修改后会立刻保存, 立即生效 (无需刷新页面)</a-alert>
|
||||
<!-- 内容区域 -->
|
||||
<div class="terminal-setting-body block-body setting-body">
|
||||
<a-form class="terminal-setting-form"
|
||||
:model="formModel"
|
||||
layout="vertical">
|
||||
<a-space>
|
||||
<!-- 顶部操作按钮 -->
|
||||
<a-form-item field="actions" label="顶部操作按钮">
|
||||
<icon-actions class="form-item-actions"
|
||||
:actions="actions"
|
||||
position="bottom" />
|
||||
</a-form-item>
|
||||
<!-- 命令输入框 -->
|
||||
<a-form-item field="showCommandInput" label="命令输入框">
|
||||
<a-switch v-model="formModel.commandInput"
|
||||
class="form-item-command-input"
|
||||
:default-checked="true"
|
||||
type="round" />
|
||||
</a-form-item>
|
||||
<!-- 连接状态 -->
|
||||
<a-form-item field="showStatus" label="连接状态">
|
||||
<a-switch v-model="formModel.connectStatus"
|
||||
:default-checked="true"
|
||||
type="round" />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'TerminalActionBarBlock'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { TerminalActionBarSetting } from '@/store/modules/terminal/types';
|
||||
import type { SidebarAction } from '../../types/terminal.type';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { PreferenceItem } from '@/store/modules/terminal';
|
||||
import { ActionBarItems } from '../../types/terminal.const';
|
||||
import IconActions from '../layout/icon-actions.vue';
|
||||
|
||||
const { preference, updateTerminalPreference } = useTerminalStore();
|
||||
|
||||
const formModel = ref<TerminalActionBarSetting>({ ...preference.actionBarSetting });
|
||||
|
||||
// 监听同步
|
||||
watch(formModel, (v) => {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
// 同步
|
||||
updateTerminalPreference(PreferenceItem.ACTION_BAR_SETTING, formModel.value, true);
|
||||
}, { deep: true });
|
||||
|
||||
// 右侧操作
|
||||
const actions = computed<Array<SidebarAction>>(() => {
|
||||
return ActionBarItems.map(s => {
|
||||
return {
|
||||
icon: s.icon,
|
||||
content: (formModel.value[s.item] === false ? '显示 ' : '隐藏 ') + s.content,
|
||||
checked: formModel.value[s.item] !== false,
|
||||
click: () => {
|
||||
formModel.value[s.item] = formModel.value[s.item] === false;
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.form-item-actions {
|
||||
display: flex;
|
||||
background-color: var(--color-fill-2);
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
|
||||
:deep(.terminal-sidebar-icon-wrapper) {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
:deep(.terminal-sidebar-icon) {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-actions, .form-item-command-input {
|
||||
margin-right: 48px;
|
||||
}
|
||||
|
||||
:deep(.arco-form) {
|
||||
.arco-form-item-label {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.arco-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -3,78 +3,80 @@
|
||||
<!-- 顶部 -->
|
||||
<div class="terminal-setting-subtitle-wrapper">
|
||||
<h3 class="terminal-setting-subtitle">
|
||||
显示设置
|
||||
显示偏好
|
||||
</h3>
|
||||
</div>
|
||||
<!-- 提示 -->
|
||||
<a-alert class="mb16">修改后会立刻保存, 重新打开终端后生效 (无需刷新页面)</a-alert>
|
||||
<!-- 内容区域 -->
|
||||
<div class="terminal-setting-body">
|
||||
<div class="terminal-setting-form">
|
||||
<a-form :model="formModel" layout="vertical">
|
||||
<a-space>
|
||||
<!-- 字体样式 -->
|
||||
<a-form-item field="fontFamily" label="字体样式">
|
||||
<a-select v-model="formModel.fontFamily"
|
||||
class="form-item form-item-font-family"
|
||||
placeholder="请选择字体样式"
|
||||
:options="toOptions(fontFamilyKey)"
|
||||
:allow-create="true"
|
||||
:filter-option="labelFilter">
|
||||
<template #option="{ data }">
|
||||
<span :style="{ fontFamily: data.value }">{{ data.label }}</span>
|
||||
</template>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<!-- 字体大小 -->
|
||||
<a-form-item field="fontSize" label="字体大小">
|
||||
<a-select v-model="formModel.fontSize"
|
||||
class="form-item form-item-font-size"
|
||||
placeholder="请选择字体大小"
|
||||
:options="toOptions(fontSizeKey)" />
|
||||
</a-form-item>
|
||||
<!-- 行高 -->
|
||||
<a-form-item field="lineHeight" label="行高">
|
||||
<a-input-number v-model="formModel.lineHeight"
|
||||
class="form-item form-item-line-height"
|
||||
placeholder="请输入行高"
|
||||
:precision="2"
|
||||
:min="1"
|
||||
:max="2"
|
||||
hide-button />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
<a-space>
|
||||
<!-- 普通文本字重 -->
|
||||
<a-form-item field="fontWeight" label="普通文本字重">
|
||||
<a-select v-model="formModel.fontWeight"
|
||||
class="form-item form-item-font-weight"
|
||||
placeholder="请选择字重"
|
||||
:options="toOptions(fontWeightKey)" />
|
||||
</a-form-item>
|
||||
<!-- 加粗文本字重 -->
|
||||
<a-form-item field="fontWeightBold" label="加粗文本字重">
|
||||
<a-select v-model="formModel.fontWeightBold"
|
||||
class="form-item form-item-font-bold-weight"
|
||||
placeholder="请选择字重"
|
||||
:options="toOptions(fontWeightKey)" />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
<a-space>
|
||||
<!-- 光标样式 -->
|
||||
<a-form-item field="cursorStyle" label="光标样式">
|
||||
<a-radio-group type="button"
|
||||
v-model="formModel.cursorStyle"
|
||||
class="form-item form-item-cursor-style usn"
|
||||
:options="toRadioOptions(cursorStyleKey)" />
|
||||
</a-form-item>
|
||||
<!-- 光标闪烁 -->
|
||||
<a-form-item field="cursorBlink" label="光标是否闪烁">
|
||||
<a-switch v-model="formModel.cursorBlink"
|
||||
type="round"
|
||||
class="form-item form-item-cursor-blink" />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="terminal-setting-body block-body setting-body">
|
||||
<a-form class="terminal-setting-form"
|
||||
:model="formModel"
|
||||
layout="vertical">
|
||||
<a-space>
|
||||
<!-- 字体样式 -->
|
||||
<a-form-item field="fontFamily" label="字体样式">
|
||||
<a-select v-model="formModel.fontFamily"
|
||||
class="form-item-font-family"
|
||||
placeholder="请选择字体样式"
|
||||
:options="toOptions(fontFamilyKey)"
|
||||
:allow-create="true"
|
||||
:filter-option="labelFilter">
|
||||
<template #option="{ data }">
|
||||
<span :style="{ fontFamily: data.value }">{{ data.label }}</span>
|
||||
</template>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<!-- 字体大小 -->
|
||||
<a-form-item field="fontSize" label="字体大小">
|
||||
<a-select v-model="formModel.fontSize"
|
||||
class="form-item-font-size"
|
||||
placeholder="请选择字体大小"
|
||||
:options="toOptions(fontSizeKey)" />
|
||||
</a-form-item>
|
||||
<!-- 行高 -->
|
||||
<a-form-item field="lineHeight" label="行高">
|
||||
<a-input-number v-model="formModel.lineHeight"
|
||||
class="form-item-line-height"
|
||||
placeholder="请输入行高"
|
||||
:precision="2"
|
||||
:min="1"
|
||||
:max="2"
|
||||
hide-button />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
<a-space>
|
||||
<!-- 普通文本字重 -->
|
||||
<a-form-item field="fontWeight" label="普通文本字重">
|
||||
<a-select v-model="formModel.fontWeight"
|
||||
class="form-item-font-weight"
|
||||
placeholder="请选择字重"
|
||||
:options="toOptions(fontWeightKey)" />
|
||||
</a-form-item>
|
||||
<!-- 加粗文本字重 -->
|
||||
<a-form-item field="fontWeightBold" label="加粗文本字重">
|
||||
<a-select v-model="formModel.fontWeightBold"
|
||||
class="form-item-font-bold-weight"
|
||||
placeholder="请选择字重"
|
||||
:options="toOptions(fontWeightKey)" />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
<a-space>
|
||||
<!-- 光标样式 -->
|
||||
<a-form-item field="cursorStyle" label="光标样式">
|
||||
<a-radio-group type="button"
|
||||
v-model="formModel.cursorStyle"
|
||||
class="form-item-cursor-style usn"
|
||||
:options="toRadioOptions(cursorStyleKey)" />
|
||||
</a-form-item>
|
||||
<!-- 光标闪烁 -->
|
||||
<a-form-item field="cursorBlink" label="光标是否闪烁">
|
||||
<a-switch v-model="formModel.cursorBlink"
|
||||
type="round"
|
||||
class="form-item-cursor-blink" />
|
||||
</a-form-item>
|
||||
</a-space>
|
||||
</a-form>
|
||||
<!-- 预览区域 -->
|
||||
<div class="terminal-example">
|
||||
<span class="terminal-example-label">预览效果</span>
|
||||
@@ -90,7 +92,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'TerminalFontBlock'
|
||||
name: 'TerminalDisplayBlock'
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -109,15 +111,6 @@
|
||||
const previewTerminal = ref();
|
||||
const formModel = ref<TerminalDisplaySetting>({ ...preference.displaySetting });
|
||||
|
||||
// 监听主题变化 动态修改预览样式
|
||||
watch(() => preference.theme, (v) => {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
const options = previewTerminal.value?.term?.options;
|
||||
options && (options.theme = v);
|
||||
});
|
||||
|
||||
// 监听内容变化
|
||||
watch(formModel, (v) => {
|
||||
if (!v) {
|
||||
@@ -136,7 +129,7 @@
|
||||
}
|
||||
});
|
||||
// 同步
|
||||
updateTerminalPreference(PreferenceItem.DISPLAY_SETTING, formModel.value);
|
||||
updateTerminalPreference(PreferenceItem.DISPLAY_SETTING, formModel.value, true);
|
||||
// 聚焦
|
||||
previewTerminal.value.term.focus();
|
||||
}, { deep: true });
|
||||
@@ -146,13 +139,8 @@
|
||||
<style lang="less" scoped>
|
||||
@terminal-width: 458px;
|
||||
|
||||
.terminal-setting-body {
|
||||
.setting-body {
|
||||
height: 248px;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--color-fill-4);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,21 +2,24 @@
|
||||
<div class="terminal-setting-container">
|
||||
<div class="terminal-setting-wrapper">
|
||||
<!-- 主标题 -->
|
||||
<h2 class="terminal-setting-title">外观设置</h2>
|
||||
<!-- 显示设置 -->
|
||||
<h2 class="terminal-setting-title">显示设置</h2>
|
||||
<!-- 显示偏好 -->
|
||||
<terminal-display-block />
|
||||
<!-- 顶部工具栏 -->
|
||||
<terminal-action-bar-block />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'TerminalViewSetting'
|
||||
name: 'TerminalDisplaySetting'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import TerminalDisplayBlock from './terminal-display-block.vue';
|
||||
import TerminalActionBarBlock from './terminal-action-bar-block.vue';
|
||||
|
||||
</script>
|
||||
|
||||
@@ -17,19 +17,21 @@
|
||||
</div>
|
||||
<!-- 右侧操作 -->
|
||||
<div class="terminal-header-right">
|
||||
<!-- 代码输入框 -->
|
||||
<!-- 命令输入框 -->
|
||||
<a-textarea class="command-input mr8"
|
||||
v-if="preference.actionBarSetting.commandInput !== false"
|
||||
v-model="commandInput"
|
||||
:auto-size="{ minRows: 1, maxRows: 1 }"
|
||||
placeholder="F8 发送命令"
|
||||
allow-clear
|
||||
@keyup="writeCommandInput" />
|
||||
<!-- 操作按钮 -->
|
||||
<icon-actions class="terminal-header-right-icon-actions"
|
||||
<icon-actions class="terminal-header-right-action-bar"
|
||||
:actions="rightActions"
|
||||
position="bottom" />
|
||||
<!-- 状态 -->
|
||||
<a-badge class="status-bridge"
|
||||
<!-- 连接状态 -->
|
||||
<a-badge v-if="preference.actionBarSetting.connectStatus !== false"
|
||||
class="status-bridge"
|
||||
:status="getDictValue(connectStatusKey, session ? session.status : 0, 'status')"
|
||||
:text="getDictValue(connectStatusKey, session ? session.status : 0)" />
|
||||
</div>
|
||||
@@ -59,12 +61,11 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { SidebarAction } from '../../types/terminal.type';
|
||||
import type { ITerminalSession, TerminalTabItem } from '../../types/terminal.type';
|
||||
import type { ITerminalSession, TerminalTabItem, SidebarAction } from '../../types/terminal.type';
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { useDictStore, useTerminalStore } from '@/store';
|
||||
import useCopy from '@/hooks/copy';
|
||||
import { connectStatusKey } from '../../types/terminal.const';
|
||||
import { ActionBarItems, connectStatusKey } from '../../types/terminal.const';
|
||||
import IconActions from '../layout/icon-actions.vue';
|
||||
import ShellEditorModal from '@/components/view/shell-editor/shell-editor-modal.vue';
|
||||
|
||||
@@ -74,7 +75,7 @@
|
||||
|
||||
const { copy, readText } = useCopy();
|
||||
const { getDictValue } = useDictStore();
|
||||
const { preference, sessionManager } = useTerminalStore();
|
||||
const { preference, tabManager, sessionManager } = useTerminalStore();
|
||||
|
||||
const modal = ref();
|
||||
const commandInput = ref();
|
||||
@@ -127,104 +128,80 @@
|
||||
session.value?.focus();
|
||||
};
|
||||
|
||||
// 右侧操作
|
||||
const rightActions = computed<Array<SidebarAction>>(() => [
|
||||
{
|
||||
icon: 'icon-up',
|
||||
content: '去顶部',
|
||||
click: () => {
|
||||
session.value?.toTop();
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-down',
|
||||
content: '去底部',
|
||||
click: () => {
|
||||
session.value?.toBottom();
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-expand',
|
||||
content: '全选',
|
||||
click: () => {
|
||||
session.value?.selectAll();
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-copy',
|
||||
content: '复制选中部分',
|
||||
click: () => {
|
||||
copy(session.value?.getSelection(), '已复制');
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-paste',
|
||||
content: '粘贴',
|
||||
disabled: session.value?.canWrite,
|
||||
click: async () => {
|
||||
session.value?.paste(await readText());
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-formula',
|
||||
content: 'ctrl + c',
|
||||
disabled: session.value?.canWrite,
|
||||
click: () => {
|
||||
session.value?.paste(String.fromCharCode(3));
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-play-arrow-fill',
|
||||
content: '回车',
|
||||
disabled: session.value?.canWrite,
|
||||
click: () => {
|
||||
session.value?.paste(String.fromCharCode(13));
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-code-square',
|
||||
content: '命令编辑器',
|
||||
disabled: session.value?.canWrite,
|
||||
click: () => {
|
||||
modal.value.open('', '');
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-search',
|
||||
content: '搜索',
|
||||
click: () => {
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-zoom-in',
|
||||
content: '增大字号',
|
||||
click: () => {
|
||||
if (session.value) {
|
||||
session.value.setOption('fontSize', session.value.getOption('fontSize') + 1);
|
||||
if (session.value.connected) {
|
||||
session.value.fit();
|
||||
session.value.focus();
|
||||
}
|
||||
// 操作禁用状态
|
||||
const actionsDisableStatus = computed<Record<string, boolean | undefined>>(() => {
|
||||
return {
|
||||
paste: session.value?.canWrite,
|
||||
interrupt: session.value?.canWrite,
|
||||
enter: session.value?.canWrite,
|
||||
commandEditor: session.value?.canWrite,
|
||||
disconnect: session.value?.connected,
|
||||
};
|
||||
});
|
||||
|
||||
// 操作点击逻辑
|
||||
const actionsClickHandler: Record<string, () => void> = {
|
||||
// 去顶部
|
||||
toTop: () => session.value?.toTop(),
|
||||
// 去底部
|
||||
toBottom: () => session.value?.toBottom(),
|
||||
// 全选
|
||||
checkAll: () => session.value?.selectAll(),
|
||||
// 复制选中部分
|
||||
copy: () => copy(session.value?.getSelection(), '已复制'),
|
||||
// 粘贴
|
||||
paste: async () => session.value?.paste(await readText()),
|
||||
// ctrl + c
|
||||
interrupt: () => session.value?.paste(String.fromCharCode(3)),
|
||||
// 回车
|
||||
enter: () => session.value?.paste(String.fromCharCode(13)),
|
||||
// 命令编辑器
|
||||
commandEditor: () => modal.value.open('', ''),
|
||||
// 搜索
|
||||
search: () => {
|
||||
},
|
||||
// 增大字号
|
||||
fontSizePlus: () => {
|
||||
if (session.value) {
|
||||
session.value.setOption('fontSize', session.value.getOption('fontSize') + 1);
|
||||
if (session.value.connected) {
|
||||
session.value.fit();
|
||||
session.value.focus();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-zoom-out',
|
||||
content: '减小字号',
|
||||
click: () => {
|
||||
if (session.value) {
|
||||
session.value.setOption('fontSize', session.value.getOption('fontSize') - 1);
|
||||
if (session.value.connected) {
|
||||
session.value.fit();
|
||||
session.value.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-delete',
|
||||
content: '清空',
|
||||
click: () => {
|
||||
session.value?.clear();
|
||||
}
|
||||
}, {
|
||||
icon: 'icon-poweroff',
|
||||
content: '关闭',
|
||||
disabled: session.value?.connected,
|
||||
click: () => {
|
||||
session.value?.logout();
|
||||
}
|
||||
},
|
||||
]);
|
||||
// 减小字号
|
||||
fontSizeSubtract: () => {
|
||||
if (session.value) {
|
||||
session.value.setOption('fontSize', session.value.getOption('fontSize') - 1);
|
||||
if (session.value.connected) {
|
||||
session.value.fit();
|
||||
session.value.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
// 清空
|
||||
clear: () => session.value?.clear(),
|
||||
// 断开连接
|
||||
disconnect: () => session.value?.disconnect(),
|
||||
// 关闭
|
||||
close: () => tabManager.deleteTab(props.tab.key),
|
||||
};
|
||||
|
||||
// 右侧操作
|
||||
const rightActions = computed<Array<SidebarAction>>(() => {
|
||||
return ActionBarItems.map(s => {
|
||||
return {
|
||||
icon: s.icon,
|
||||
content: s.content,
|
||||
visible: preference.actionBarSetting[s.item] !== false,
|
||||
disabled: actionsDisableStatus.value[s.item] !== false,
|
||||
click: () => {
|
||||
actionsClickHandler[s.item] && actionsClickHandler[s.item]();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化会话
|
||||
onMounted(async () => {
|
||||
@@ -297,7 +274,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-right-icon-actions {
|
||||
&-right-action-bar {
|
||||
display: flex;
|
||||
|
||||
:deep(.terminal-sidebar-icon-wrapper) {
|
||||
@@ -315,6 +292,10 @@
|
||||
.status-bridge {
|
||||
margin: 0 2px 0 8px;
|
||||
user-select: none;
|
||||
|
||||
:deep(.arco-badge-status-text) {
|
||||
width: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
// 登出
|
||||
session.logout();
|
||||
// 关闭连接
|
||||
session.disconnect();
|
||||
// 关闭 session
|
||||
session.close();
|
||||
// 移除 session
|
||||
|
||||
@@ -165,8 +165,8 @@ export default class TerminalSession implements ITerminalSession {
|
||||
this.inst.options[option as keyof ITerminalOptions] = value;
|
||||
}
|
||||
|
||||
// 登出
|
||||
logout(): void {
|
||||
// 断开连接
|
||||
disconnect(): void {
|
||||
// 发送关闭消息
|
||||
this.channel.send(InputProtocol.CLOSE, {
|
||||
sessionId: this.sessionId
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
&-header {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
height: var(--header-height);
|
||||
background: var(--color-bg-header);
|
||||
position: relative;
|
||||
z-index: 9999;
|
||||
|
||||
@@ -68,6 +68,67 @@ export const TerminalStatus = {
|
||||
CLOSED: 2
|
||||
};
|
||||
|
||||
// 终端操作栏-操作项
|
||||
export const ActionBarItems = [
|
||||
{
|
||||
item: 'toTop',
|
||||
icon: 'icon-up',
|
||||
content: '去顶部',
|
||||
}, {
|
||||
item: 'toBottom',
|
||||
icon: 'icon-down',
|
||||
content: '去底部',
|
||||
}, {
|
||||
item: 'checkAll',
|
||||
icon: 'icon-expand',
|
||||
content: '全选',
|
||||
}, {
|
||||
item: 'copy',
|
||||
icon: 'icon-copy',
|
||||
content: '复制选中部分',
|
||||
}, {
|
||||
item: 'paste',
|
||||
icon: 'icon-paste',
|
||||
content: '粘贴',
|
||||
}, {
|
||||
item: 'interrupt',
|
||||
icon: 'icon-formula',
|
||||
content: 'ctrl + c',
|
||||
}, {
|
||||
item: 'enter',
|
||||
icon: 'icon-play-arrow-fill',
|
||||
content: '回车',
|
||||
}, {
|
||||
item: 'commandEditor',
|
||||
icon: 'icon-code-square',
|
||||
content: '命令编辑器',
|
||||
}, {
|
||||
item: 'search',
|
||||
icon: 'icon-search',
|
||||
content: '搜索',
|
||||
}, {
|
||||
item: 'fontSizePlus',
|
||||
icon: 'icon-zoom-in',
|
||||
content: '增大字号',
|
||||
}, {
|
||||
item: 'fontSizeSubtract',
|
||||
icon: 'icon-zoom-out',
|
||||
content: '减小字号',
|
||||
}, {
|
||||
item: 'clear',
|
||||
icon: 'icon-delete',
|
||||
content: '清空',
|
||||
}, {
|
||||
item: 'disconnect',
|
||||
icon: 'icon-poweroff',
|
||||
content: '断开连接',
|
||||
}, {
|
||||
item: 'close',
|
||||
icon: 'icon-close',
|
||||
content: '关闭',
|
||||
}
|
||||
];
|
||||
|
||||
// 获取会话id
|
||||
export const nextSessionId = (): string => {
|
||||
return getUUID().replaceAll('-', '').substring(0, 10);
|
||||
|
||||
@@ -21,6 +21,7 @@ export interface SidebarAction {
|
||||
content: string;
|
||||
visible?: boolean;
|
||||
disabled?: boolean;
|
||||
checked?: boolean;
|
||||
iconStyle?: CSSProperties;
|
||||
click: () => void;
|
||||
}
|
||||
@@ -161,8 +162,8 @@ export interface ITerminalSession {
|
||||
getOption: (option: string) => any;
|
||||
// 设置配置
|
||||
setOption: (option: string, value: any) => void;
|
||||
// 登出
|
||||
logout: () => void;
|
||||
// 断开连接
|
||||
disconnect: () => void;
|
||||
// 关闭
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user