feat: reports page with formatted daily report cards
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="report-card">
|
||||
<div v-if="statsEntries.length" class="report-stats">
|
||||
<div v-for="item in statsEntries" :key="item.key" class="report-stat">
|
||||
<div class="report-stat-value">{{ item.value }}</div>
|
||||
<div class="report-stat-label">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="htmlContent" class="report-body-html" v-html="htmlContent" />
|
||||
|
||||
<pre v-else-if="plainBody" class="report-body-plain">{{ plainBody }}</pre>
|
||||
|
||||
<p v-else-if="summary && summary !== 'Отчёт за сутки'" class="report-fallback">{{ summary }}</p>
|
||||
|
||||
<p v-else class="report-empty">
|
||||
Полный текст отчёта не сохранён (старая версия агента). Обновите ssh-monitor и дождитесь следующего
|
||||
ежедневного отчёта.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import {
|
||||
reportBodyFromDetails,
|
||||
reportHtmlFromDetails,
|
||||
reportStatsFromDetails,
|
||||
sanitizeAgentHtml,
|
||||
type DailyReportStats,
|
||||
} from "../utils/reportDisplay";
|
||||
|
||||
const props = defineProps<{
|
||||
type: string;
|
||||
summary: string;
|
||||
details: Record<string, unknown> | null;
|
||||
}>();
|
||||
|
||||
const stats = computed(() => reportStatsFromDetails(props.details));
|
||||
|
||||
const statLabels: Record<keyof DailyReportStats, string> = {
|
||||
successful_ssh: "Успешных SSH",
|
||||
failed_ssh: "Неудачных SSH",
|
||||
sudo_commands: "Sudo",
|
||||
active_bans: "Активных банов",
|
||||
active_sessions: "Сессий (SSH)",
|
||||
active_sessions_rdp: "Сессий (RDP)",
|
||||
};
|
||||
|
||||
const statsEntries = computed(() => {
|
||||
const s = stats.value;
|
||||
if (!s) return [];
|
||||
const out: { key: string; label: string; value: string | number }[] = [];
|
||||
for (const [key, label] of Object.entries(statLabels)) {
|
||||
const k = key as keyof DailyReportStats;
|
||||
const v = s[k];
|
||||
if (typeof v === "number") {
|
||||
out.push({ key, label, value: v });
|
||||
}
|
||||
}
|
||||
if (Array.isArray(s.unique_users) && s.unique_users.length) {
|
||||
out.push({
|
||||
key: "unique_users",
|
||||
label: "Уникальные логины",
|
||||
value: s.unique_users.length,
|
||||
});
|
||||
}
|
||||
return out;
|
||||
});
|
||||
|
||||
const htmlContent = computed(() => {
|
||||
const raw = reportHtmlFromDetails(props.details);
|
||||
return raw ? sanitizeAgentHtml(raw) : null;
|
||||
});
|
||||
|
||||
const plainBody = computed(() => reportBodyFromDetails(props.details));
|
||||
</script>
|
||||
Reference in New Issue
Block a user