feat: 更新前端UI,增强审计和日志视图功能

This commit is contained in:
caoxiaozhu
2026-05-18 02:51:25 +00:00
parent 35a3783481
commit 9d90bf5299
10 changed files with 3544 additions and 954 deletions

View File

@@ -1,15 +1,20 @@
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import LogTrendChart from '../../components/charts/LogTrendChart.vue'
import DonutChart from '../../components/charts/DonutChart.vue'
import { fetchAgentRuns } from '../../services/agentAssets.js'
import { fetchSystemLogEntries } from '../../services/systemLogs.js'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import { isManagerUser } from '../../utils/accessControl.js'
const POLL_INTERVAL_MS = 5000
import LogTrendChart from '../../components/charts/LogTrendChart.vue'
import DonutChart from '../../components/charts/DonutChart.vue'
import { fetchAgentRuns } from '../../services/agentAssets.js'
import { fetchSystemLogEntries } from '../../services/systemLogs.js'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import {
AGENT_RUN_POLL_INTERVAL_MS,
formatAgentRunElapsed,
formatAgentRunProgress,
resolveAgentRunHeartbeat,
resolveAgentRunStatus
} from '../../utils/agentRunMonitor.js'
import { isManagerUser } from '../../utils/accessControl.js'
const SOURCE_LABELS = {
schedule: '定时任务',
@@ -30,37 +35,13 @@ function formatDateTime(value) {
return date.toLocaleString('zh-CN', { hour12: false })
}
function resolveStatusLabel(status) {
if (status === 'running') {
return '运行中'
}
if (status === 'succeeded') {
return '已完成'
}
if (status === 'failed') {
return '失败'
}
if (status === 'blocked') {
return '待确认'
}
return status || '未知'
}
function resolveStatusTone(status) {
if (status === 'running') {
return 'warning'
}
if (status === 'succeeded') {
return 'success'
}
if (status === 'failed') {
return 'danger'
}
if (status === 'blocked') {
return 'muted'
}
return 'muted'
}
function resolveStatusLabel(run) {
return resolveAgentRunStatus(run).label
}
function resolveStatusTone(run) {
return resolveAgentRunStatus(run).tone
}
function resolveRunSourceLabel(source) {
return SOURCE_LABELS[source] || source || '未标记'
@@ -88,16 +69,20 @@ function resolveRunTitle(run) {
return `Hermes 调用 · ${resolveRunModuleLabel(run)}`
}
function resolveRunLevel(run) {
const progress = run?.route_json?.progress || {}
if (run?.status === 'failed' || run?.error_message) {
return 'ERROR'
}
if (run?.status === 'blocked' || Number(progress.failed_documents || 0) > 0) {
return 'WARN'
}
if (run?.status === 'running') {
return 'INFO'
function resolveRunLevel(run) {
const progress = run?.route_json?.progress || {}
const statusInfo = resolveAgentRunStatus(run)
if (run?.status === 'failed' || run?.error_message) {
return 'ERROR'
}
if (statusInfo.isSuspicious) {
return 'WARN'
}
if (run?.status === 'blocked' || Number(progress.failed_documents || 0) > 0) {
return 'WARN'
}
if (run?.status === 'running') {
return 'INFO'
}
return 'INFO'
}
@@ -115,7 +100,7 @@ function resolveLevelTone(level) {
return 'muted'
}
function formatSummary(summary) {
function formatSummary(summary) {
const text = String(summary || '').trim()
if (!text) {
return '暂无摘要。'
@@ -123,8 +108,39 @@ function formatSummary(summary) {
if (text.length <= 64) {
return text
}
return `${text.slice(0, 64)}...`
}
return `${text.slice(0, 64)}...`
}
function resolveRunSummaryMeta(run) {
const statusInfo = resolveAgentRunStatus(run)
const progressText = formatAgentRunProgress(run)
const elapsedLabel = run?.status === 'running' ? '已运行' : '耗时'
const elapsedText = formatAgentRunElapsed(run)
const parts = [`阶段 ${statusInfo.phaseLabel}`]
if (progressText) {
parts.push(progressText)
}
if (elapsedText !== '—') {
parts.push(`${elapsedLabel} ${elapsedText}`)
}
return parts.join(' · ')
}
function resolveRunStatusNote(run) {
const statusInfo = resolveAgentRunStatus(run)
if (statusInfo.note) {
return statusInfo.note
}
const heartbeat = resolveAgentRunHeartbeat(run)
if (heartbeat.at !== null) {
return `最后心跳 ${formatDateTime(heartbeat.at)}`
}
return '暂无额外状态'
}
function resolveSystemLevelTone(level) {
if (level === 'ERROR' || level === 'CRITICAL') {
@@ -368,9 +384,9 @@ export default {
stopPolling()
pollTimer = window.setInterval(() => {
loadHermesRuns()
loadSystemLogs()
}, POLL_INTERVAL_MS)
}
loadSystemLogs()
}, AGENT_RUN_POLL_INTERVAL_MS)
}
function stopPolling() {
if (pollTimer) {
@@ -442,11 +458,13 @@ export default {
pageSizes,
resolveLevelTone,
resolveRunLevel,
resolveRunModuleLabel,
resolveRunSourceLabel,
resolveRunTitle,
resolveStatusLabel,
resolveStatusTone,
resolveRunModuleLabel,
resolveRunSourceLabel,
resolveRunStatusNote,
resolveRunSummaryMeta,
resolveRunTitle,
resolveStatusLabel,
resolveStatusTone,
resolveSystemLevelTone,
resolveSystemOutcomeTone,
runningRunCount,