130 lines
3.2 KiB
Vue
130 lines
3.2 KiB
Vue
<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>
|