fix(ops): modern fiber status hero when GenieACS has no data (tech-3 ONUs)
Fibre ONUs on unpolled OLTs (tech-3 XGS-PON, e.g. olt3/172.17.192.6) have no GenieACS `device`, so the modern topo card AND the "Do Stuff en direct" block — both gated on `device` — rendered nothing, leaving a stuck "Chargement ACS…", a stale "Unauthorized" modem-diag, and static titles. But dostuff gives full live status for these ONUs. - New modern fiber hero (v-if="isFibre && !device"): topology strip (Internet→OLT→ ONT) + online/offline pill + colored Rx/Tx signal + distance/uptime/mgmt(link)/ WAN/VoIP/IPTV/firmware tiles + copy-for-ticket + refresh — driven by the live OLT read (dostuff), auto-loaded on mount (2.5s grace for ACS to fill `device` first, so ACS-covered ONUs keep their native card; no double fetch). - Suppressed the misleading stuck "Chargement diagnostic ACS…" for fibre (hero owns the state) and confirmed the heavy Playwright modem-diag stays v-if="false". Verified: build clean, leak 0; dostuff on the shown ONU (TPLGC4160688 @ 172.17.192.6) returns live state (Hors ligne, uptime 2d12h, mgmt/WAN/VoIP/IPTV) → hero populates. Deployed index.42eea809. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
db03b0cdab
commit
81701724a2
|
|
@ -65,6 +65,42 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- FIBRE sans données ACS (ex. ONU tech-3 sur OLT non supervisée) : vue MODERNE pilotée par le direct OLT
|
||||||
|
(dostuff), auto-chargée au montage. Remplace l'ancien panneau statique. Statut + signal coloré + faits clés. -->
|
||||||
|
<div v-if="isFibre && !device" class="topo-summary">
|
||||||
|
<div class="topo-row">
|
||||||
|
<div class="topo-node"><q-icon name="public" size="22px" :color="fibOnline === true ? 'green-6' : fibOnline === false ? 'red-5' : 'grey-5'" /><div class="topo-cap">Internet</div></div>
|
||||||
|
<div class="topo-link" :class="{ ok: fibOnline === true }"></div>
|
||||||
|
<div class="topo-node"><q-icon name="cell_tower" size="22px" color="blue-grey-6" /><div class="topo-cap">OLT</div><div class="topo-sub">{{ oltLabel }}</div></div>
|
||||||
|
<div class="topo-link" :class="{ ok: fibOnline === true }"></div>
|
||||||
|
<div class="topo-node"><div class="topo-modem"><q-icon name="router" size="22px" color="primary" /><span class="topo-dot" :class="fibOnline === true ? 'on' : fibOnline === false ? 'off' : ''"></span></div><div class="topo-cap">ONT</div><div class="topo-sub" v-if="doc.olt_slot != null">{{ doc.olt_slot }}/{{ doc.olt_port }}/{{ doc.olt_ontid }}</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="topo-badges">
|
||||||
|
<q-badge :color="fibOnline === true ? 'green' : fibOnline === false ? 'red' : 'amber'">{{ fibOnline === true ? 'En ligne' : fibOnline === false ? 'Hors ligne' : 'À vérifier' }}</q-badge>
|
||||||
|
<q-badge v-if="liveF && liveF.ok && liveF.rxPower != null" outline :style="{ color: fibreRxColor(liveF.rxPower), borderColor: fibreRxColor(liveF.rxPower) }">Rx {{ liveF.rxPower }} dBm</q-badge>
|
||||||
|
<span v-if="liveFLoading" class="text-caption text-deep-purple-6"><q-spinner-dots size="16px" /> Interrogation de l'OLT en direct… (~30 s)</span>
|
||||||
|
<span v-else-if="liveF && !liveF.ok" class="text-caption text-grey-6">{{ liveF.error }}</span>
|
||||||
|
<span v-else-if="!liveF" class="text-caption text-grey-5">via OLT en direct</span>
|
||||||
|
<q-space />
|
||||||
|
<q-btn flat dense no-caps size="sm" color="grey-7" icon="content_copy" label="Ticket" @click="copyForTicket"><q-tooltip>Copier un résumé pour le ticket</q-tooltip></q-btn>
|
||||||
|
<q-btn flat dense round size="sm" icon="sync" :loading="liveFLoading" @click="fetchLiveF" title="Réinterroger l'OLT" />
|
||||||
|
</div>
|
||||||
|
<div v-if="liveF && liveF.ok" class="dv-grid">
|
||||||
|
<div class="dv-tile" v-if="liveF.rxPower != null"><div class="dv-tl"><q-icon name="network_check" size="14px" /> Signal Rx/Tx</div><div class="dv-tv" :style="{ color: fibreRxColor(liveF.rxPower) }">{{ liveF.rxPower }}<span v-if="liveF.txPower != null"> / {{ liveF.txPower }}</span> dBm</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.distance != null"><div class="dv-tl"><q-icon name="straighten" size="14px" /> Distance</div><div class="dv-tv">{{ liveF.distance }} m</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.uptime"><div class="dv-tl"><q-icon name="schedule" size="14px" /> Uptime</div><div class="dv-tv">{{ liveF.uptime }}</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.managementIp"><div class="dv-tl"><q-icon name="settings" size="14px" /> Gestion</div><a :href="'https://' + liveF.managementIp + '/'" target="_blank" class="dv-tv dv-link">{{ liveF.managementIp }}</a></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.wanIp"><div class="dv-tl"><q-icon name="public" size="14px" /> WAN</div><div class="dv-tv">{{ liveF.wanIp }}</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.profileId"><div class="dv-tl"><q-icon name="speed" size="14px" /> Profil</div><div class="dv-tv">{{ liveF.profileId }}</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.voip"><div class="dv-tl"><q-icon name="call" size="14px" /> VoIP</div><div class="dv-tv">{{ liveF.voip }}</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.iptv"><div class="dv-tl"><q-icon name="live_tv" size="14px" /> IPTV</div><div class="dv-tv">{{ liveF.iptv }}</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.firmware"><div class="dv-tl"><q-icon name="memory" size="14px" /> Firmware</div><div class="dv-tv">{{ liveF.firmware }}</div></div>
|
||||||
|
<div class="dv-tile" v-if="liveF.lastDown"><div class="dv-tl dv-warn"><q-icon name="power_off" size="14px" /> Dern. coupure</div><div class="dv-tv">{{ liveF.lastDown }}</div></div>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="!liveFLoading && liveF && !liveF.ok" class="dv-wan-ph"><q-icon name="info" size="16px" color="grey-5" /> {{ liveF.error || 'OLT injoignable' }}</div>
|
||||||
|
<div v-else-if="liveFLoading && !liveF" class="dv-wan-ph"><q-icon name="cell_tower" size="16px" color="grey-4" /> Lecture des données OLT en direct…</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Do Stuff en direct (F) : interroge l'OLT via n8n (comme F) — remonte VoIP / IPTV / distance / WAN / profil de
|
<!-- Do Stuff en direct (F) : interroge l'OLT via n8n (comme F) — remonte VoIP / IPTV / distance / WAN / profil de
|
||||||
ligne que le poller passif n'expose pas. À la demande (~30 s). + « Copier pour le ticket » (bouton copy de F). -->
|
ligne que le poller passif n'expose pas. À la demande (~30 s). + « Copier pour le ticket » (bouton copy de F). -->
|
||||||
<div v-if="device && doc.serial_number && doc.olt_ip" class="dsf">
|
<div v-if="device && doc.serial_number && doc.olt_ip" class="dsf">
|
||||||
|
|
@ -325,8 +361,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="doc.serial_number && !device" class="q-mt-md text-caption text-grey-5">
|
<div v-else-if="doc.serial_number && !device && !isFibre && deviceLoading" class="q-mt-md text-caption text-grey-5">
|
||||||
<q-spinner size="14px" class="q-mr-xs" v-if="deviceLoading" /> Chargement diagnostic ACS...
|
<q-spinner size="14px" class="q-mr-xs" /> Chargement diagnostic ACS...
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Diagnostic modem avancé (modem-bridge / Playwright) — DÉSACTIVÉ « pour le moment » : trop lourd (~15 s).
|
<!-- ── Diagnostic modem avancé (modem-bridge / Playwright) — DÉSACTIVÉ « pour le moment » : trop lourd (~15 s).
|
||||||
|
|
@ -646,6 +682,15 @@ const isWireless = computed(() => {
|
||||||
const s = ((d.brand || '') + ' ' + (d.model || '') + ' ' + (d.equipment_type || '')).toLowerCase()
|
const s = ((d.brand || '') + ' ' + (d.model || '') + ' ' + (d.equipment_type || '')).toLowerCase()
|
||||||
return /ubiquit|airmax|litebeam|nanostation|nanobridge|rocket|powerbeam|bullet|cambium|airos|\bap\b|sans.?fil|wireless/.test(s)
|
return /ubiquit|airmax|litebeam|nanostation|nanobridge|rocket|powerbeam|bullet|cambium|airos|\bap\b|sans.?fil|wireless/.test(s)
|
||||||
})
|
})
|
||||||
|
// Fibre (ONT/ONU) : a une OLT (olt_ip) OU un type/modèle fibre OU des données optiques ACS.
|
||||||
|
const isFibre = computed(() => {
|
||||||
|
const d = props.doc
|
||||||
|
if (d.olt_ip) return true
|
||||||
|
if (/\b(ont|onu|gpon|fibre?|fiber)\b/i.test(String(d.equipment_type || '') + ' ' + String(d.model || ''))) return true
|
||||||
|
return !!(device.value && device.value.opticalStatus)
|
||||||
|
})
|
||||||
|
// Statut fibre MODERNE quand l'ACS (GenieACS) n'a rien : piloté par le direct OLT (liveF/dostuff). En ligne ? état.
|
||||||
|
const fibOnline = computed(() => (liveF.value && liveF.value.ok) ? liveF.value.online : null)
|
||||||
const airos = ref(null); const airosLoading = ref(false)
|
const airos = ref(null); const airosLoading = ref(false)
|
||||||
async function fetchAiros () {
|
async function fetchAiros () {
|
||||||
airos.value = null; airosLoading.value = true
|
airos.value = null; airosLoading.value = true
|
||||||
|
|
@ -1098,6 +1143,9 @@ onMounted(async () => {
|
||||||
loadWanHistory()
|
loadWanHistory()
|
||||||
}
|
}
|
||||||
loadWStatus() // sans-fil : état rapide RADIUS au chargement (self-guard isWireless)
|
loadWStatus() // sans-fil : état rapide RADIUS au chargement (self-guard isWireless)
|
||||||
|
// Fibre sans ACS (ONU tech-3 non supervisée) : laisse ~2,5 s à l'ACS pour remplir `device` ; sinon auto-interroge
|
||||||
|
// l'OLT en direct (dostuff) → peuple la vue moderne au lieu du panneau statique. Une seule fois (~30 s).
|
||||||
|
setTimeout(() => { if (isFibre.value && !device.value && props.doc.olt_ip && !liveF.value && !liveFLoading.value) fetchLiveF() }, 2500)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Chargement PARESSEUX : on n'interroge le modem (modem-bridge) que si l'agent déplie « Appareils connectés ».
|
// Chargement PARESSEUX : on n'interroge le modem (modem-bridge) que si l'agent déplie « Appareils connectés ».
|
||||||
|
|
@ -1112,6 +1160,7 @@ watch(() => props.doc.serial_number, sn => {
|
||||||
loadEvents(); loadWanHistory() // rafraîchir la bande dispo/événements pour le nouvel appareil
|
loadEvents(); loadWanHistory() // rafraîchir la bande dispo/événements pour le nouvel appareil
|
||||||
}
|
}
|
||||||
loadWStatus()
|
loadWStatus()
|
||||||
|
setTimeout(() => { if (isFibre.value && !device.value && props.doc.olt_ip && !liveF.value && !liveFLoading.value) fetchLiveF() }, 2500)
|
||||||
})
|
})
|
||||||
onUnmounted(() => { stopWanLive(); stopEthLive() })
|
onUnmounted(() => { stopWanLive(); stopEthLive() })
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user