feat: 终端操作栏配置化.

This commit is contained in:
lijiahang
2024-01-11 16:55:37 +08:00
parent 8e03368e85
commit 25acde6d1e
16 changed files with 409 additions and 221 deletions

View File

@@ -24,15 +24,18 @@ public class TerminalPreferenceModel implements PreferenceModel {
@Schema(description = "新建连接类型") @Schema(description = "新建连接类型")
private String newConnectionType; private String newConnectionType;
@Schema(description = "终端主题")
private JSONObject theme;
@Schema(description = "显示设置") @Schema(description = "显示设置")
private JSONObject displaySetting; private JSONObject displaySetting;
@Schema(description = "操作栏设置")
private JSONObject actionBarSetting;
@Schema(description = "背景设置") @Schema(description = "背景设置")
private JSONObject backgroundSetting; private JSONObject backgroundSetting;
@Schema(description = "终端主题")
private JSONObject theme;
@Data @Data
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor

View File

@@ -16,21 +16,24 @@ public class TerminalPreferenceStrategy implements IPreferenceStrategy<TerminalP
@Override @Override
public TerminalPreferenceModel getDefault() { public TerminalPreferenceModel getDefault() {
return TerminalPreferenceModel.builder() // 默认显示设置
.newConnectionType("group") JSONObject defaultDisplaySetting = TerminalPreferenceModel.DisplaySettingModel
.displaySetting(TerminalPreferenceModel.DisplaySettingModel.builder() .builder()
.fontFamily("_") .fontFamily("_")
.fontSize(12) .fontSize(14)
.lineHeight(1.00) .lineHeight(1.00)
.fontWeight("normal") .fontWeight("normal")
.fontWeightBold("bold") .fontWeightBold("bold")
.cursorStyle("bar") .cursorStyle("bar")
.cursorBlink(true) .cursorBlink(true)
.build() .build()
.toJson() .toJson();
) return TerminalPreferenceModel.builder()
.backgroundSetting(new JSONObject()) .newConnectionType("group")
.theme(new JSONObject()) .theme(new JSONObject())
.displaySetting(defaultDisplaySetting)
.actionBarSetting(new JSONObject())
.backgroundSetting(new JSONObject())
.build(); .build();
} }

View File

@@ -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 type { TerminalTheme } from '@/api/asset/host-terminal';
import { getTerminalThemes } from '@/api/asset/host-terminal'; import { getTerminalThemes } from '@/api/asset/host-terminal';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
@@ -15,14 +15,17 @@ export const PreferenceItem = {
THEME: 'theme', THEME: 'theme',
// 显示设置 // 显示设置
DISPLAY_SETTING: 'displaySetting', DISPLAY_SETTING: 'displaySetting',
// 操作栏设置
ACTION_BAR_SETTING: 'actionBarSetting',
}; };
export default defineStore('terminal', { export default defineStore('terminal', {
state: (): TerminalState => ({ state: (): TerminalState => ({
preference: { preference: {
newConnectionType: 'group', newConnectionType: 'group',
theme: {} as TerminalTheme,
displaySetting: {} as TerminalDisplaySetting, displaySetting: {} as TerminalDisplaySetting,
theme: {} as TerminalTheme actionBarSetting: {} as TerminalActionBarSetting,
}, },
tabManager: new TerminalTabManager(), tabManager: new TerminalTabManager(),
sessionManager: new TerminalSessionManager() sessionManager: new TerminalSessionManager()

View File

@@ -10,8 +10,9 @@ export interface TerminalState {
// 终端配置 // 终端配置
export interface TerminalPreference { export interface TerminalPreference {
newConnectionType: string; newConnectionType: string;
displaySetting: TerminalDisplaySetting;
theme: TerminalTheme; theme: TerminalTheme;
displaySetting: TerminalDisplaySetting;
actionBarSetting: TerminalActionBarSetting;
} }
// 显示设置 // 显示设置
@@ -25,3 +26,11 @@ export interface TerminalDisplaySetting {
cursorBlink?: boolean; cursorBlink?: boolean;
} }
// 操作栏设置
export interface TerminalActionBarSetting {
commandInput?: boolean;
connectStatus?: boolean;
[key: string]: unknown;
}

View File

@@ -192,11 +192,14 @@ body[terminal-theme='dark'] .arco-modal-container {
background: var(--color-sidebar-icon-bg); background: var(--color-sidebar-icon-bg);
} }
&.checked-item {
background: var(--color-sidebar-icon-bg);
}
&.disabled-item { &.disabled-item {
cursor: not-allowed; cursor: not-allowed;
} }
} }
} }
// 终端设置容器 // 终端设置容器
@@ -239,6 +242,14 @@ body[terminal-theme='dark'] .arco-modal-container {
.terminal-setting-body { .terminal-setting-body {
display: flex; display: flex;
&.block-body {
display: flex;
width: 100%;
padding: 16px;
border: 1px solid var(--color-fill-4);
border-radius: 4px;
}
} }
} }

View File

@@ -9,7 +9,11 @@
:content="action.content"> :content="action.content">
<div class="terminal-sidebar-icon-wrapper" v-if="action.visible !== false"> <div class="terminal-sidebar-icon-wrapper" v-if="action.visible !== false">
<div class="terminal-sidebar-icon" <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"> @click="action.disabled !== false ? action.click() : false">
<component :is="action.icon" :style="action?.iconStyle" /> <component :is="action.icon" :style="action?.iconStyle" />
</div> </div>

View File

@@ -85,12 +85,13 @@
} }
&-logo-text { &-logo-text {
height: var(--header-height);
margin: 0; margin: 0;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 8px; padding: 0 8px;
font-size: 16px; font-size: 16px;
overflow: hidden;
white-space: nowrap;
} }
&-tabs { &-tabs {

View File

@@ -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>

View File

@@ -3,18 +3,21 @@
<!-- 顶部 --> <!-- 顶部 -->
<div class="terminal-setting-subtitle-wrapper"> <div class="terminal-setting-subtitle-wrapper">
<h3 class="terminal-setting-subtitle"> <h3 class="terminal-setting-subtitle">
显示设置 显示偏好
</h3> </h3>
</div> </div>
<!-- 提示 -->
<a-alert class="mb16">修改后会立刻保存, 重新打开终端后生效 (无需刷新页面)</a-alert>
<!-- 内容区域 --> <!-- 内容区域 -->
<div class="terminal-setting-body"> <div class="terminal-setting-body block-body setting-body">
<div class="terminal-setting-form"> <a-form class="terminal-setting-form"
<a-form :model="formModel" layout="vertical"> :model="formModel"
layout="vertical">
<a-space> <a-space>
<!-- 字体样式 --> <!-- 字体样式 -->
<a-form-item field="fontFamily" label="字体样式"> <a-form-item field="fontFamily" label="字体样式">
<a-select v-model="formModel.fontFamily" <a-select v-model="formModel.fontFamily"
class="form-item form-item-font-family" class="form-item-font-family"
placeholder="请选择字体样式" placeholder="请选择字体样式"
:options="toOptions(fontFamilyKey)" :options="toOptions(fontFamilyKey)"
:allow-create="true" :allow-create="true"
@@ -27,14 +30,14 @@
<!-- 字体大小 --> <!-- 字体大小 -->
<a-form-item field="fontSize" label="字体大小"> <a-form-item field="fontSize" label="字体大小">
<a-select v-model="formModel.fontSize" <a-select v-model="formModel.fontSize"
class="form-item form-item-font-size" class="form-item-font-size"
placeholder="请选择字体大小" placeholder="请选择字体大小"
:options="toOptions(fontSizeKey)" /> :options="toOptions(fontSizeKey)" />
</a-form-item> </a-form-item>
<!-- 行高 --> <!-- 行高 -->
<a-form-item field="lineHeight" label="行高"> <a-form-item field="lineHeight" label="行高">
<a-input-number v-model="formModel.lineHeight" <a-input-number v-model="formModel.lineHeight"
class="form-item form-item-line-height" class="form-item-line-height"
placeholder="请输入行高" placeholder="请输入行高"
:precision="2" :precision="2"
:min="1" :min="1"
@@ -46,14 +49,14 @@
<!-- 普通文本字重 --> <!-- 普通文本字重 -->
<a-form-item field="fontWeight" label="普通文本字重"> <a-form-item field="fontWeight" label="普通文本字重">
<a-select v-model="formModel.fontWeight" <a-select v-model="formModel.fontWeight"
class="form-item form-item-font-weight" class="form-item-font-weight"
placeholder="请选择字重" placeholder="请选择字重"
:options="toOptions(fontWeightKey)" /> :options="toOptions(fontWeightKey)" />
</a-form-item> </a-form-item>
<!-- 加粗文本字重 --> <!-- 加粗文本字重 -->
<a-form-item field="fontWeightBold" label="加粗文本字重"> <a-form-item field="fontWeightBold" label="加粗文本字重">
<a-select v-model="formModel.fontWeightBold" <a-select v-model="formModel.fontWeightBold"
class="form-item form-item-font-bold-weight" class="form-item-font-bold-weight"
placeholder="请选择字重" placeholder="请选择字重"
:options="toOptions(fontWeightKey)" /> :options="toOptions(fontWeightKey)" />
</a-form-item> </a-form-item>
@@ -63,18 +66,17 @@
<a-form-item field="cursorStyle" label="光标样式"> <a-form-item field="cursorStyle" label="光标样式">
<a-radio-group type="button" <a-radio-group type="button"
v-model="formModel.cursorStyle" v-model="formModel.cursorStyle"
class="form-item form-item-cursor-style usn" class="form-item-cursor-style usn"
:options="toRadioOptions(cursorStyleKey)" /> :options="toRadioOptions(cursorStyleKey)" />
</a-form-item> </a-form-item>
<!-- 光标闪烁 --> <!-- 光标闪烁 -->
<a-form-item field="cursorBlink" label="光标是否闪烁"> <a-form-item field="cursorBlink" label="光标是否闪烁">
<a-switch v-model="formModel.cursorBlink" <a-switch v-model="formModel.cursorBlink"
type="round" type="round"
class="form-item form-item-cursor-blink" /> class="form-item-cursor-blink" />
</a-form-item> </a-form-item>
</a-space> </a-space>
</a-form> </a-form>
</div>
<!-- 预览区域 --> <!-- 预览区域 -->
<div class="terminal-example"> <div class="terminal-example">
<span class="terminal-example-label">预览效果</span> <span class="terminal-example-label">预览效果</span>
@@ -90,7 +92,7 @@
<script lang="ts"> <script lang="ts">
export default { export default {
name: 'TerminalFontBlock' name: 'TerminalDisplayBlock'
}; };
</script> </script>
@@ -109,15 +111,6 @@
const previewTerminal = ref(); const previewTerminal = ref();
const formModel = ref<TerminalDisplaySetting>({ ...preference.displaySetting }); 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) => { watch(formModel, (v) => {
if (!v) { if (!v) {
@@ -136,7 +129,7 @@
} }
}); });
// 同步 // 同步
updateTerminalPreference(PreferenceItem.DISPLAY_SETTING, formModel.value); updateTerminalPreference(PreferenceItem.DISPLAY_SETTING, formModel.value, true);
// 聚焦 // 聚焦
previewTerminal.value.term.focus(); previewTerminal.value.term.focus();
}, { deep: true }); }, { deep: true });
@@ -146,13 +139,8 @@
<style lang="less" scoped> <style lang="less" scoped>
@terminal-width: 458px; @terminal-width: 458px;
.terminal-setting-body { .setting-body {
height: 248px; height: 248px;
width: 100%;
padding: 16px;
border: 1px solid var(--color-fill-4);
border-radius: 4px;
display: flex;
justify-content: space-between; justify-content: space-between;
} }

