feat: 添加终端交互配置项.

This commit is contained in:
lijiahangmax
2024-01-12 00:08:56 +08:00
parent 13c352691a
commit cacc7de364
14 changed files with 387 additions and 77 deletions

View File

@@ -0,0 +1,68 @@
<template>
<a-col :span="12">
<div class="block-form-item-wrapper">
<div class="block-form-item-header">
<!-- label -->
<div class="block-form-item-label">
{{ label }}
</div>
<!-- item -->
<div class="block-form-item-value">
<slot />
</div>
</div>
<!-- 描述 -->
<div class="block-form-item-desc">
{{ desc }}
</div>
</div>
</a-col>
</template>
<script lang="ts">
export default {
name: 'blockSettingItem'
};
</script>
<script lang="ts" setup>
defineProps<{
label: string,
desc: string,
}>();
</script>
<style lang="less" scoped>
.block-form-item-wrapper {
height: 100%;
min-height: 64px;
border-radius: 4px;
background: var(--color-fill-2);
padding: 16px;
display: flex;
flex-direction: column;
.block-form-item-header {
display: flex;
justify-content: space-between;
margin-bottom: 14px;
}
.block-form-item-label {
color: var(--color-content-text-3);
font-size: 14px;
}
.block-form-item-desc {
color: var(--color-text-2);
font-size: 12px;
}
:deep(.arco-input-wrapper) {
background-color: var(--color-fill-3)
}
}
</style>

View File

@@ -21,14 +21,14 @@
position="bottom" />
</a-form-item>
<!-- 命令输入框 -->
<a-form-item field="showCommandInput" label="命令输入框">
<a-form-item field="commandInput" 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-form-item field="showStatus" label="终端连接状态">
<a-switch v-model="formModel.connectStatus"
:default-checked="true"
type="round" />

View File

@@ -5,6 +5,8 @@
<h2 class="terminal-setting-title">终端设置</h2>
<!-- 交互设置 -->
<terminal-interact-block />
<!-- 插件设置 -->
<terminal-plugins-block />
<!-- 会话设置 -->
<terminal-session-block />
</div>
@@ -19,6 +21,7 @@
<script lang="ts" setup>
import TerminalInteractBlock from './terminal-interact-block.vue';
import TerminalPluginsBlock from './terminal-plugins-block.vue';
import TerminalSessionBlock from './terminal-session-block.vue';
</script>

View File

