feat: 添加终端交互配置项.
This commit is contained in:
@@ -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>
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -227,7 +227,6 @@
|
||||
height: 100%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
|
||||
.address-copy {
|
||||
display: none;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
];
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user