新增: 服务器列表右键菜单

- 右键弹出连接编辑删除,复用既有操作链路
- 本地项仅连接,远程项含编辑删除
- 与三点菜单和设置面板互斥展开
This commit is contained in:
lxy
2026-09-28 13:53:37 +08:00
parent 6c59f81b44
commit b488354369
@@ -19,26 +19,49 @@
<span class="col-metric">内存</span> <span class="col-metric">内存</span>
<span class="col-action settings-btn" @click="toggleSettings($event)" title="管理">···</span> <span class="col-action settings-btn" @click="toggleSettings($event)" title="管理">···</span>
</div> </div>
<!-- 表格行 --> <!-- 表格行(右键菜单与行内「...」菜单共用同一组操作,互斥展开) -->
<div <a-dropdown
v-for="p in visibleProfiles" v-for="(p, idx) in visibleProfiles"
:key="p.id" :key="p.id"
class="server-table-row" trigger="contextMenu"
:class="{ active: p.id === activeId }" align-point
@click="handleSelect(p)" :popup-visible="srvCtxMenuIndex === idx"
@popup-visible-change="(v: boolean) => onSrvCtxVisible(idx, v)"
> >
<span class="col-name" :title="stateText(p.id)"><span :class="['dot', stateDotClass(p.id)]" />{{ p.name }}</span> <div
<span class="col-metric" :class="metricWarnClass(p.id, 'disk')" :title="metricTooltip(p.id, 'disk')">{{ sysInfo(p.id)?.diskUsage || '-' }}</span> class="server-table-row"
<span class="col-metric" :class="metricWarnClass(p.id, 'cpu')" :title="metricTooltip(p.id, 'cpu')">{{ sysInfo(p.id)?.cpuUsage || '-' }}</span> :class="{ active: p.id === activeId }"
<span class="col-metric" :class="metricWarnClass(p.id, 'mem')" :title="metricTooltip(p.id, 'mem')">{{ sysInfo(p.id)?.memUsage || '-' }}</span> @click="handleSelect(p)"
<span >
v-if="p.type !== 'local'" <span class="col-name" :title="stateText(p.id)"><span :class="['dot', stateDotClass(p.id)]" />{{ p.name }}</span>
class="col-action more-btn" <span class="col-metric" :class="metricWarnClass(p.id, 'disk')" :title="metricTooltip(p.id, 'disk')">{{ sysInfo(p.id)?.diskUsage || '-' }}</span>
title="更多操作" <span class="col-metric" :class="metricWarnClass(p.id, 'cpu')" :title="metricTooltip(p.id, 'cpu')">{{ sysInfo(p.id)?.cpuUsage || '-' }}</span>
@click.stop="toggleMore(p, $event)" <span class="col-metric" :class="metricWarnClass(p.id, 'mem')" :title="metricTooltip(p.id, 'mem')">{{ sysInfo(p.id)?.memUsage || '-' }}</span>
>···</span> <span
<span v-else class="col-action"></span> v-if="p.type !== 'local'"
</div> class="col-action more-btn"
title="更多操作"
@click.stop="toggleMore(p, $event)"
>···</span>
<span v-else class="col-action"></span>
</div>
<template #content>
<a-doption @click="handleSelect(p)">
<template #icon><icon-computer /></template>
连接
</a-doption>
<template v-if="p.type !== 'local'">
<a-doption @click="handleEdit(p)">
<template #icon><icon-edit /></template>
编辑
</a-doption>
<a-doption class="danger" @click="handleDelete(p)">
<template #icon><icon-close /></template>
删除
</a-doption>
</template>
</template>
</a-dropdown>
</div> </div>
</div> </div>
@@ -268,6 +291,7 @@ function toggleSettings(e: MouseEvent) {
return return
} }
moreOpenId.value = null moreOpenId.value = null
srvCtxMenuIndex.value = -1
const btn = (e.target as HTMLElement).closest<HTMLElement>('.settings-btn') const btn = (e.target as HTMLElement).closest<HTMLElement>('.settings-btn')
if (!btn) return if (!btn) return
settingsPanelStyle.value = calcPopupStyle(btn) settingsPanelStyle.value = calcPopupStyle(btn)
@@ -281,6 +305,7 @@ function toggleMore(p: { id: string; name: string }, e: MouseEvent) {
return return
} }
settingsOpen.value = false settingsOpen.value = false
srvCtxMenuIndex.value = -1
moreOpenId.value = p.id moreOpenId.value = p.id
moreProfile.value = p moreProfile.value = p
const target = (e.target as HTMLElement).closest('.more-btn') as HTMLElement const target = (e.target as HTMLElement).closest('.more-btn') as HTMLElement
@@ -611,6 +636,18 @@ function handleDelete(p: { id: string; name: string }) {
// 删除的是活跃服务器时连接已回落本地,补发切换让视图加载本地根目录 // 删除的是活跃服务器时连接已回落本地,补发切换让视图加载本地根目录
if (wasActive) emit('serverSelect', 'local-default') if (wasActive) emit('serverSelect', 'local-default')
} }
// 服务器项右键菜单(与行内「...」菜单互斥:一方展开强制收起另一方)
const srvCtxMenuIndex = ref(-1)
function onSrvCtxVisible(index: number, visible: boolean) {
srvCtxMenuIndex.value = visible ? index : -1
if (visible) {
moreOpenId.value = null
moreProfile.value = null
settingsOpen.value = false
}
}
</script> </script>
<style scoped> <style scoped>