Volver al centro de ayuda

Guía de plantillas de fichas Hotspot

Hotspot, Plantilla SnFix Manager · Actualizado: 10/09/2026 11:04

Cómo crear o modificar un tema tomando uno existente como base

Aplicación: SnFix Manager
Carpeta de plantillas: templates/fichas/
Formato de salida: HTML, PDF e impresión directa

1. Arquitectura de un tema

Cada tema de fichas está compuesto por dos archivos con el mismo nombre base:

Archivo Función
mi-tema.html.j2 Plantilla principal (layout). Define el CSS, la grilla de impresión y recorre las filas de fichas con Jinja2.
mi-tema.html Partial (fragmento) de una sola ficha. Se incluye dentro de cada celda de la grilla. Contiene usuario, contraseña/PIN, límites y precio.
templates/fichas/
├── ocean.html.j2 ← layout + estilos
├── ocean.html ← contenido de cada ficha
├── emerald-logo.html.j2
├── emerald-logo.html
└── ...
La aplicación detecta automáticamente todos los archivos *.html.j2 y los muestra en el selector Plantilla de la ventana Imprimir Fichas.

2. Variables disponibles en Jinja2

El servicio FichaTemplateService pasa estas variables al renderizar:

Variable Tipo Descripción
title string Título principal (ej. nombre del hotspot).
subtitle string Subtítulo (ej. identidad del router).
footer string Texto del pie de página.
columns int (1–5) Número de columnas por fila en la hoja.
rows lista de listas Matriz de fichas agrupadas por filas para la tabla.
ficha dict Datos de una ficha individual (solo dentro del partial).
logo_url string Logo del RouterBoard en base64 (data:image/...). Vacío si no hay logo.
generated_at string Fecha/hora de generación (dd/mm/YYYY HH:MM).

Campos del objeto ficha

Campo Descripción
ficha.usernameNombre de usuario.
ficha.passwordContraseña o PIN.
ficha.profilePerfil Hotspot asignado.
ficha.usage_limitTiempo de uso (ej. "1 hora"). Muestra "—" si no aplica.
ficha.time_limitLímite de sesión / uptime.
ficha.pricePrecio de la ficha.
ficha.status"Activo" o "Deshabilitado".
Si ficha.username == ficha.password, la ficha es de tipo PIN (usuario y clave iguales). En ese caso se recomienda mostrar solo el PIN con estilo destacado.

3. Estructura del layout (.html.j2)

El archivo principal sigue este patrón mínimo:

<!-- mi-tema.html.j2 -->
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            background: #ffffff;   /* fondo blanco para impresión */
        }
        table.grid { width: 100%; border-collapse: separate; border-spacing: 6px; }
        td.ticket {
            width: {{ (100 / columns)|int }}%;
            page-break-inside: avoid;
        }
        /* ... más estilos del tema ... */
        @page { size: Letter; margin: 0; }
        @media print {
            .ficha-header {
                -webkit-print-color-adjust: exact;
                print-color-adjust: exact;
            }
        }
    </style>
</head>
<body>
    <table class="grid">
        {% for row in rows %}
        <tr>
            {% for ficha in row %}
            {% if ficha %}
            <td class="ticket">
                {% include "mi-tema.html" %}
            </td>
            {% endif %}
            {% endfor %}
        </tr>
        {% endfor %}
    </table>
    <div class="footer">
        {{ footer|default("Conserve esta ficha para acceder al servicio de internet.") }}
    </div>
</body>
</html>
El nombre en {% include "mi-tema.html" %} debe coincidir exactamente con el partial que creaste. Si el layout se llama ocean.html.j2, el include debe ser {% include "ocean.html" %}.

4. Estructura del partial (.html)

Ejemplo simplificado del contenido de cada ficha:

<!-- mi-tema.html -->
<div class="ficha-card">
    <div class="ficha-header">
        {% if title %}
        <div class="ficha-title">{{ title }}</div>
        {% if subtitle %}
        <div class="ficha-subtitle">{{ subtitle }}</div>
        {% endif %}
        {% else %}
        <div class="ficha-title">Acceso WiFi</div>
        {% endif %}
    </div>

    <div class="ficha-body">
        {% if ficha.username != ficha.password %}
        <div class="ficha-item">
            <span class="ficha-label">Usuario:</span>
            <span class="ficha-value">{{ ficha.username }}</span>
        </div>
        <div class="ficha-item">
            <span class="ficha-label">Contraseña:</span>
            <span class="ficha-value">{{ ficha.password }}</span>
        </div>
        {% else %}
        <div class="ficha-item ficha-pin">
            <span class="ficha-label">PIN:</span>
            <span class="ficha-value ficha-pin-value">{{ ficha.password }}</span>
        </div>
        {% endif %}

        {% if ficha.usage_limit and ficha.usage_limit != "—" %}
        <div class="ficha-item">
            <span class="ficha-label">Tiempo de uso:</span>
            <span class="ficha-value">{{ ficha.usage_limit }}</span>
        </div>
        {% endif %}

        {% if ficha.price and ficha.price != "—" %}
        <div class="ficha-item">
            <span class="ficha-label">Precio:</span>
            <span class="ficha-value">{{ ficha.price }}</span>
        </div>
        {% endif %}
    </div>
