From c0475dc7de449821f415f6ef6d47ba6ecbab5a00 Mon Sep 17 00:00:00 2001 From: lijiahangmax Date: Sat, 13 Jan 2024 02:22:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=88=E7=AB=AF=E5=86=85=E6=90=9C?= =?UTF-8?q?=E7=B4=A2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/theme/terminal.theme.json | 102 ++++----- .../asset/meta/TerminalThemeGenerator.java | 4 +- orion-ops-ui/components.d.ts | 6 +- .../host/terminal/assets/styles/layout.less | 16 ++ .../components/layout/empty-recommend.vue | 6 +- .../xterm/terminal-search-modal.vue | 201 ++++++++++++++++++ .../components/xterm/terminal-view.vue | 31 ++- .../host/terminal/handler/terminal-session.ts | 11 +- .../host/terminal/types/terminal.const.ts | 10 +- .../host/terminal/types/terminal.type.ts | 4 +- 10 files changed, 314 insertions(+), 77 deletions(-) create mode 100644 orion-ops-ui/src/views/host/terminal/components/xterm/terminal-search-modal.vue diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/theme/terminal.theme.json b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/theme/terminal.theme.json index 55767b29..1815cf3a 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/theme/terminal.theme.json +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/theme/terminal.theme.json @@ -1,29 +1,4 @@ [ - { - "name": "catppuccin-macchiato", - "dark": true, - "headerBackgroundColor": "#181B2E", - "schema": { - "background": "#24273A", - "foreground": "#CAD3F5", - "cursor": "#F4DBD6", - "selectionBackground": "#5B6078", - "black": "#494D64", - "red": "#ED8796", - "green": "#A6DA95", - "yellow": "#EED49F", - "blue": "#8AADF4", - "cyan": "#8BD5CA", - "white": "#B8C0E0", - "brightBlack": "#5B6078", - "brightRed": "#ED8796", - "brightGreen": "#A6DA95", - "brightYellow": "#EED49F", - "brightBlue": "#8AADF4", - "brightCyan": "#8BD5CA", - "brightWhite": "#A5ADCB" - } - }, { "name": "catppuccin-mocha", "dark": true, @@ -49,31 +24,6 @@ "brightWhite": "#A6ADC8" } }, - { - "name": "OneHalfDark", - "dark": true, - "headerBackgroundColor": "#1C2028", - "schema": { - "background": "#282C34", - "foreground": "#DCDFE4", - "cursor": "#A3B3CC", - "selectionBackground": "#474E5D", - "black": "#282C34", - "red": "#E06C75", - "green": "#98C379", - "yellow": "#E5C07B", - "blue": "#61AFEF", - "cyan": "#56B6C2", - "white": "#DCDFE4", - "brightBlack": "#282C34", - "brightRed": "#E06C75", - "brightGreen": "#98C379", - "brightYellow": "#E5C07B", - "brightBlue": "#61AFEF", - "brightCyan": "#56B6C2", - "brightWhite": "#DCDFE4" - } - }, { "name": "MaterialDesignColors", "dark": true, @@ -99,6 +49,56 @@ "brightWhite": "#FFFFFF" } }, + { + "name": "catppuccin-macchiato", + "dark": true, + "headerBackgroundColor": "#181B2E", + "schema": { + "background": "#24273A", + "foreground": "#CAD3F5", + "cursor": "#F4DBD6", + "selectionBackground": "#5B6078", + "black": "#494D64", + "red": "#ED8796", + "green": "#A6DA95", + "yellow": "#EED49F", + "blue": "#8AADF4", + "cyan": "#8BD5CA", + "white": "#B8C0E0", + "brightBlack": "#5B6078", + "brightRed": "#ED8796", + "brightGreen": "#A6DA95", + "brightYellow": "#EED49F", + "brightBlue": "#8AADF4", + "brightCyan": "#8BD5CA", + "brightWhite": "#A5ADCB" + } + }, + { + "name": "OneHalfDark", + "dark": true, + "headerBackgroundColor": "#1C2028", + "schema": { + "background": "#282C34", + "foreground": "#DCDFE4", + "cursor": "#A3B3CC", + "selectionBackground": "#474E5D", + "black": "#282C34", + "red": "#E06C75", + "green": "#98C379", + "yellow": "#E5C07B", + "blue": "#61AFEF", + "cyan": "#56B6C2", + "white": "#DCDFE4", + "brightBlack": "#282C34", + "brightRed": "#E06C75", + "brightGreen": "#98C379", + "brightYellow": "#E5C07B", + "brightBlue": "#61AFEF", + "brightCyan": "#56B6C2", + "brightWhite": "#DCDFE4" + } + }, { "name": "Dracula", "dark": true, @@ -349,4 +349,4 @@ "brightWhite": "#FFFFFF" } } -] \ No newline at end of file +] diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/test/java/com/orion/ops/module/asset/meta/TerminalThemeGenerator.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/test/java/com/orion/ops/module/asset/meta/TerminalThemeGenerator.java index ca8f9e87..95736067 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/test/java/com/orion/ops/module/asset/meta/TerminalThemeGenerator.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/test/java/com/orion/ops/module/asset/meta/TerminalThemeGenerator.java @@ -29,8 +29,8 @@ public class TerminalThemeGenerator { List files = Files1.listFiles("D:\\idea-project\\iTerm2-Color-Schemes\\vhs"); // 过滤的 theme List schemaFilter = Lists.of( - "catppuccin-macchiato", "catppuccin-mocha", - "OneHalfDark", "MaterialDesignColors", + "catppuccin-mocha", "MaterialDesignColors", + "catppuccin-macchiato", "OneHalfDark", "Dracula", "Atom", "Apple System Colors", "Builtin Tango Light", "Duotone Dark", "BlulocoLight", diff --git a/orion-ops-ui/components.d.ts b/orion-ops-ui/components.d.ts index 24f3a4c2..224b0d1c 100644 --- a/orion-ops-ui/components.d.ts +++ b/orion-ops-ui/components.d.ts @@ -5,11 +5,11 @@ // Read more: https://github.com/vuejs/core/pull/3399 import '@vue/runtime-core'; -export {} +export {}; declare module '@vue/runtime-core' { export interface GlobalComponents { - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] + RouterLink: typeof import('vue-router')['RouterLink']; + RouterView: typeof import('vue-router')['RouterView']; } } diff --git a/orion-ops-ui/src/views/host/terminal/assets/styles/layout.less b/orion-ops-ui/src/views/host/terminal/assets/styles/layout.less index 3d5a3442..a8fcde0e 100644 --- a/orion-ops-ui/src/views/host/terminal/assets/styles/layout.less +++ b/orion-ops-ui/src/views/host/terminal/assets/styles/layout.less @@ -10,6 +10,14 @@ body { --color-content-text-1: rgba(0, 0, 0, .8); --color-content-text-2: rgba(0, 0, 0, .85); --color-content-text-3: rgba(0, 0, 0, .95); + --search-bg-focus: rgba(234, 234, 234, .75); + --search-bg: rgba(234, 234, 234, .95); + --search-color-text: #0E0E0E; + --search-color-text-focus: #0F0F0F; + --search-bg-icon-hover: rgba(12, 12, 12, .04); + --search-bg-icon-hover-focus: rgba(12, 12, 12, .08); + --search-bg-icon-selected: rgba(12, 12, 12, .06); + --search-bg-icon-selected-focus: rgba(12, 12, 12, .10); } // 暗色主题配色常量 @@ -24,6 +32,14 @@ body[terminal-theme='dark'] { --color-content-text-1: rgba(255, 255, 255, .8); --color-content-text-2: rgba(255, 255, 255, .85); --color-content-text-3: rgba(255, 255, 255, .95); + --search-bg: rgba(12, 12, 12, .75); + --search-bg-focus: rgba(12, 12, 12, .95); + --search-color-text: #E0E0E0; + --search-color-text-focus: #F0F0F0; + --search-bg-icon-hover: rgba(255, 255, 255, .07); + --search-bg-icon-hover-focus: rgba(255, 255, 255, .12); + --search-bg-icon-selected: rgba(255, 255, 255, .12); + --search-bg-icon-selected-focus: rgba(255, 255, 255, .16); } // 布局常量 diff --git a/orion-ops-ui/src/views/host/terminal/components/layout/empty-recommend.vue b/orion-ops-ui/src/views/host/terminal/components/layout/empty-recommend.vue index cd84fcfa..1cd55885 100644 --- a/orion-ops-ui/src/views/host/terminal/components/layout/empty-recommend.vue +++ b/orion-ops-ui/src/views/host/terminal/components/layout/empty-recommend.vue @@ -35,7 +35,7 @@ import { InnerTabs, TerminalTabType } from '../../types/terminal.const'; import { get } from 'lodash'; - const totalCount = 8; + const totalCount = 7; const { tabManager, hosts, openTerminal } = useTerminalStore(); const combinedHandlers = ref>([{ @@ -104,7 +104,7 @@ .combined-container { padding: 12px; margin: 64px auto; - width: 424px; + width: 398px; height: 448px; display: flex; flex-direction: column; @@ -145,7 +145,7 @@ width: calc(100% - @handler-height - 12px); display: flex; align-items: center; - font-size: 14px; + font-size: 12px; &-wrapper { display: block; diff --git a/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-search-modal.vue b/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-search-modal.vue new file mode 100644 index 00000000..a0846021 --- /dev/null +++ b/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-search-modal.vue @@ -0,0 +1,201 @@ + + + + + + + diff --git a/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-view.vue b/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-view.vue index 98248deb..cee6021f 100644 --- a/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-view.vue +++ b/orion-ops-ui/src/views/host/terminal/components/xterm/terminal-view.vue @@ -42,14 +42,18 @@ background: preference.theme.schema.background }">
+ +
- @@ -68,6 +72,7 @@ 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'; + import TerminalSearchModal from './terminal-search-modal.vue'; const props = defineProps<{ tab: TerminalTabItem @@ -77,18 +82,18 @@ const { getDictValue } = useDictStore(); const { preference, tabManager, sessionManager } = useTerminalStore(); - const modal = ref(); + const editorModal = ref(); + const searchModal = ref(); const commandInput = ref(); const terminalRef = ref(); const session = ref(); // TODO - // index 页面 - // 搜索 search color 配置 // 右键菜单补充 启用右键菜单 enableRightClickMenu 粘贴逻辑 - // 快捷键补充 粘贴逻辑 + // 设置快捷键 粘贴逻辑 + // 读取快捷键并且禁用快捷键 // 截屏 - // 主机获取逻辑 最近连接逻辑 + // sftp // 发送命令 const writeCommandInput = async (e: KeyboardEvent) => { @@ -111,6 +116,11 @@ session.value?.focus(); }; + // 查询关键字 + const findWords = (word: string, next: boolean, options: any) => { + session.value?.find(word, next, options); + }; + // 操作禁用状态 const actionsDisableStatus = computed>(() => { return { @@ -132,6 +142,8 @@ checkAll: () => session.value?.selectAll(), // 复制选中部分 copy: () => session.value?.copySelection(), + // 搜索 + search: () => searchModal.value.toggle(), // 粘贴 paste: async () => session.value?.pasteTrimEnd(await readText()), // ctrl + c @@ -139,10 +151,7 @@ // 回车 enter: () => session.value?.paste(String.fromCharCode(13)), // 命令编辑器 - commandEditor: () => modal.value.open('', ''), - // 搜索 - search: () => { - }, + commandEditor: () => editorModal.value.open('', ''), // 增大字号 fontSizePlus: () => { if (session.value) { diff --git a/orion-ops-ui/src/views/host/terminal/handler/terminal-session.ts b/orion-ops-ui/src/views/host/terminal/handler/terminal-session.ts index ae643e28..04ea24bd 100644 --- a/orion-ops-ui/src/views/host/terminal/handler/terminal-session.ts +++ b/orion-ops-ui/src/views/host/terminal/handler/terminal-session.ts @@ -7,7 +7,7 @@ import { InputProtocol } from '../types/terminal.protocol'; import { ITerminalOptions, Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; import { WebLinksAddon } from 'xterm-addon-web-links'; -import { SearchAddon } from 'xterm-addon-search'; +import { ISearchOptions, SearchAddon } from 'xterm-addon-search'; import { ImageAddon } from 'xterm-addon-image'; import { CanvasAddon } from 'xterm-addon-canvas'; import { WebglAddon } from 'xterm-addon-webgl'; @@ -235,6 +235,15 @@ export default class TerminalSession implements ITerminalSession { return selection; } + // 查找 + find(word: string, next: boolean, options: ISearchOptions): void { + if (next) { + this.addons.search.findNext(word, options); + } else { + this.addons.search.findPrevious(word, options); + } + } + // 去顶部 toTop(): void { this.inst.scrollToTop(); diff --git a/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts b/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts index 2b9a6182..8643c7e2 100644 --- a/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts +++ b/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts @@ -21,7 +21,7 @@ export const InnerTabs = { DISPLAY_SETTING: { key: 'displaySetting', title: '显示设置', - icon: 'icon-dice', + icon: 'icon-stamp', type: TerminalTabType.SETTING }, THEME_SETTING: { @@ -88,6 +88,10 @@ export const ActionBarItems = [ item: 'paste', icon: 'icon-paste', content: '粘贴', + }, { + item: 'search', + icon: 'icon-find-replace', + content: '搜索', }, { item: 'interrupt', icon: 'icon-formula', @@ -100,10 +104,6 @@ export const ActionBarItems = [ item: 'commandEditor', icon: 'icon-code-square', content: '命令编辑器', - }, { - item: 'search', - icon: 'icon-search', - content: '搜索', }, { item: 'fontSizePlus', icon: 'icon-zoom-in', diff --git a/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts b/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts index 9b71bc29..5dc016bd 100644 --- a/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts +++ b/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts @@ -3,7 +3,7 @@ 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'; +import type { ISearchOptions, SearchAddon } from 'xterm-addon-search'; import type { ImageAddon } from 'xterm-addon-image'; import type { CSSProperties } from 'vue'; import type { HostQueryResponse } from '@/api/asset/host'; @@ -169,6 +169,8 @@ export interface ITerminalSession { selectAll: () => void; // 复制选中 copySelection: () => string; + // 查找 + find: (word: string, next: boolean, options: ISearchOptions) => void; // 去顶部 toTop: () => void; // 去底部