From fc42e1b29a54e24512b2dd2f5b1a136ad8112a8d Mon Sep 17 00:00:00 2001 From: chaos-zhu Date: Sun, 20 Oct 2024 19:59:34 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=96=B0=E5=A2=9E=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E7=AB=AF=E8=99=9A=E6=8B=9F=E6=8C=89=E9=94=AE=E6=98=A0?= =?UTF-8?q?=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 + web/src/assets/scss/element/dark.scss | 3 + web/src/components/float-menu/index.vue | 258 ++++++++++++++++++ web/src/utils/enum.js | 6 +- .../terminal/components/terminal-tab.vue | 26 +- .../views/terminal/components/terminal.vue | 55 +++- 6 files changed, 346 insertions(+), 4 deletions(-) create mode 100644 web/src/components/float-menu/index.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8bb99..860a48d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,11 @@ ### Features * 兼容移动端UI +* 新增移动端虚拟功能按键映射 * 调整终端功能菜单 * 修复终端选中文本无法复制的bug * 修复无法展示服务端ping客户端延迟ms的bug +* 修复暗黑模式下的一些样式问题 ## [2.2.7](https://github.com/chaos-zhu/easynode/releases) (2024-10-17) diff --git a/web/src/assets/scss/element/dark.scss b/web/src/assets/scss/element/dark.scss index 37897a0..b5f8cea 100644 --- a/web/src/assets/scss/element/dark.scss +++ b/web/src/assets/scss/element/dark.scss @@ -79,6 +79,9 @@ html.dark { background-color: #6d6d6d; } + .el-menu { + border-right: none; + } .el-menu-item:not(.is-active):hover { color: var(--el-menu-active-color); } diff --git a/web/src/components/float-menu/index.vue b/web/src/components/float-menu/index.vue new file mode 100644 index 0000000..b619566 --- /dev/null +++ b/web/src/components/float-menu/index.vue @@ -0,0 +1,258 @@ + + + + + diff --git a/web/src/utils/enum.js b/web/src/utils/enum.js index f65b1ca..1516452 100644 --- a/web/src/utils/enum.js +++ b/web/src/utils/enum.js @@ -11,5 +11,7 @@ export const terminalStatusList = [ { value: terminalStatus.CONNECT_FAIL, label: '连接失败', color: '#DC3545' }, { value: terminalStatus.CONNECT_SUCCESS, label: '已连接', color: '#28A745' }, ] - -// other... +export const virtualKeyType = { + LONG_PRESS: 'long-press', + SINGLE_PRESS: 'single-press' +} diff --git a/web/src/views/terminal/components/terminal-tab.vue b/web/src/views/terminal/components/terminal-tab.vue index 9138357..acabdd5 100644 --- a/web/src/views/terminal/components/terminal-tab.vue +++ b/web/src/views/terminal/components/terminal-tab.vue @@ -33,10 +33,18 @@ const props = defineProps({ hostObj: { required: true, type: Object + }, + longPressCtrl: { + type: Boolean, + default: false + }, + longPressAlt: { + type: Boolean, + default: false } }) -const emit = defineEmits(['inputCommand', 'cdCommand', 'ping-data',]) +const emit = defineEmits(['inputCommand', 'cdCommand', 'ping-data', 'reset-long-press',]) const socket = ref(null) // const commandHistoryList = ref([]) @@ -64,6 +72,8 @@ const menuCollapse = computed(() => $store.menuCollapse) const quickCopy = computed(() => $store.terminalConfig.quickCopy) const quickPaste = computed(() => $store.terminalConfig.quickPaste) const autoExecuteScript = computed(() => $store.terminalConfig.autoExecuteScript) +const isLongPressCtrl = computed(() => props.longPressCtrl) +const isLongPressAlt = computed(() => props.longPressAlt) watch(menuCollapse, () => { nextTick(() => { @@ -326,7 +336,21 @@ function extractLastCdPath(text) { const onData = () => { // term.value.off('data', listenerInput) term.value.onData((key) => { + // console.log('key: ', key) + // if (key === '\x03') console.log('Ctrl + C detected') if (socketConnected.value === false) return + if (isLongPressCtrl.value || isLongPressAlt.value) { + const keyCode = key.toUpperCase().charCodeAt(0) + const ansiCode = keyCode - 64 + // console.log('ansiCode:', ansiCode) + if (ansiCode >= 1 && ansiCode <= 26) { + const controlChar = String.fromCharCode(ansiCode) + socket.value.emit('input', controlChar) + } + emit('reset-long-press') + return + } + let acsiiCode = key.codePointAt() // console.log(acsiiCode) if (acsiiCode === 22) return handlePaste() // Ctrl + V diff --git a/web/src/views/terminal/components/terminal.vue b/web/src/views/terminal/components/terminal.vue index 5f2191f..eb49839 100644 --- a/web/src/views/terminal/components/terminal.vue +++ b/web/src/views/terminal/components/terminal.vue @@ -155,9 +155,12 @@ + + + + + @@ -185,7 +199,8 @@ import { ref, computed, getCurrentInstance, watch, onMounted, onBeforeUnmount, n import { ArrowDown } from '@element-plus/icons-vue' import useMobileWidth from '@/composables/useMobileWidth' import InputCommand from '@/components/input-command/index.vue' -import { terminalStatusList } from '@/utils/enum' +import FloatMenu from '@/components/float-menu/index.vue' +import { terminalStatusList, virtualKeyType } from '@/utils/enum' import TerminalTab from './terminal-tab.vue' import InfoSide from './info-side.vue' import Sftp from './sftp.vue' @@ -217,6 +232,9 @@ const hostFormVisible = ref(false) const updateHostData = ref(null) const showSetting = ref(false) const showMobileInfoSideDialog = ref(false) +const showFloatMenu = ref(false) +const longPressCtrl = ref(false) +const longPressAlt = ref(false) const terminalTabs = computed(() => props.terminalTabs) const terminalTabsLen = computed(() => props.terminalTabs.length) @@ -268,6 +286,41 @@ const handleCloseAllTab = () => { emit('close-all-tab') } +const { LONG_PRESS, SINGLE_PRESS } = virtualKeyType +const handleClickVirtualKeyboard = async (virtualKey) => { + const { key, ansi ,type } = virtualKey + // console.log(key, ascii, ansi, type) + switch (type) { + case LONG_PRESS: + // console.log('待组合键') + if (key === 'Ctrl') { + longPressCtrl.value = true + longPressAlt.value = false + } + if (key === 'Alt') { + longPressAlt.value = true + longPressCtrl.value = false + } + // eslint-disable-next-line no-case-declarations + const curTerminalRef = terminalRefs.value[activeTabIndex.value] + await $nextTick() + curTerminalRef?.focusTab() + break + case SINGLE_PRESS: + longPressCtrl.value = false + longPressAlt.value = false + handleExecScript({ command: ansi }) + break + default: + break + } +} + +const resetLongPress = () => { + longPressCtrl.value = false + longPressAlt.value = false +} + const handleExecScript = (scriptObj) => { let { command } = scriptObj if (!isSyncAllSession.value) return handleInputCommand(command)