</div>

5. Pasos para crear un tema nuevo (copiando uno existente)

Elegir un tema base

Recomendados para empezar:

  • ocean.html.j2 — diseño horizontal con banner de color.
  • emerald-logo.html.j2 — incluye soporte de logo del RouterBoard.
  • ejemplo.html.j2 — múltiples variantes de color con clases CSS.

Copiar los dos archivos

Desde templates/fichas/, copia el par base y renómbralo. Ejemplo:

ocean.html.j2      →  mi-cafe.html.j2
ocean.html         →  mi-cafe.html

Actualizar el include en el layout

En mi-cafe.html.j2, cambia la línea del include:

{% include "mi-cafe.html" %}

Modificar colores y estilos

En el bloque <style> del .html.j2, ajusta:

  • Colores de borde, fondo de tarjeta y encabezado.
  • Tipografía (font-family, tamaños).
  • Bordes redondeados, sombras y espaciado.

Ejemplo: cambiar un tema azul a marrón café:

border-left-color: #2563eb;   →   border-left-color: #92400e;
color: #2563eb;               →   color: #92400e;
background: #dbeafe;          →   background: #fef3c7;

Ajustar el partial si cambias la estructura HTML

Si agregas nuevas secciones (iconos, logo, columnas internas), modifica mi-cafe.html y define las clases CSS correspondientes en el layout.

Probar en la aplicación

  1. Abre Imprimir Fichas en el RouterBoard conectado.
  2. Selecciona tu plantilla en el combo Plantilla.
  3. Marca unas fichas de prueba y usa Exportar HTML o Exportar PDF.
  4. Revisa con 1, 2 y 3 columnas para verificar el ancho de cada celda.

6. Variante con logo del RouterBoard

Los temas emerald-logo e indigo-logo muestran el logo configurado en el RouterBoard. No necesitas leer archivos manualmente: la aplicación resuelve logo_path y entrega logo_url listo para usar.

<div class="ficha-logo">
    {% if logo_url %}
    <img src="{{ logo_url }}" alt="Logo">
    {% else %}
    <!-- Icono SVG de respaldo -->
    {% endif %}
</div>
Concepto Detalle
logo_path Ruta relativa guardada en la base de datos del RouterBoard (ej. images/routerboards/1.png).
Carpeta física data/images/routerboards/ (ROUTERBOARD_LOGOS_DIR)
logo_url Data URI base64 generada por FichaTemplateService. Funciona en HTML exportado, PDF e impresión sin rutas externas.
Formatos de logo soportados: PNG, JPG, JPEG, GIF, BMP y WEBP. Asigna el logo desde el diálogo de edición del RouterBoard.

7. Consejos para impresión

  • Mantén background: #ffffff en body para ahorrar tinta.
  • Usa page-break-inside: avoid en td.ticket para no cortar fichas entre páginas.
  • Para colores de fondo en impresión, agrega: -webkit-print-color-adjust: exact; print-color-adjust: exact;
  • El ancho de columna se calcula con {{ (100 / columns)|int }}%.
  • Tamaño de página: @page { size: Letter; margin: 0; }
  • Usa SVG embebido para iconos decorativos (no dependen de archivos externos).

8. Temas incluidos de referencia

Plantilla Estilo Logo
default.html.j2Clásico con borde punteadoNo
ejemplo.html.j2Horizontal, 7 variantes de color CSSNo
ocean.html.j2Azul/cyan, banner con icono WiFiNo
sunset.html.j2Naranja/ámbar, icono solNo
forest.html.j2Verde, icono árbol lateralNo
midnight.html.j2Oscuro/dorado, luna y estrellasNo
coral.html.j2Rosa/coral, diseño centradoNo
emerald-logo.html.j2Verde esmeralda, logo en headerSí
indigo-logo.html.j2Índigo/violeta, logo circularSí

9. Solución de problemas

Problema Causa probable Solución
La plantilla no aparece en el selector Archivo sin extensión .html.j2 Renombra el layout a mi-tema.html.j2
Error al renderizar / include not found Nombre incorrecto en {% include %} Verifica que el partial exista y coincida el nombre
Colores no se imprimen Navegador/impresora omite fondos Agrega print-color-adjust: exact en CSS
Logo no aparece RouterBoard sin logo asignado Configura logo en edición del RouterBoard; usa tema *-logo
Ficha se corta en dos páginas Falta regla CSS de page-break Agrega page-break-inside: avoid a td.ticket

10. Resumen rápido

  1. Copia un par .html.j2 + .html existente.
  2. Renombra ambos archivos con el mismo nombre base.
  3. Actualiza el {% include %} en el layout.
  4. Modifica CSS (colores, tipografía, bordes) en el .html.j2.
  5. Ajusta el HTML del partial si cambias la estructura de la ficha.
  6. Para logo, usa {% if logo_url %} con imagen base64.
  7. Prueba exportando HTML/PDF con distintas columnas.
SnFix Hotspot Manager — Guía de plantillas de fichas — Generado automáticamente

¿Necesitas gestionar licencias?

Accede a tu panel para comprar, vincular equipos y descargar archivos de licencia.

Iniciar sesión