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
@@ -6,7 +6,7 @@ const dashboardService = new DashboardService();
export class DashboardController {
async getSummary(req: Request, res: Response): Promise<void> {
try {
const summary = await dashboardService.getSummary();
const summary = await dashboardService.getSummary(req.session.userId);
res.status(200).json(summary);
} catch (error: any) {
console.error('[DashboardController] 获取仪表盘统计失败:', error);
@@ -3,7 +3,7 @@ import type {
DashboardActionBreakdownItem,
DashboardActivityTrendPoint,
DashboardCountByType,
DashboardSummary,
DashboardStaticSummary,
DashboardTopConnection,
} from './dashboard.types';
import type { AuditLogActionType } from '../types/audit.types';
@@ -75,7 +75,7 @@ const safeParseAuditDetails = (raw: string | null): ParsedAuditDetails | null =>
}
};
export const getDashboardSummary = async (): Promise<DashboardSummary> => {
export const getDashboardSummary = async (): Promise<DashboardStaticSummary> => {
const db = await getDbInstance();
const now = Math.floor(Date.now() / 1000);
const since7d = now - (DASHBOARD_WINDOW_DAYS - 1) * DAY_IN_SECONDS;
@@ -1,8 +1,32 @@
import { getDashboardSummary } from './dashboard.repository';
import type { DashboardSummary } from './dashboard.types';
import { clientStates } from '../websocket/state';
import { sshSuspendService } from '../ssh-suspend/ssh-suspend.service';
export class DashboardService {
async getSummary(): Promise<DashboardSummary> {
return getDashboardSummary();
async getSummary(userId?: number): Promise<DashboardSummary> {
const summary = await getDashboardSummary();
const activeStates = Array.from(clientStates.values()).filter((state) => !state.isSuspendedByService);
const systemActiveSshSessions = activeStates.length;
const systemStatusStreams = activeStates.filter((state) => !!state.statusIntervalId).length;
const currentUserActiveSshSessions = typeof userId === 'number'
? activeStates.filter((state) => state.ws.userId === userId).length
: 0;
const suspendedMetrics = sshSuspendService.getSessionMetrics(userId);
return {
...summary,
liveMetrics: {
currentUser: {
activeSshSessions: currentUserActiveSshSessions,
suspendedSessions: suspendedMetrics.currentUserSuspendedSessions,
},
system: {
activeSshSessions: systemActiveSshSessions,
suspendedSessions: suspendedMetrics.totalSuspendedSessions,
statusStreams: systemStatusStreams,
},
},
};
}
}
@@ -35,7 +35,23 @@ export interface DashboardActionBreakdownItem {
count: number;
}
export interface DashboardSummary {
export interface DashboardCurrentUserLiveMetrics {
activeSshSessions: number;
suspendedSessions: number;
}
export interface DashboardSystemLiveMetrics {
activeSshSessions: number;
suspendedSessions: number;
statusStreams: number;
}
export interface DashboardLiveMetrics {
currentUser: DashboardCurrentUserLiveMetrics;
system: DashboardSystemLiveMetrics;
}
export interface DashboardStaticSummary {
totals: DashboardTotals;
sshOutcomes24h: DashboardSshOutcomes24h;
connectionTypes: DashboardCountByType[];
@@ -43,3 +59,7 @@ export interface DashboardSummary {
activityTrend7d: DashboardActivityTrendPoint[];
topConnections: DashboardTopConnection[];
}
export interface DashboardSummary extends DashboardStaticSummary {
liveMetrics: DashboardLiveMetrics;
}
@@ -211,6 +211,28 @@ export class SshSuspendService extends EventEmitter {
return sessionsInfo;
}
getSessionMetrics(userId?: number): {
totalSuspendedSessions: number;
currentUserSuspendedSessions: number;
} {
let totalSuspendedSessions = 0;
let currentUserSuspendedSessions = 0;
for (const [ownerUserId, sessions] of this.suspendedSessions.entries()) {
const sessionCount = sessions.size;
totalSuspendedSessions += sessionCount;
if (typeof userId === 'number' && ownerUserId === userId) {
currentUserSuspendedSessions += sessionCount;
}
}
return {
totalSuspendedSessions,
currentUserSuspendedSessions,
};
}
/**
* 恢复指定的挂起会话。
* @param userId 用户ID。
@@ -450,4 +472,4 @@ export class SshSuspendService extends EventEmitter {
}
// 单例模式导出
export const sshSuspendService = new SshSuspendService();
export const sshSuspendService = new SshSuspendService();