feat(frontend): 增强工作台快捷指令与仪表盘能力

补充快捷指令动态变量解析与编辑弹窗一键插入,
统一列表执行、粘贴到终端和批量发送的处理链路

扩展快捷命令右键菜单动作,并为文件面板新增
多根目录资源管理器式侧栏浏览体验

为首页 dashboard 增加当前用户与系统总览双视角的
实时会话指标展示,并同步更新相关知识库记录
This commit is contained in:
yinjianm
2026-03-26 01:39:42 +08:00
parent a2ac4047d9
commit 3f6e2bffc6
35 changed files with 2206 additions and 190 deletions
@@ -0,0 +1,116 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import type { DashboardSummary } from '../types/server.types';
const props = defineProps<{
summary: DashboardSummary | null;
isLoading: boolean;
}>();
const { t, locale } = useI18n();
const summaryAvailable = computed(() => !!props.summary);
const liveMetricGroups = computed(() => {
if (!props.summary) {
return [];
}
return [
{
key: 'currentUser',
title: t('dashboard.liveMetrics.currentUser.title'),
description: t('dashboard.liveMetrics.currentUser.description'),
items: [
{
key: 'activeSshSessions',
label: t('dashboard.liveMetrics.labels.activeSshSessions'),
value: formatNumber(props.summary.liveMetrics.currentUser.activeSshSessions),
icon: 'fa-terminal',
iconClass: 'text-emerald-400',
},
{
key: 'suspendedSessions',
label: t('dashboard.liveMetrics.labels.suspendedSessions'),
value: formatNumber(props.summary.liveMetrics.currentUser.suspendedSessions),
icon: 'fa-pause-circle',
iconClass: 'text-amber-400',
},
],
},
{
key: 'system',
title: t('dashboard.liveMetrics.system.title'),
description: t('dashboard.liveMetrics.system.description'),
items: [
{
key: 'activeSshSessions',
label: t('dashboard.liveMetrics.labels.activeSshSessions'),
value: formatNumber(props.summary.liveMetrics.system.activeSshSessions),
icon: 'fa-network-wired',
iconClass: 'text-sky-400',
},
{
key: 'suspendedSessions',
label: t('dashboard.liveMetrics.labels.suspendedSessions'),
value: formatNumber(props.summary.liveMetrics.system.suspendedSessions),
icon: 'fa-layer-group',
iconClass: 'text-violet-400',
},
{
key: 'statusStreams',
label: t('dashboard.liveMetrics.labels.statusStreams'),
value: formatNumber(props.summary.liveMetrics.system.statusStreams),
icon: 'fa-heart-pulse',
iconClass: 'text-rose-400',
},
],
},
];
});
function formatNumber(value: number): string {
return new Intl.NumberFormat(locale.value).format(value);
}
</script>
<template>
<section class="rounded-xl border border-border bg-card p-4 shadow-sm">
<div class="mb-4">
<h2 class="text-lg font-medium">{{ t('dashboard.liveMetrics.title') }}</h2>
<p class="text-sm text-text-secondary">{{ t('dashboard.liveMetrics.description') }}</p>
</div>
<div v-if="isLoading && !summaryAvailable" class="text-center text-text-secondary">
{{ t('common.loading') }}
</div>
<div v-else class="grid grid-cols-1 gap-4 xl:grid-cols-2">
<section
v-for="group in liveMetricGroups"
:key="group.key"
class="rounded-xl border border-border/70 bg-header/30 p-4"
>
<div class="mb-3">
<h3 class="text-base font-medium">{{ group.title }}</h3>
<p class="text-sm text-text-secondary">{{ group.description }}</p>
</div>
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
<article
v-for="item in group.items"
:key="item.key"
class="rounded-lg border border-border/70 bg-card/80 px-3 py-3"
>
<div class="mb-2 flex items-center justify-between gap-2">
<span class="text-sm text-text-secondary">{{ item.label }}</span>
<i :class="['fas', item.icon, item.iconClass]"></i>
</div>
<p class="text-2xl font-semibold leading-none">{{ item.value }}</p>
</article>
</div>
</section>
</div>
</section>
</template>