/** * Store Pinia pour la gestion des IPs */ import { defineStore } from 'pinia' import { ref, computed } from 'vue' import axios from 'axios' export const useIPStore = defineStore('ip', () => { // État const ips = ref([]) const selectedIP = ref(null) const loading = ref(false) const error = ref(null) const stats = ref({ total: 0, online: 0, offline: 0, known: 0, unknown: 0 }) const lastScanDate = ref(null) const scanProgress = ref({ current: 0, total: 0, currentIP: null }) const isScanning = ref(false) const uiConfig = ref({ cell_size: 30 }) // Filtres const filters = ref({ showOnline: true, showOffline: true, showKnown: true, showUnknown: true, showFree: true }) // WebSocket const ws = ref(null) const wsConnected = ref(false) // Computed const filteredIPs = computed(() => { return ips.value.filter(ip => { // Filtrer par statut if (ip.last_status === 'online' && !filters.value.showOnline) return false if (ip.last_status === 'offline' && !filters.value.showOffline) return false // Filtrer par connu/inconnu if (ip.known && !filters.value.showKnown) return false if (!ip.known && !filters.value.showUnknown) return false // Filtrer IP libres (pas de last_status) if (!ip.last_status && !filters.value.showFree) return false return true }) }) // Actions async function fetchUIConfig() { try { const response = await axios.get('/api/config/ui') uiConfig.value = response.data // Appliquer la taille des cellules, de la police et de l'espacement via variables CSS document.documentElement.style.setProperty('--cell-size', `${response.data.cell_size}px`) document.documentElement.style.setProperty('--font-size', `${response.data.font_size}px`) document.documentElement.style.setProperty('--cell-gap', `${response.data.cell_gap}px`) } catch (err) { console.error('Erreur chargement config UI:', err) } } async function reloadConfig() { try { const response = await axios.post('/api/config/reload') if (response.data.success) { // Appliquer la nouvelle config UI uiConfig.value = response.data.ui document.documentElement.style.setProperty('--cell-size', `${response.data.ui.cell_size}px`) document.documentElement.style.setProperty('--font-size', `${response.data.ui.font_size}px`) document.documentElement.style.setProperty('--cell-gap', `${response.data.ui.cell_gap}px`) return response.data.message } } catch (err) { console.error('Erreur rechargement config:', err) throw err } } async function fetchIPs() { loading.value = true error.value = null try { const response = await axios.get('/api/ips/') ips.value = response.data await fetchStats() } catch (err) { error.value = err.message console.error('Erreur chargement IPs:', err) } finally { loading.value = false } } async function fetchStats() { try { const response = await axios.get('/api/ips/stats/summary') stats.value = response.data } catch (err) { console.error('Erreur chargement stats:', err) } } async function updateIP(ipAddress, data) { try { const response = await axios.put(`/api/ips/${ipAddress}`, data) // Mettre à jour dans le store const index = ips.value.findIndex(ip => ip.ip === ipAddress) if (index !== -1) { ips.value[index] = response.data } if (selectedIP.value?.ip === ipAddress) { selectedIP.value = response.data } return response.data } catch (err) { error.value = err.message throw err } } async function deleteIP(ipAddress) { try { await axios.delete(`/api/ips/${ipAddress}`) // Retirer du store const index = ips.value.findIndex(ip => ip.ip === ipAddress) if (index !== -1) { ips.value.splice(index, 1) } if (selectedIP.value?.ip === ipAddress) { selectedIP.value = null } await fetchStats() } catch (err) { error.value = err.message throw err } } async function getIPHistory(ipAddress, hours = 24) { try { const response = await axios.get(`/api/ips/${ipAddress}/history?hours=${hours}`) return response.data } catch (err) { console.error('Erreur chargement historique:', err) throw err } } async function startScan() { try { await axios.post('/api/scan/start') } catch (err) { error.value = err.message throw err } } function selectIP(ip) { selectedIP.value = ip } function clearSelection() { selectedIP.value = null } // WebSocket function connectWebSocket() { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' const wsUrl = `${protocol}//${window.location.host}/ws` ws.value = new WebSocket(wsUrl) ws.value.onopen = () => { console.log('WebSocket connecté') wsConnected.value = true // Heartbeat toutes les 30s setInterval(() => { if (ws.value?.readyState === WebSocket.OPEN) { ws.value.send('ping') } }, 30000) } ws.value.onmessage = (event) => { try { const message = JSON.parse(event.data) handleWebSocketMessage(message) } catch (err) { console.error('Erreur parsing WebSocket:', err) } } ws.value.onerror = (error) => { console.error('Erreur WebSocket:', error) wsConnected.value = false } ws.value.onclose = () => { console.log('WebSocket déconnecté') wsConnected.value = false // Reconnexion après 5s setTimeout(connectWebSocket, 5000) } } function handleWebSocketMessage(message) { console.log('Message WebSocket:', message) switch (message.type) { case 'scan_start': // Notification début de scan isScanning.value = true scanProgress.value = { current: 0, total: message.total || 0, currentIP: null } break case 'scan_progress': // Progression du scan if (message.current) scanProgress.value.current = message.current if (message.total) scanProgress.value.total = message.total if (message.ip) scanProgress.value.currentIP = message.ip break case 'scan_complete': // Rafraîchir les données après scan isScanning.value = false lastScanDate.value = new Date() scanProgress.value = { current: 0, total: 0, currentIP: null } fetchIPs() if (message.stats) stats.value = message.stats break case 'ip_update': // Mise à jour d'une IP const updatedIP = ips.value.find(ip => ip.ip === message.data.ip) if (updatedIP) { Object.assign(updatedIP, message.data) } break case 'new_ip': // Nouvelle IP détectée fetchIPs() // Recharger pour être sûr break } } function disconnectWebSocket() { if (ws.value) { ws.value.close() ws.value = null wsConnected.value = false } } return { // État ips, selectedIP, loading, error, stats, filters, wsConnected, lastScanDate, scanProgress, isScanning, uiConfig, // Computed filteredIPs, // Actions fetchUIConfig, reloadConfig, fetchIPs, fetchStats, updateIP, deleteIP, getIPHistory, startScan, selectIP, clearSelection, connectWebSocket, disconnectWebSocket } })