Files
sub2api/frontend/src/stores/adminSettings.ts
IanShaw027 337a188660 feat(前端状态): 添加运维监控状态管理和路由
- 新增 adminSettings store 管理 ops 配置状态
- 注册 adminSettings store 到全局 store
- 添加 ops 监控相关路由(dashboard, alerts, realtime, settings)
2026-01-09 20:59:02 +08:00

131 lines
4.0 KiB
TypeScript

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { adminAPI } from '@/api'
export const useAdminSettingsStore = defineStore('adminSettings', () => {
const loaded = ref(false)
const loading = ref(false)
const readCachedBool = (key: string, defaultValue: boolean): boolean => {
try {
const raw = localStorage.getItem(key)
if (raw === 'true') return true
if (raw === 'false') return false
} catch {
// ignore localStorage failures
}
return defaultValue
}
const writeCachedBool = (key: string, value: boolean) => {
try {
localStorage.setItem(key, value ? 'true' : 'false')
} catch {
// ignore localStorage failures
}
}
const readCachedString = (key: string, defaultValue: string): string => {
try {
const raw = localStorage.getItem(key)
if (typeof raw === 'string' && raw.length > 0) return raw
} catch {
// ignore localStorage failures
}
return defaultValue
}
const writeCachedString = (key: string, value: string) => {
try {
localStorage.setItem(key, value)
} catch {
// ignore localStorage failures
}
}
// Default open, but honor cached value to reduce UI flicker on first paint.
const opsMonitoringEnabled = ref(readCachedBool('ops_monitoring_enabled_cached', true))
const opsRealtimeMonitoringEnabled = ref(readCachedBool('ops_realtime_monitoring_enabled_cached', true))
const opsQueryModeDefault = ref(readCachedString('ops_query_mode_default_cached', 'auto'))
async function fetch(force = false): Promise<void> {
if (loaded.value && !force) return
if (loading.value) return
loading.value = true
try {
const settings = await adminAPI.settings.getSettings()
opsMonitoringEnabled.value = settings.ops_monitoring_enabled ?? true
writeCachedBool('ops_monitoring_enabled_cached', opsMonitoringEnabled.value)
opsRealtimeMonitoringEnabled.value = settings.ops_realtime_monitoring_enabled ?? true
writeCachedBool('ops_realtime_monitoring_enabled_cached', opsRealtimeMonitoringEnabled.value)
opsQueryModeDefault.value = settings.ops_query_mode_default || 'auto'
writeCachedString('ops_query_mode_default_cached', opsQueryModeDefault.value)
loaded.value = true
} catch (err) {
// Keep cached/default value: do not "flip" the UI based on a transient fetch failure.
loaded.value = true
console.error('[adminSettings] Failed to fetch settings:', err)
} finally {
loading.value = false
}
}
function setOpsMonitoringEnabledLocal(value: boolean) {
opsMonitoringEnabled.value = value
writeCachedBool('ops_monitoring_enabled_cached', value)
loaded.value = true
}
function setOpsRealtimeMonitoringEnabledLocal(value: boolean) {
opsRealtimeMonitoringEnabled.value = value
writeCachedBool('ops_realtime_monitoring_enabled_cached', value)
loaded.value = true
}
function setOpsQueryModeDefaultLocal(value: string) {
opsQueryModeDefault.value = value || 'auto'
writeCachedString('ops_query_mode_default_cached', opsQueryModeDefault.value)
loaded.value = true
}
// Keep UI consistent if we learn that ops is disabled via feature-gated 404s.
// (event is dispatched from the axios interceptor)
let eventHandlerCleanup: (() => void) | null = null
function initializeEventListeners() {
if (eventHandlerCleanup) return
try {
const handler = () => {
setOpsMonitoringEnabledLocal(false)
}
window.addEventListener('ops-monitoring-disabled', handler)
eventHandlerCleanup = () => {
window.removeEventListener('ops-monitoring-disabled', handler)
}
} catch {
// ignore window access failures (SSR)
}
}
if (typeof window !== 'undefined') {
initializeEventListeners()
}
return {
loaded,
loading,
opsMonitoringEnabled,
opsRealtimeMonitoringEnabled,
opsQueryModeDefault,
fetch,
setOpsMonitoringEnabledLocal,
setOpsRealtimeMonitoringEnabledLocal,
setOpsQueryModeDefaultLocal
}
})