✨ 调整移动端虚拟按键位置
This commit is contained in:
parent
5724ede172
commit
7aefa410dc
@ -15,7 +15,7 @@ module.exports.KeyDB = class KeyDB {
|
||||
constructor() {
|
||||
if (!KeyDB.instance) {
|
||||
KeyDB.instance = new Datastore({ filename: keyDBPath, autoload: true })
|
||||
KeyDB.instance.setAutocompactionInterval(5000)
|
||||
// KeyDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -27,7 +27,7 @@ module.exports.HostListDB = class HostListDB {
|
||||
constructor() {
|
||||
if (!HostListDB.instance) {
|
||||
HostListDB.instance = new Datastore({ filename: hostListDBPath, autoload: true })
|
||||
HostListDB.instance.setAutocompactionInterval(5000)
|
||||
// HostListDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -39,7 +39,7 @@ module.exports.SshRecordDB = class SshRecordDB {
|
||||
constructor() {
|
||||
if (!SshRecordDB.instance) {
|
||||
SshRecordDB.instance = new Datastore({ filename: credentialsDBPath, autoload: true })
|
||||
SshRecordDB.instance.setAutocompactionInterval(5000)
|
||||
// SshRecordDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -51,7 +51,7 @@ module.exports.NotifyDB = class NotifyDB {
|
||||
constructor() {
|
||||
if (!NotifyDB.instance) {
|
||||
NotifyDB.instance = new Datastore({ filename: notifyDBPath, autoload: true })
|
||||
NotifyDB.instance.setAutocompactionInterval(5000)
|
||||
// NotifyDB.instance.setAutocompactionInterval(5000)
|
||||
|
||||
}
|
||||
}
|
||||
@ -64,7 +64,7 @@ module.exports.NotifyConfigDB = class NotifyConfigDB {
|
||||
constructor() {
|
||||
if (!NotifyConfigDB.instance) {
|
||||
NotifyConfigDB.instance = new Datastore({ filename: notifyConfigDBPath, autoload: true })
|
||||
NotifyConfigDB.instance.setAutocompactionInterval(5000)
|
||||
// NotifyConfigDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -76,7 +76,7 @@ module.exports.GroupDB = class GroupDB {
|
||||
constructor() {
|
||||
if (!GroupDB.instance) {
|
||||
GroupDB.instance = new Datastore({ filename: groupConfDBPath, autoload: true })
|
||||
GroupDB.instance.setAutocompactionInterval(5000)
|
||||
// GroupDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -88,7 +88,7 @@ module.exports.ScriptsDB = class ScriptsDB {
|
||||
constructor() {
|
||||
if (!ScriptsDB.instance) {
|
||||
ScriptsDB.instance = new Datastore({ filename: scriptsDBPath, autoload: true })
|
||||
ScriptsDB.instance.setAutocompactionInterval(5000)
|
||||
// ScriptsDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -100,7 +100,7 @@ module.exports.OnekeyDB = class OnekeyDB {
|
||||
constructor() {
|
||||
if (!OnekeyDB.instance) {
|
||||
OnekeyDB.instance = new Datastore({ filename: onekeyDBPath, autoload: true })
|
||||
OnekeyDB.instance.setAutocompactionInterval(5000)
|
||||
// OnekeyDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
@ -112,7 +112,7 @@ module.exports.LogDB = class LogDB {
|
||||
constructor() {
|
||||
if (!LogDB.instance) {
|
||||
LogDB.instance = new Datastore({ filename: logDBPath, autoload: true })
|
||||
LogDB.instance.setAutocompactionInterval(5000)
|
||||
// LogDB.instance.setAutocompactionInterval(5000)
|
||||
}
|
||||
}
|
||||
getInstance() {
|
||||
|
@ -1,50 +1,28 @@
|
||||
<template>
|
||||
<div class="mobile_float_menu_container">
|
||||
<div
|
||||
class="draggable_ball"
|
||||
:style="styleObject"
|
||||
@touchstart="startDrag"
|
||||
@click.stop="handleClick"
|
||||
>
|
||||
<el-icon><Calendar /></el-icon>
|
||||
</div>
|
||||
<el-drawer
|
||||
v-model="showMenu"
|
||||
direction="ttb"
|
||||
:with-header="false"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:modal="false"
|
||||
modal-class="keyboard_drawer"
|
||||
>
|
||||
<ul class="keyboard">
|
||||
<li
|
||||
v-for="item in keys"
|
||||
:key="item.key"
|
||||
:class="['key', { long_press: item.type === LONG_PRESS }]"
|
||||
@click="handleClickKey(item)"
|
||||
>
|
||||
<div :class="{ active: (item.key === 'Ctrl' && longPressCtrl) || (item.key === 'Alt' && longPressAlt) }">
|
||||
{{ item.key }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="key placeholder" />
|
||||
<li class="key placeholder" />
|
||||
</ul>
|
||||
</el-drawer>
|
||||
<ul class="keyboard">
|
||||
<li
|
||||
v-for="item in keys"
|
||||
:key="item.key"
|
||||
:class="['key', { long_press: item.type === LONG_PRESS }]"
|
||||
@click="handleClickKey(item)"
|
||||
>
|
||||
<div :class="{ active: (item.key === 'Ctrl' && longPressCtrl) || (item.key === 'Alt' && longPressAlt) }">
|
||||
{{ item.key }}
|
||||
</div>
|
||||
</li>
|
||||
<li class="key placeholder" />
|
||||
<li class="key placeholder" />
|
||||
<li class="key placeholder" />
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { Calendar } from '@element-plus/icons-vue'
|
||||
import { ref } from 'vue'
|
||||
import { virtualKeyType } from '@/utils/enum'
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defineProps({
|
||||
longPressCtrl: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@ -57,23 +35,21 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['update:show', 'click-key',])
|
||||
|
||||
let showMenu = computed({
|
||||
get: () => props.show,
|
||||
set: (newVal) => emit('update:show', newVal) })
|
||||
|
||||
const { LONG_PRESS, SINGLE_PRESS } = virtualKeyType
|
||||
const keys = ref([
|
||||
{ key: 'Ctrl+C', ascii: null, type: SINGLE_PRESS, ansi: '\x03' },
|
||||
{ key: 'Ctrl+A', ascii: null, type: SINGLE_PRESS, ansi: '\x01' },
|
||||
{ key: 'Ctrl+E', ascii: null, type: SINGLE_PRESS, ansi: '\x05' },
|
||||
{ key: 'Ctrl+L', ascii: null, type: SINGLE_PRESS, ansi: '\x0C' },
|
||||
{ key: 'Ctrl+R', ascii: null, type: SINGLE_PRESS, ansi: '\x12' },
|
||||
{ key: ':wq', ascii: null, type: SINGLE_PRESS, ansi: ':wq\r' },
|
||||
{ key: ':q!', ascii: null, type: SINGLE_PRESS, ansi: ':q!\r' },
|
||||
{ key: 'dd', ascii: null, type: SINGLE_PRESS, ansi: 'dd\r' },
|
||||
{ key: 'Ctrl', ascii: null, type: LONG_PRESS, ansi: '' },
|
||||
{ key: 'Esc', ascii: 27, type: SINGLE_PRESS, ansi: '\x1B' },
|
||||
{ key: 'Tab', ascii: 9, type: SINGLE_PRESS, ansi: '\x09' },
|
||||
{ key: 'Ctrl', ascii: null, type: LONG_PRESS, ansi: '' },
|
||||
{ key: 'Backspace', ascii: 8, type: SINGLE_PRESS, ansi: '\x7F' },
|
||||
// { key: 'Delete', ascii: 46, type: SINGLE_PRESS, ansi: '\x1B[3~' },
|
||||
{ key: '←', ascii: 37, type: SINGLE_PRESS, ansi: '\x1B[D' },
|
||||
{ key: '↑', ascii: 38, type: SINGLE_PRESS, ansi: '\x1B[A' },
|
||||
{ key: '↓', ascii: 40, type: SINGLE_PRESS, ansi: '\x1B[B' },
|
||||
{ key: '→', ascii: 39, type: SINGLE_PRESS, ansi: '\x1B[C' },
|
||||
{ key: 'Home', ascii: 36, type: SINGLE_PRESS, ansi: '\x1B[H' },
|
||||
{ key: 'End', ascii: 35, type: SINGLE_PRESS, ansi: '\x1B[F' },
|
||||
{ key: 'PageUp', ascii: 33, type: SINGLE_PRESS, ansi: '\x1B[5~' },
|
||||
{ key: 'PageDown', ascii: 34, type: SINGLE_PRESS, ansi: '\x1B[6~' },
|
||||
{ key: 'Alt', ascii: null, type: LONG_PRESS, ansi: '' },
|
||||
{ key: 'F1', ascii: 112, type: SINGLE_PRESS, ansi: '\x1BOP' },
|
||||
{ key: 'F2', ascii: 113, type: SINGLE_PRESS, ansi: '\x1BOQ' },
|
||||
@ -87,170 +63,51 @@ const keys = ref([
|
||||
{ key: 'F10', ascii: 121, type: SINGLE_PRESS, ansi: '\x1B[21~' },
|
||||
{ key: 'F11', ascii: 122, type: SINGLE_PRESS, ansi: '\x1B[23~' },
|
||||
{ key: 'F12', ascii: 123, type: SINGLE_PRESS, ansi: '\x1B[24~' },
|
||||
{ key: 'Backspace', ascii: 8, type: SINGLE_PRESS, ansi: '\x7F' },
|
||||
{ key: 'Delete', ascii: 46, type: SINGLE_PRESS, ansi: '\x1B[3~' },
|
||||
{ key: '↑', ascii: 38, type: SINGLE_PRESS, ansi: '\x1B[A' },
|
||||
{ key: '→', ascii: 39, type: SINGLE_PRESS, ansi: '\x1B[C' },
|
||||
{ key: 'Home', ascii: 36, type: SINGLE_PRESS, ansi: '\x1B[H' },
|
||||
{ key: 'End', ascii: 35, type: SINGLE_PRESS, ansi: '\x1B[F' },
|
||||
{ key: '↓', ascii: 40, type: SINGLE_PRESS, ansi: '\x1B[B' },
|
||||
{ key: '←', ascii: 37, type: SINGLE_PRESS, ansi: '\x1B[D' },
|
||||
{ key: 'PageUp', ascii: 33, type: SINGLE_PRESS, ansi: '\x1B[5~' },
|
||||
{ key: 'PageDown', ascii: 34, type: SINGLE_PRESS, ansi: '\x1B[6~' },
|
||||
])
|
||||
|
||||
const handleClickKey = (key) => {
|
||||
emit('click-key', key)
|
||||
}
|
||||
|
||||
const handleClick = () => {
|
||||
showMenu.value = !showMenu.value
|
||||
// if (!dragging || (Math.abs(initialX - x.value) < 10 && Math.abs(initialY - y.value) < 10)) {
|
||||
// }
|
||||
}
|
||||
|
||||
const radius = 20 // 悬浮球的半径
|
||||
const x = ref(window.innerWidth - radius * 2) // 初始化位置在屏幕右下角
|
||||
const y = ref(window.innerHeight - radius * 2)
|
||||
|
||||
const styleObject = ref({
|
||||
position: 'fixed',
|
||||
top: `${ y.value }px`,
|
||||
left: `${ x.value }px`,
|
||||
cursor: 'grab',
|
||||
userSelect: 'none',
|
||||
width: `${ radius * 2 }px`, // 悬浮球的直径
|
||||
height: `${ radius * 2 }px`,
|
||||
borderRadius: '50%',
|
||||
backgroundColor: '#42b983',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: 'white',
|
||||
fontSize: '14px',
|
||||
zIndex: '1000'
|
||||
})
|
||||
|
||||
let startX = 0
|
||||
let startY = 0
|
||||
let dragging = false
|
||||
let initialX = 0 // 初始化点击位置X
|
||||
let initialY = 0 // 初始化点击位置Y
|
||||
|
||||
const startDrag = (event) => {
|
||||
const touchEvent = event.type.includes('touch') ? event.touches[0] : event
|
||||
dragging = true
|
||||
initialX = touchEvent.clientX
|
||||
initialY = touchEvent.clientY
|
||||
startX = touchEvent.clientX - x.value
|
||||
startY = touchEvent.clientY - y.value
|
||||
if (event.type.includes('touch')) {
|
||||
document.addEventListener('touchmove', onDragging)
|
||||
document.addEventListener('touchend', stopDrag)
|
||||
} else {
|
||||
document.addEventListener('mousemove', onDragging)
|
||||
document.addEventListener('mouseup', stopDrag)
|
||||
}
|
||||
// event.preventDefault()
|
||||
}
|
||||
|
||||
const onDragging = (event) => {
|
||||
if (dragging) {
|
||||
const moveEvent = event.type.includes('touch') ? event.touches[0] : event
|
||||
let newX = moveEvent.clientX - startX
|
||||
let newY = moveEvent.clientY - startY
|
||||
|
||||
// 边界检查以保持悬浮球至少露出一半
|
||||
newX = Math.max(newX, -radius) // 允许悬浮球露出一半
|
||||
newX = Math.min(newX, window.innerWidth - radius) // 确保右侧至少露出一半
|
||||
newY = Math.max(newY, -radius) // 允许悬浮球露出一半
|
||||
newY = Math.min(newY, window.innerHeight - radius) // 确保底部至少露出一半
|
||||
|
||||
x.value = newX
|
||||
y.value = newY
|
||||
styleObject.value.top = `${ y.value }px`
|
||||
styleObject.value.left = `${ x.value }px`
|
||||
}
|
||||
}
|
||||
|
||||
const stopDrag = (event) => {
|
||||
dragging = false
|
||||
if (event.type.includes('touch')) {
|
||||
document.removeEventListener('touchmove', onDragging)
|
||||
document.removeEventListener('touchend', stopDrag)
|
||||
} else {
|
||||
document.removeEventListener('mousemove', onDragging)
|
||||
document.removeEventListener('mouseup', stopDrag)
|
||||
}
|
||||
}
|
||||
|
||||
// 确保组件在初始加载时位于右下角
|
||||
onMounted(() => {
|
||||
x.value = window.innerWidth - radius * 2
|
||||
y.value = window.innerHeight - radius * 2
|
||||
styleObject.value.top = `${ y.value }px`
|
||||
styleObject.value.left = `${ x.value }px`
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
x.value = window.innerWidth - radius * 2
|
||||
y.value = window.innerHeight - radius * 2
|
||||
styleObject.value.top = `${ y.value }px`
|
||||
styleObject.value.left = `${ x.value }px`
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style scoped lang="scss">
|
||||
.mobile_float_menu_container {
|
||||
.draggable_ball {
|
||||
transition: background-color 0.3s;
|
||||
&:active,
|
||||
&:touch-active {
|
||||
background-color: #333;
|
||||
cursor: grabbing;
|
||||
}
|
||||
height: 55px;
|
||||
padding-top: 5px;
|
||||
overflow-y: auto;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.keyboard_drawer {
|
||||
height: 150px;
|
||||
.el-drawer {
|
||||
height: 100%!important;
|
||||
.el-drawer__header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.el-drawer__body {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
.keyboard {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
.key.placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
.keyboard {
|
||||
list-style: none;
|
||||
.key {
|
||||
width: 25%;
|
||||
height: 25px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
.key.placeholder {
|
||||
opacity: 0;
|
||||
}
|
||||
.key {
|
||||
width: 76px;
|
||||
min-height: 15px;
|
||||
font-size: 12px;
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 6px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.long_press {
|
||||
.active {
|
||||
// color: red;
|
||||
font-weight: bolder;
|
||||
text-decoration: underline;
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 8px;
|
||||
// margin-bottom: 6px;
|
||||
// border: 1px solid #cccccc5b;
|
||||
// border-radius: 2px;
|
||||
}
|
||||
.long_press {
|
||||
.active {
|
||||
// color: red;
|
||||
font-weight: bolder;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
}</style>
|
||||
|
@ -158,6 +158,12 @@
|
||||
@ping-data="getPingData"
|
||||
@reset-long-press="resetLongPress"
|
||||
/>
|
||||
<FloatMenu
|
||||
v-if="isMobileScreen"
|
||||
:long-press-ctrl="longPressCtrl"
|
||||
:long-press-alt="longPressAlt"
|
||||
@click-key="handleClickVirtualKeyboard"
|
||||
/>
|
||||
<Sftp
|
||||
v-if="showSftp"
|
||||
ref="sftpRefs"
|
||||
@ -179,14 +185,6 @@
|
||||
/>
|
||||
|
||||
<TerminalSetting v-model:show="showSetting" />
|
||||
|
||||
<FloatMenu
|
||||
v-if="isMobileScreen"
|
||||
v-model:show="showFloatMenu"
|
||||
:long-press-ctrl="longPressCtrl"
|
||||
:long-press-alt="longPressAlt"
|
||||
@click-key="handleClickVirtualKeyboard"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -228,7 +226,6 @@ 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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user