@@ -9,21 +9,70 @@
<!-- 提示 -->
<a-alert class="mb16">修改后会立刻保存, 刷新页面后生效</a-alert>
<!-- 内容区域 -->
<div class="terminal-setting-body">
<a-row class="" :gutter="[16, 16]">
<a-col :span="12">
<div class="block-form-item-wrapper">
<div class="block-form-item-label">
label
</div>
<div class="block-form-item-desc">
描述一下
</div>
<div class="block-form-item-value">
<a-switch />
</div>
</div>
</a-col>
<div class="terminal-setting-body setting-body">
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 快速滚动 -->
<block-setting-item label="快速滚动" desc="alt + 鼠标滚轮快速滚动">
<a-switch type="round"
v-model="formModel.fastScrollModifier"
checked-value="alt"
unchecked-value="none" />
</block-setting-item>
<!-- 点击移动光标 -->
<block-setting-item label="点击移动光标" desc="alt + 鼠标左键可以切换光标位置">
<a-switch type="round"
v-model="formModel.altClickMovesCursor" />
</block-setting-item>
</a-row>
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 右键选中词条 -->
<block-setting-item label="右键选中词条" desc="右键文本">
<a-switch type="round"
v-model="formModel.rightClickSelectsWord" />
</block-setting-item>
<!-- 选中词条自动复制 -->
<block-setting-item label="选中词条自动复制" desc="自动将选中的词条复制到剪切板">
<a-switch type="round"
v-model="formModel.selectionChangeCopy" />
</block-setting-item>
</a-row>
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 复制去除空格 -->
<block-setting-item label="复制去除空格" desc="复制文本后自动删除尾部空格">
<a-switch type="round"
v-model="formModel.copyAutoTrim" />
</block-setting-item>
<!-- 粘贴去除空格 -->
<block-setting-item label="粘贴去除空格" desc="粘贴文本前自动删除尾部空格">
<a-switch type="round"
v-model="formModel.pasteAutoTrim" />
</block-setting-item>
</a-row>
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 右键粘贴 -->
<block-setting-item label="右键粘贴" desc="右键自动粘贴, 启用后需要关闭右键菜单">
<a-switch type="round"
v-model="formModel.rightClickPaste" />
</block-setting-item>
<!-- 启用右键菜单 -->
<block-setting-item label="启用右键菜单" desc="右键终端将打开自定义菜单, 启用后需要关闭右键粘贴">
<a-switch type="round"
v-model="formModel.pasteAutoTrim" />
</block-setting-item>
</a-row>
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 启用响铃 -->
<block-setting-item label="启用响铃" desc="系统接受到 \a 时候会发出响铃 (一般不用开启)">
<a-switch type="round"
v-model="formModel.enableBell" />
</block-setting-item>
<!-- 单词分隔符 -->
<block-setting-item label="单词分隔符" desc="在终端中双击文本将使用该分隔符进行分割">
<a-input size="small"
v-model="formModel.wordSeparator"
placeholder="单词分隔符"
allow-clear />
</block-setting-item>
</a-row>
</div>
</div>
@@ -37,46 +86,31 @@
<script lang="ts" setup>
// TODO
// 交互设置
// alt + 滚轮快速滚动 fastScrollModifier 'none' | 'alt'
// alt 点击可以切换光标位置 altClickMovesCursor
// 快速滚动 fastScrollModifier
// 点击移动光标 altClickMovesCursor
// 右键选中词条 rightClickSelectsWord
// 自动将选中内容复制到剪切板 onSelectionChange
// 自动将选中内容复制到剪切板 selectionChangeCopy onSelectionChange
// 粘贴时删除空格
// 复制时删除空格
// 复制时删除空格 pasteAutoTrim
// 粘贴时删除空格 copyAutoTrim
// 右键粘贴
// 启用右键菜单
// 右键粘贴 rightClickPaste
// 启用右键菜单 enableRightClickMenu
// 自动检测 url 并可以点击
// 支持显示图片 使用 sixel 打开图片
// 启用响铃 enableBell
// 单词分隔符 /\()"'` -.,:;<>~!@#$%^&*|+=[]{}~?│ wordSeparator
// bell sound
// 分隔符 /\()"'-.,:;<>~!@#$%^&*|+=[]{}~?│ 在终端中双击文本将使用到这些符号 wordSeparator
import { ref } from 'vue';
import BlockSettingItem from './block-setting-item.vue';
const formModel = ref<Record<string, any>>({});
</script>
<style lang="less" scoped>
.block-form-item-wrapper {
height: 84px;
border-radius: 4px;
background: var(--color-fill-2);
display: flex;
padding: 16px;
.block-form-item-label {
color: var(--color-content-text-3);
font-size: 15px;
font-weight: bold;
}
.block-form-item-desc {
color: var(--color-content-text-2);
font-size: 12px;
}
.setting-body {
flex-direction: column;
}
</style>

View File

@@ -0,0 +1,61 @@
<template>
<div class="terminal-setting-block">
<!-- 顶部 -->
<div class="terminal-setting-subtitle-wrapper">
<h3 class="terminal-setting-subtitle">
插件设置
</h3>
</div>
<!-- 内容区域 -->
<div class="terminal-setting-body setting-body">
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 超链接插件 -->
<block-setting-item label="超链接插件" desc="自动检测 http url 并可以点击">
<a-switch type="round"
v-model="formModel.enableWeblinkPlugin"
checked-value="alt"
unchecked-value="none" />
</block-setting-item>
<!-- WebGL 渲染插件 -->
<block-setting-item label="WebGL 渲染插件" desc="使用 WebGL 加速渲染终端 (建议开启, 若无法开启终端请关闭)">
<a-switch type="round"
v-model="formModel.enableWebglPlugin" />
</block-setting-item>
</a-row>
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 图片渲染插件 -->
<block-setting-item label="图片渲染插件" desc="支持使用 sixel 打开图片 (一般不需要开启)">
<a-switch type="round"
v-model="formModel.enableImagePlugin" />
</block-setting-item>
</a-row>
</div>
</div>
</template>
<script lang="ts">
export default {
name: 'TerminalPluginsBlock'
};
</script>
<script lang="ts" setup>
// fixme
// 自动检测 url 并可以点击 enableWeblinkPlugin
// 启用 webgl 支持 enableWebglPlugin
// 支持显示图片 使用 sixel 打开图片 enableImagePlugin
import { ref } from 'vue';
import BlockSettingItem from './block-setting-item.vue';
const formModel = ref<Record<string, any>>({});
</script>
<style lang="less" scoped>
.setting-body {
flex-direction: column;
}
</style>

View File

@@ -7,9 +7,26 @@
</h3>
</div>
<!-- 内容区域 -->
<div class="terminal-setting-body">
<div class="terminal-setting-body setting-body">
<a-row class="mb16" align="stretch" :gutter="16">
<!-- 终端类型 -->
<block-setting-item label="终端类型" desc="若显示异常请尝试切换此选项 兼容性 vt100 > xterm > 16color > 256color">
<a-select style="width: 160px;"
v-model="formModel.terminalEmulationType"
size="small"
:options="toOptions(terminalEmulationTypeKey)" />
</block-setting-item>
<!-- 缓冲区行数 -->
<block-setting-item label="缓冲区行数" desc="保存在缓冲区的行数, 多出的行数会被忽略, 此值越大占用内存的内存会更多">
<a-input-number v-model="formModel.scrollBackLine"
size="small"
:min="1"
:max="10000"
placeholder="缓冲区行数"
allow-clear
hide-button />
</block-setting-item>
</a-row>
</div>
</div>
</template>
@@ -21,13 +38,25 @@
</script>
<script lang="ts" setup>
import { terminalEmulationTypeKey } from '../../types/terminal.const';
const { toOptions } = useDictStore();
// TODO
// terminal emulation type: xterm 256color
// 回滚ScrollBack scrollback 保存在缓冲区的行数
// terminalEmulationType: xterm 256color
// scrollBackLine 保存在缓冲区的行数 1000
import { ref } from 'vue';
import BlockSettingItem from './block-setting-item.vue';
import { useDictStore } from '@/store';
const formModel = ref<Record<string, any>>({});
</script>
<style lang="less" scoped>
.setting-body {
flex-direction: column;
}
</style>

View File

@@ -227,7 +227,6 @@
height: 100%;
display: inline-flex;
align-items: center;
user-select: none;
.address-copy {
display: none;

View File

@@ -8,6 +8,7 @@ import { WebglAddon } from 'xterm-addon-webgl';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon } from 'xterm-addon-search';
import { ImageAddon } from 'xterm-addon-image';
import { CanvasAddon } from 'xterm-addon-canvas';
// 终端会话实现
export default class TerminalSession implements ITerminalSession {
@@ -48,12 +49,13 @@ export default class TerminalSession implements ITerminalSession {
this.inst = new Terminal({
...(preference.displaySetting as any),
theme: preference.theme.schema,
fastScrollModifier: 'ctrl',
fastScrollModifier: 'alt',
fontFamily: preference.displaySetting.fontFamily + fontFamilySuffix,
});
// 注册插件
this.addons.fit = new FitAddon();
this.addons.webgl = new WebglAddon();
// this.addons.webgl = new WebglAddon();
this.addons.canvas = new CanvasAddon();
this.addons.link = new WebLinksAddon();
this.addons.search = new SearchAddon();
this.addons.image = new ImageAddon();

View File

@@ -156,10 +156,13 @@ export const extraSshAuthTypeKey = 'hostExtraSshAuthType';
// 终端状态
export const connectStatusKey = 'terminalConnectStatus';
// 终端类型
export const terminalEmulationTypeKey = 'terminalEmulationType';
// 加载的字典值
export const dictKeys = [
fontFamilyKey,
fontSizeKey, fontWeightKey,
cursorStyleKey, newConnectionTypeKey,
extraSshAuthTypeKey, connectStatusKey
fontFamilyKey, fontSizeKey,
fontWeightKey, cursorStyleKey,
newConnectionTypeKey, extraSshAuthTypeKey,
connectStatusKey, terminalEmulationTypeKey
];

View File

@@ -1,5 +1,6 @@
import type { Terminal } from 'xterm';
import type { FitAddon } from 'xterm-addon-fit';
import type { CanvasAddon } from 'xterm-addon-canvas';
import type { WebglAddon } from 'xterm-addon-webgl';
import type { WebLinksAddon } from 'xterm-addon-web-links';
import type { SearchAddon } from 'xterm-addon-search';
@@ -117,6 +118,7 @@ export interface ITerminalOutputProcessor {
export interface TerminalAddons {
fit: FitAddon;
webgl: WebglAddon;
canvas: CanvasAddon;
link: WebLinksAddon;
search: SearchAddon;
image: ImageAddon;