fix(studio): cambiar de tenant o de agente no recargaba la pantalla

Al navegar de /tenants/2 a /tenants/3, vue-router reusa la misma instancia
del componente porque es la misma ruta con otro parámetro. onMounted no
vuelve a dispararse, así que la vista seguía mostrando los agentes del
tenant anterior.

Las tres vistas tenían el mismo problema: TenantAgentes, AgenteDetail y
Uso. Ahora reaccionan al parámetro (watch con immediate) en vez de al
montaje.

En AgenteDetail se limpia el estado antes de pedir los datos nuevos: si no,
durante la carga se ven los documentos, canales y conversaciones del agente
anterior bajo el nombre del nuevo, que es peor que una pantalla vacía.

Verificado navegando de verdad entre dos tenants con agentes distintos: la
lista pasa de "Ventas T2" a "Soporte T3 / Cobros T3".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-15 08:01:37 -05:00
co-authored by Claude Sonnet 5
parent a25329c7b1
commit ad3458bb71
6 changed files with 64 additions and 39 deletions
+27 -8
View File
@@ -1,5 +1,5 @@
<script setup>
import { computed, onMounted, ref } from 'vue'
import { computed, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { api } from '../lib/api.js'
import { apiUmind, contexto } from '../lib/contexto.js'
@@ -330,13 +330,32 @@ function formatearFecha(iso) {
}
}
onMounted(async () => {
try {
await Promise.all([cargarAgente(), cargarDocumentos(), cargarSesiones(), cargarTools(), cargarCanales(), cargarConexiones(), cargarEventos()])
} catch (e) {
error.value = e.message
}
})
// Se observan los dos parámetros: al saltar de un agente a otro (o a un
// agente de otro tenant) vue-router reusa la instancia y onMounted no vuelve
// a correr, así que la pantalla quedaba con los datos del agente anterior.
watch(
() => [props.tenantId, props.agenteId],
async () => {
error.value = ''
// Se limpia antes de pedir: si no, durante la carga se ven los datos del
// agente anterior bajo el nombre del nuevo.
agente.value = null
documentos.value = []
sesiones.value = []
historial.value = []
sesionActiva.value = null
tools.value = []
canales.value = []
conexiones.value = []
eventos.value = []
try {
await Promise.all([cargarAgente(), cargarDocumentos(), cargarSesiones(), cargarTools(), cargarCanales(), cargarConexiones(), cargarEventos()])
} catch (e) {
error.value = e.message
}
},
{ immediate: true },
)
</script>
<template>
+6 -2
View File
@@ -1,5 +1,5 @@
<script setup>
import { computed, onMounted, ref } from 'vue'
import { computed, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import { api } from '../lib/api.js'
import { apiUmind, contexto } from '../lib/contexto.js'
@@ -127,7 +127,11 @@ async function eliminarAgente(a) {
await cargar()
}
onMounted(cargar)
// watch con immediate en vez de onMounted: al navegar entre /tenants/2 y
// /tenants/3 vue-router reusa la misma instancia del componente, así que
// onMounted no vuelve a dispararse y la pantalla seguía mostrando los agentes
// del tenant anterior.
watch(() => props.id, cargar, { immediate: true })
</script>
<template>
+4 -2
View File
@@ -1,5 +1,5 @@
<script setup>
import { computed, onMounted, ref } from 'vue'
import { computed, ref, watch } from 'vue'
import { api } from '../lib/api.js'
import { apiUmind } from '../lib/contexto.js'
import UiEmptyState from '../components/ui/UiEmptyState.vue'
@@ -76,7 +76,9 @@ function atajo(dias) {
cargar()
}
onMounted(cargar)
// Ver el comentario en TenantAgentes.vue: la instancia se reusa al cambiar
// de tenant, así que hay que reaccionar al parámetro y no al montaje.
watch(() => props.id, cargar, { immediate: true })
</script>
<template>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>uMind Studio</title>
<script type="module" crossorigin src="/orchestrator/assets/index-CXtokcMG.js"></script>
<script type="module" crossorigin src="/orchestrator/assets/index-DsDQ67K1.js"></script>
<link rel="stylesheet" crossorigin href="/orchestrator/assets/index-DyYio0bD.css">
</head>
<!-- Sin clase de fondo: el color lo pone body en style.css desde los tokens,