admin firs step

This commit is contained in:
Roo
2026-03-23 21:43:40 +00:00
parent 309a72cc0b
commit cddcd34ba9
47 changed files with 22698 additions and 19 deletions

View File

@@ -0,0 +1,335 @@
import { ref, computed } from 'vue'
import { useAuthStore } from '~/stores/auth'
// Types
export interface HealthMetrics {
total_assets: number
total_organizations: number
critical_alerts_24h: number
system_status: 'healthy' | 'degraded' | 'critical'
uptime_percentage: number
response_time_ms: number
database_connections: number
active_users: number
last_updated: string
}
export interface SystemAlert {
id: string
severity: 'info' | 'warning' | 'critical'
title: string
description: string
timestamp: string
component: string
resolved: boolean
}
export interface HealthMonitorState {
metrics: HealthMetrics | null
alerts: SystemAlert[]
loading: boolean
error: string | null
lastUpdated: Date | null
}
// Mock data for development/testing
const generateMockMetrics = (): HealthMetrics => {
return {
total_assets: Math.floor(Math.random() * 10000) + 5000,
total_organizations: Math.floor(Math.random() * 500) + 100,
critical_alerts_24h: Math.floor(Math.random() * 10),
system_status: Math.random() > 0.8 ? 'degraded' : Math.random() > 0.95 ? 'critical' : 'healthy',
uptime_percentage: 99.5 + (Math.random() * 0.5 - 0.25), // 99.25% - 99.75%
response_time_ms: Math.floor(Math.random() * 100) + 50,
database_connections: Math.floor(Math.random() * 50) + 10,
active_users: Math.floor(Math.random() * 1000) + 500,
last_updated: new Date().toISOString()
}
}
const generateMockAlerts = (count: number = 5): SystemAlert[] => {
const severities: SystemAlert['severity'][] = ['info', 'warning', 'critical']
const components = ['Database', 'API Gateway', 'Redis', 'PostgreSQL', 'Docker', 'Network', 'Authentication', 'File Storage']
const titles = [
'High memory usage detected',
'Database connection pool exhausted',
'API response time above threshold',
'Redis cache miss rate increased',
'Disk space running low',
'Network latency spike',
'Authentication service slow response',
'Backup job failed'
]
const alerts: SystemAlert[] = []
for (let i = 0; i < count; i++) {
const severity = severities[Math.floor(Math.random() * severities.length)]
const isResolved = Math.random() > 0.7
alerts.push({
id: `alert_${Date.now()}_${i}`,
severity,
title: titles[Math.floor(Math.random() * titles.length)],
description: `Detailed description of the ${severity} alert in the ${components[Math.floor(Math.random() * components.length)]} component.`,
timestamp: new Date(Date.now() - Math.random() * 24 * 60 * 60 * 1000).toISOString(), // Within last 24 hours
component: components[Math.floor(Math.random() * components.length)],
resolved: isResolved
})
}
return alerts
}
// API Service
class HealthMonitorApiService {
private baseUrl = 'http://localhost:8000/api/v1/admin' // Should come from environment config
private delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
// Get health metrics
async getHealthMetrics(): Promise<HealthMetrics> {
// In a real implementation, this would call the actual API
// const response = await fetch(`${this.baseUrl}/health-monitor`, {
// headers: this.getAuthHeaders()
// })
//
// if (!response.ok) {
// throw new Error(`HTTP ${response.status}: ${response.statusText}`)
// }
//
// return await response.json()
await this.delay(800) // Simulate network delay
// For now, return mock data
return generateMockMetrics()
}
// Get system alerts
async getSystemAlerts(options?: {
severity?: SystemAlert['severity']
resolved?: boolean
limit?: number
}): Promise<SystemAlert[]> {
await this.delay(500)
let alerts = generateMockAlerts(10)
if (options?.severity) {
alerts = alerts.filter(alert => alert.severity === options.severity)
}
if (options?.resolved !== undefined) {
alerts = alerts.filter(alert => alert.resolved === options.resolved)
}
if (options?.limit) {
alerts = alerts.slice(0, options.limit)
}
return alerts
}
// Get auth headers (for real API calls)
private getAuthHeaders(): Record<string, string> {
const authStore = useAuthStore()
const headers: Record<string, string> = {
'Content-Type': 'application/json'
}
if (authStore.token) {
headers['Authorization'] = `Bearer ${authStore.token}`
}
// Add geographical scope headers
if (authStore.getScopeId) {
headers['X-Scope-Id'] = authStore.getScopeId.toString()
}
if (authStore.getRegionCode) {
headers['X-Region-Code'] = authStore.getRegionCode
}
if (authStore.getScopeLevel) {
headers['X-Scope-Level'] = authStore.getScopeLevel
}
return headers
}
}
// Composable
export const useHealthMonitor = () => {
const state = ref<HealthMonitorState>({
metrics: null,
alerts: [],
loading: false,
error: null,
lastUpdated: null
})
const apiService = new HealthMonitorApiService()
// Computed properties
const systemStatusColor = computed(() => {
if (!state.value.metrics) return 'grey'
switch (state.value.metrics.system_status) {
case 'healthy': return 'green'
case 'degraded': return 'orange'
case 'critical': return 'red'
default: return 'grey'
}
})
const systemStatusIcon = computed(() => {
if (!state.value.metrics) return 'mdi-help-circle'
switch (state.value.metrics.system_status) {
case 'healthy': return 'mdi-check-circle'
case 'degraded': return 'mdi-alert-circle'
case 'critical': return 'mdi-alert-octagon'
default: return 'mdi-help-circle'
}
})
const criticalAlerts = computed(() => {
return state.value.alerts.filter(alert => alert.severity === 'critical' && !alert.resolved)
})
const warningAlerts = computed(() => {
return state.value.alerts.filter(alert => alert.severity === 'warning' && !alert.resolved)
})
const formattedUptime = computed(() => {
if (!state.value.metrics) return 'N/A'
return `${state.value.metrics.uptime_percentage.toFixed(2)}%`
})
const formattedResponseTime = computed(() => {
if (!state.value.metrics) return 'N/A'
return `${state.value.metrics.response_time_ms}ms`
})
// Actions
const fetchHealthMetrics = async () => {
state.value.loading = true
state.value.error = null
try {
const metrics = await apiService.getHealthMetrics()
state.value.metrics = metrics
state.value.lastUpdated = new Date()
} catch (error) {
state.value.error = error instanceof Error ? error.message : 'Failed to fetch health metrics'
console.error('Error fetching health metrics:', error)
// Fallback to mock data
state.value.metrics = generateMockMetrics()
} finally {
state.value.loading = false
}
}
const fetchSystemAlerts = async (options?: {
severity?: SystemAlert['severity']
resolved?: boolean
limit?: number
}) => {
state.value.loading = true
state.value.error = null
try {
const alerts = await apiService.getSystemAlerts(options)
state.value.alerts = alerts
} catch (error) {
state.value.error = error instanceof Error ? error.message : 'Failed to fetch system alerts'
console.error('Error fetching system alerts:', error)
// Fallback to mock data
state.value.alerts = generateMockAlerts(5)
} finally {
state.value.loading = false
}
}
const refreshAll = async () => {
await Promise.all([
fetchHealthMetrics(),
fetchSystemAlerts()
])
}
const markAlertAsResolved = async (alertId: string) => {
// In a real implementation, this would call an API endpoint
// await apiService.resolveAlert(alertId)
// Update local state
const alertIndex = state.value.alerts.findIndex(alert => alert.id === alertId)
if (alertIndex !== -1) {
state.value.alerts[alertIndex].resolved = true
}
}
const dismissAlert = (alertId: string) => {
// Remove alert from local state (frontend only)
state.value.alerts = state.value.alerts.filter(alert => alert.id !== alertId)
}
// Initialize
const initialize = () => {
refreshAll()
}
return {
// State
state: computed(() => state.value),
metrics: computed(() => state.value.metrics),
alerts: computed(() => state.value.alerts),
loading: computed(() => state.value.loading),
error: computed(() => state.value.error),
lastUpdated: computed(() => state.value.lastUpdated),
// Computed
systemStatusColor,
systemStatusIcon,
criticalAlerts,
warningAlerts,
formattedUptime,
formattedResponseTime,
// Actions
fetchHealthMetrics,
fetchSystemAlerts,
refreshAll,
markAlertAsResolved,
dismissAlert,
initialize,
// Helper functions
getAlertColor: (severity: SystemAlert['severity']) => {
switch (severity) {
case 'info': return 'blue'
case 'warning': return 'orange'
case 'critical': return 'red'
default: return 'grey'
}
},
getAlertIcon: (severity: SystemAlert['severity']) => {
switch (severity) {
case 'info': return 'mdi-information'
case 'warning': return 'mdi-alert'
case 'critical': return 'mdi-alert-circle'
default: return 'mdi-help-circle'
}
},
formatTimestamp: (timestamp: string) => {
const date = new Date(timestamp)
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
}
}
}
export default useHealthMonitor