feat: 快速发送 shell 命令.

This commit is contained in:
lijiahangmax
2024-01-10 01:05:15 +08:00
parent 3f1a6aa0d1
commit f9069d08d3
7 changed files with 169 additions and 60 deletions

View File

@@ -44,7 +44,7 @@ body[terminal-theme='dark'] {
}
// arco 亮色配色
body .host-layout {
body .host-layout, .arco-modal-container {
--color-white: #ffffff;
--color-black: #000000;
--color-border: rgb(var(--gray-3));
@@ -115,7 +115,8 @@ body .host-layout {
}
// arco 暗色配色
body[terminal-theme='dark'] .host-layout {
body[terminal-theme='dark'] .host-layout,
body[terminal-theme='dark'] .arco-modal-container {
--color-white: rgba(255, 255, 255, 0.9);
--color-black: #000000;
--color-border: #333335;
@@ -125,6 +126,7 @@ body[terminal-theme='dark'] .host-layout {
--color-bg-4: #313132;
--color-bg-5: #373739;
--color-bg-white: #f6f6f6;
--color-neutral-3: rgba(255, 255, 255, 0.12);
--color-text-1: rgba(255, 255, 255, 0.9);
--color-text-2: rgba(255, 255, 255, 0.7);
--color-text-3: rgba(255, 255, 255, 0.5);

View File

@@ -29,7 +29,7 @@
:actions="rightActions"
position="bottom" />
<!-- 状态 -->
<a-badge style="margin: 0 2px 0 8px;"
<a-badge class="status-bridge"
:status="getDictValue(connectStatusKey, session ? session.status : 0, 'status')"
:text="getDictValue(connectStatusKey, session ? session.status : 0)" />
</div>
@@ -41,6 +41,13 @@
}">
<div class="terminal-inst" ref="terminalRef" />
</div>
<!-- 命令编辑器 -->
<shell-editor-modal ref="modal"
:closable="false"
:body-style="{ padding: '16px 16px 16px 0' }"
:dark="themeSchema.dark"
cancel-text="关闭"
@ok="writeCommand(modal.getValue())" />
</div>
</template>
@@ -51,13 +58,15 @@
</script>
<script lang="ts" setup>
import type { SidebarAction } from '../../types/terminal.const';
import type { ITerminalSession, TerminalTabItem } from '../../types/terminal.type';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useDictStore, useTerminalStore } from '@/store';
import useCopy from '@/hooks/copy';
import IconActions from '@/views/host/terminal/components/layout/icon-actions.vue';
import { connectStatusKey, SidebarAction } from '@/views/host/terminal/types/terminal.const';
import { connectStatusKey } from '../../types/terminal.const';
import { adjustColor } from '@/utils';
import ShellEditorModal from '@/components/view/shell-editor/shell-editor-modal.vue';
const props = defineProps<{
tab: TerminalTabItem
@@ -67,27 +76,41 @@
const { getDictValue } = useDictStore();
const { preference, sessionManager } = useTerminalStore();
const modal = ref();
const commandInput = ref();
const themeSchema = preference.themeSchema;
const terminalRef = ref();
const session = ref<ITerminalSession>();
// FIXME
// 命令编辑器 搜索
// 卸载 最外层 terminal 组件, 卸载 style
// terminal themes 改成非同步 style
// (改成可配置/拆分)
// 自定义 font siderBar 颜色, 集成到主题里面, 现在的问题是切换主题字体颜色就变了
// 是否开启 link, url 匹配策略
// 是否开启 image
// search color 配置
// 右键菜单补充
// 搜索
// 搜索插件, link插件
// 截屏
// 发送命令
const writeCommandInput = async (e: KeyboardEvent) => {
const value = commandInput.value;
if (value && e.code === 'F8' && session.value?.canWrite) {
session.value.paste(value);
if (value && e.code === 'F8') {
writeCommand(value);
commandInput.value = undefined;
}
};
// 发送命令
const writeCommand = (value: string) => {
if (session.value?.canWrite) {
session.value.paste(value);
}
};
// 右侧操作
const rightActions = computed<Array<SidebarAction>>(() => [
{
@@ -140,6 +163,7 @@
content: '命令编辑器',
disabled: session.value?.canWrite,
click: () => {
modal.value.open('', '');
}
}, {
icon: 'icon-search',
@@ -269,6 +293,11 @@
font-size: 20px;
}
}
.status-bridge {
margin: 0 2px 0 8px;
user-select: none;
}
}
.terminal-wrapper {

View File

@@ -1,16 +1,13 @@
import type { ITerminalChannel, ITerminalSession } from '../types/terminal.type';
import type { ITerminalChannel, ITerminalSession, TerminalAddons } from '../types/terminal.type';
import { useTerminalStore } from '@/store';
import { fontFamilySuffix, TerminalStatus } from '../types/terminal.const';
import { InputProtocol } from '../types/terminal.protocol';
import { ITerminalOptions, Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { WebglAddon } from 'xterm-addon-webgl';
// 终端插件
export interface TerminalAddons {
fit: FitAddon;
webgl: WebglAddon;
}
import { WebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon } from 'xterm-addon-search';
import { ImageAddon } from 'xterm-addon-image';
// 终端会话实现
export default class TerminalSession implements ITerminalSession {
@@ -57,6 +54,9 @@ export default class TerminalSession implements ITerminalSession {
// 注册插件
this.addons.fit = new FitAddon();
this.addons.webgl = new WebglAddon();
this.addons.link = new WebLinksAddon();
this.addons.search = new SearchAddon();
this.addons.image = new ImageAddon();
for (const addon of Object.values(this.addons)) {
this.inst.loadAddon(addon);
}

View File

@@ -1,4 +1,9 @@
import type { Terminal } from 'xterm';
import type { FitAddon } from 'xterm-addon-fit';
import type { WebglAddon } from 'xterm-addon-webgl';
import type { WebLinksAddon } from 'xterm-addon-web-links';
import type { SearchAddon } from 'xterm-addon-search';
import type { ImageAddon } from 'xterm-addon-image';
// 终端 tab 元素
export interface TerminalTabItem {
@@ -88,6 +93,15 @@ export interface ITerminalOutputProcessor {
processOutput: (payload: OutputPayload) => void;
}
// 终端插件
export interface TerminalAddons {
fit: FitAddon;
webgl: WebglAddon;
link: WebLinksAddon;
search: SearchAddon;
image: ImageAddon;
}
// 终端会话定义
export interface ITerminalSession {
hostId: number;