View File

@@ -2,21 +2,24 @@
<div class="terminal-setting-container"> <div class="terminal-setting-container">
<div class="terminal-setting-wrapper"> <div class="terminal-setting-wrapper">
<!-- 主标题 --> <!-- 主标题 -->
<h2 class="terminal-setting-title">外观设置</h2> <h2 class="terminal-setting-title">显示设置</h2>
<!-- 显示设置 --> <!-- 显示偏好 -->
<terminal-display-block /> <terminal-display-block />
<!-- 顶部工具栏 -->
<terminal-action-bar-block />
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
export default { export default {
name: 'TerminalViewSetting' name: 'TerminalDisplaySetting'
}; };
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import TerminalDisplayBlock from './terminal-display-block.vue'; import TerminalDisplayBlock from './terminal-display-block.vue';
import TerminalActionBarBlock from './terminal-action-bar-block.vue';
</script> </script>

View File

@@ -17,19 +17,21 @@
</div> </div>
<!-- 右侧操作 --> <!-- 右侧操作 -->
<div class="terminal-header-right"> <div class="terminal-header-right">
<!-- 代码输入框 --> <!-- 命令输入框 -->
<a-textarea class="command-input mr8" <a-textarea class="command-input mr8"
v-if="preference.actionBarSetting.commandInput !== false"
v-model="commandInput" v-model="commandInput"
:auto-size="{ minRows: 1, maxRows: 1 }" :auto-size="{ minRows: 1, maxRows: 1 }"
placeholder="F8 发送命令" placeholder="F8 发送命令"
allow-clear allow-clear
@keyup="writeCommandInput" /> @keyup="writeCommandInput" />
<!-- 操作按钮 --> <!-- 操作按钮 -->
<icon-actions class="terminal-header-right-icon-actions" <icon-actions class="terminal-header-right-action-bar"
:actions="rightActions" :actions="rightActions"
position="bottom" /> 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')" :status="getDictValue(connectStatusKey, session ? session.status : 0, 'status')"
:text="getDictValue(connectStatusKey, session ? session.status : 0)" /> :text="getDictValue(connectStatusKey, session ? session.status : 0)" />
</div> </div>
@@ -59,12 +61,11 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import type { SidebarAction } from '../../types/terminal.type'; import type { ITerminalSession, TerminalTabItem, SidebarAction } from '../../types/terminal.type';
import type { ITerminalSession, TerminalTabItem } from '../../types/terminal.type';
import { computed, onMounted, onUnmounted, ref } from 'vue'; import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useDictStore, useTerminalStore } from '@/store'; import { useDictStore, useTerminalStore } from '@/store';
import useCopy from '@/hooks/copy'; 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 IconActions from '../layout/icon-actions.vue';
import ShellEditorModal from '@/components/view/shell-editor/shell-editor-modal.vue'; import ShellEditorModal from '@/components/view/shell-editor/shell-editor-modal.vue';
@@ -74,7 +75,7 @@
const { copy, readText } = useCopy(); const { copy, readText } = useCopy();
const { getDictValue } = useDictStore(); const { getDictValue } = useDictStore();
const { preference, sessionManager } = useTerminalStore(); const { preference, tabManager, sessionManager } = useTerminalStore();
const modal = ref(); const modal = ref();
const commandInput = ref(); const commandInput = ref();
@@ -127,69 +128,40 @@
session.value?.focus(); session.value?.focus();
}; };
// 右侧操作 // 操作禁用状态
const rightActions = computed<Array<SidebarAction>>(() => [ const actionsDisableStatus = computed<Record<string, boolean | undefined>>(() => {
{ return {
icon: 'icon-up', paste: session.value?.canWrite,
content: '去顶部', interrupt: session.value?.canWrite,
click: () => { enter: session.value?.canWrite,
session.value?.toTop(); commandEditor: session.value?.canWrite,
} disconnect: session.value?.connected,
}, { };
icon: 'icon-down', });
content: '去底部',
click: () => { // 操作点击逻辑
session.value?.toBottom(); const actionsClickHandler: Record<string, () => void> = {
} // 去顶部
}, { toTop: () => session.value?.toTop(),
icon: 'icon-expand', // 去底部
content: '全选', toBottom: () => session.value?.toBottom(),
click: () => { // 全选
session.value?.selectAll(); checkAll: () => session.value?.selectAll(),
} // 复制选中部分
}, { copy: () => copy(session.value?.getSelection(), '已复制'),
icon: 'icon-copy', // 粘贴
content: '复制选中部分', paste: async () => session.value?.paste(await readText()),
click: () => { // ctrl + c
copy(session.value?.getSelection(), '已复制'); interrupt: () => session.value?.paste(String.fromCharCode(3)),
} // 回车
}, { enter: () => session.value?.paste(String.fromCharCode(13)),
icon: 'icon-paste', // 命令编辑器
content: '粘贴', commandEditor: () => modal.value.open('', ''),
disabled: session.value?.canWrite, // 搜索
click: async () => { search: () => {
session.value?.paste(await readText()); },
} // 增大字号
}, { fontSizePlus: () => {
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) { if (session.value) {
session.value.setOption('fontSize', session.value.getOption('fontSize') + 1); session.value.setOption('fontSize', session.value.getOption('fontSize') + 1);
if (session.value.connected) { if (session.value.connected) {
@@ -197,11 +169,9 @@
session.value.focus(); session.value.focus();
} }
} }
} },
}, { // 减小字号
icon: 'icon-zoom-out', fontSizeSubtract: () => {
content: '减小字号',
click: () => {
if (session.value) { if (session.value) {
session.value.setOption('fontSize', session.value.getOption('fontSize') - 1); session.value.setOption('fontSize', session.value.getOption('fontSize') - 1);
if (session.value.connected) { if (session.value.connected) {
@@ -209,22 +179,29 @@
session.value.focus(); session.value.focus();
} }
} }
}
}, {
icon: 'icon-delete',
content: '清空',
click: () => {
session.value?.clear();
}
}, {
icon: 'icon-poweroff',
content: '关闭',
disabled: session.value?.connected,
click: () => {
session.value?.logout();
}
}, },
]); // 清空
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 () => { onMounted(async () => {
@@ -297,7 +274,7 @@
} }
} }
&-right-icon-actions { &-right-action-bar {
display: flex; display: flex;
:deep(.terminal-sidebar-icon-wrapper) { :deep(.terminal-sidebar-icon-wrapper) {
@@ -315,6 +292,10 @@
.status-bridge { .status-bridge {
margin: 0 2px 0 8px; margin: 0 2px 0 8px;
user-select: none; user-select: none;
:deep(.arco-badge-status-text) {
width: 36px;
}
} }
} }

View File

@@ -60,8 +60,8 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
if (!session) { if (!session) {
return; return;
} }
// 登出 // 关闭连接
session.logout(); session.disconnect();
// 关闭 session // 关闭 session
session.close(); session.close();
// 移除 session // 移除 session

View File

@@ -165,8 +165,8 @@ export default class TerminalSession implements ITerminalSession {
this.inst.options[option as keyof ITerminalOptions] = value; this.inst.options[option as keyof ITerminalOptions] = value;
} }
// 登出 // 断开连接
logout(): void { disconnect(): void {
// 发送关闭消息 // 发送关闭消息
this.channel.send(InputProtocol.CLOSE, { this.channel.send(InputProtocol.CLOSE, {
sessionId: this.sessionId sessionId: this.sessionId

View File

@@ -94,7 +94,7 @@
&-header { &-header {
width: 100%; width: 100%;
height: 44px; height: var(--header-height);
background: var(--color-bg-header); background: var(--color-bg-header);
position: relative; position: relative;
z-index: 9999; z-index: 9999;

View File

@@ -68,6 +68,67 @@ export const TerminalStatus = {
CLOSED: 2 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 // 获取会话id
export const nextSessionId = (): string => { export const nextSessionId = (): string => {
return getUUID().replaceAll('-', '').substring(0, 10); return getUUID().replaceAll('-', '').substring(0, 10);

View File

@@ -21,6 +21,7 @@ export interface SidebarAction {
content: string; content: string;
visible?: boolean; visible?: boolean;
disabled?: boolean; disabled?: boolean;
checked?: boolean;
iconStyle?: CSSProperties; iconStyle?: CSSProperties;
click: () => void; click: () => void;
} }
@@ -161,8 +162,8 @@ export interface ITerminalSession {
getOption: (option: string) => any; getOption: (option: string) => any;
// 设置配置 // 设置配置
setOption: (option: string, value: any) => void; setOption: (option: string, value: any) => void;
// 登出 // 断开连接
logout: () => void; disconnect: () => void;
// 关闭 // 关闭
close: () => void; close: () => void;
} }