Files
mengyaconnect/mengyaconnect-frontend/src/components/MobileFab.vue
2026-05-16 19:19:39 +08:00

130 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="fab-wrap mobile-only">
<div v-show="fabOpen" class="fab-backdrop" @click="fabOpen = false"></div>
<div class="fab-actions" :class="{ open: fabOpen }">
<button class="fab-action" type="button" @click="openPanel('scripts')">
<span class="fab-action-label">脚本管理</span>
<span class="fab-action-icon"></span>
</button>
<button class="fab-action" type="button" @click="openPanel('commands')">
<span class="fab-action-label">快捷命令</span>
<span class="fab-action-icon"></span>
</button>
<button class="fab-action" type="button" @click="openPanel('ssh')">
<span class="fab-action-label">SSH 配置</span>
<span class="fab-action-icon"></span>
</button>
<button class="fab-action" type="button" @click="openPanel('connect')">
<span class="fab-action-label">新建连接</span>
<span class="fab-action-icon"></span>
</button>
</div>
<button class="fab-btn" :class="{ open: fabOpen }" type="button" @click="fabOpen = !fabOpen">
{{ fabOpen ? "" : "" }}
</button>
</div>
</template>
<script setup>
import { useUI } from "../composables/useUI";
const { fabOpen, openPanel } = useUI();
</script>
<style scoped>
.fab-wrap {
display: none;
position: fixed;
bottom: 16px;
right: 16px;
z-index: 90;
flex-direction: column;
align-items: flex-end;
gap: 10px;
}
.fab-backdrop {
position: fixed;
inset: 0;
z-index: -1;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px);
}
.fab-actions {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8px;
pointer-events: none;
opacity: 0;
transform: translateY(10px);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.fab-actions.open {
pointer-events: auto;
opacity: 1;
transform: translateY(0);
}
.fab-action {
display: flex;
align-items: center;
gap: 8px;
border: none;
background: none;
cursor: pointer;
padding: 0;
}
.fab-action-label {
background: var(--bg-2);
color: var(--text-1);
font-size: 13px;
padding: 6px 12px;
border-radius: 8px;
border: 1px solid var(--border);
white-space: nowrap;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
font-family: inherit;
}
.fab-action-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--bg-2);
color: var(--accent);
border: 1px solid var(--border-hi);
display: flex;
align-items: center;
justify-content: center;
font-size: 17px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
flex-shrink: 0;
}
.fab-action:active .fab-action-icon { background: var(--accent-dim); }
.fab-btn {
width: 52px;
height: 52px;
border-radius: 50%;
border: 1px solid var(--border-hi);
background: var(--bg-2);
color: var(--accent);
font-size: 24px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(63, 185, 80, 0.2);
transition: transform 0.2s ease, background 0.2s ease;
flex-shrink: 0;
}
.fab-btn.open { background: var(--bg-3); transform: rotate(45deg); }
.fab-btn:active { transform: scale(0.94); }
@media (max-width: 768px) {
.fab-wrap { display: flex; }
}
</style>