Pantalla TV del turnero: playlist de videos e imágenes en vez de un solo video
Nueva tabla turnero_tv_media (tipo, url, orden, duracion_segundos) para soportar múltiples videos/imágenes reproducidos en secuencia y en bucle. El video que ya estaba cargado se migró como primer ítem de la playlist. - save_tv_media.php / delete_tv_media.php / reorder_tv_media.php reemplazan a save_tv_video.php (eliminado). - configuracion.php (tab TV): subida múltiple, lista reordenable por arrastre, duración editable por imagen. - display_global.php: el <video> único se reemplaza por un reproductor JS que recorre la playlist — video hasta 'ended', imagen por su duración configurada, y vuelve a empezar al terminar. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
2ba13add34
commit
6254e45e8f
@@ -3,16 +3,21 @@ $_dispCfg = [];
|
||||
try {
|
||||
$__pdo = Database::getInstance()->getConnection();
|
||||
$__rows = $__pdo->query(
|
||||
"SELECT clave, valor FROM lab_config WHERE clave IN ('empresa_nombre','doc_logo_base64','doc_color','turnero_tv_video')"
|
||||
"SELECT clave, valor FROM lab_config WHERE clave IN ('empresa_nombre','doc_logo_base64','doc_color')"
|
||||
)->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
$_dispCfg = $__rows ?: [];
|
||||
} catch (\Throwable $_) {}
|
||||
$_labNombre = htmlspecialchars($_dispCfg['empresa_nombre'] ?? 'Sistema de Turnos');
|
||||
$_labLogo = $_dispCfg['doc_logo_base64'] ?? '';
|
||||
$_labColor = preg_match('/^#[0-9a-fA-F]{3,8}$/', $_dispCfg['doc_color'] ?? '') ? $_dispCfg['doc_color'] : '#1565c0';
|
||||
$_tvVideo = $_dispCfg['turnero_tv_video'] ?? '';
|
||||
if ($_tvVideo && !preg_match('#^https?://#', $_tvVideo)) { $_tvVideo = ''; }
|
||||
$_hasVideo = (bool)$_tvVideo;
|
||||
|
||||
$_tvPlaylist = [];
|
||||
try {
|
||||
$_tvPlaylist = $__pdo->query(
|
||||
"SELECT tipo, url, duracion_segundos FROM turnero_tv_media WHERE activo = 1 ORDER BY orden ASC"
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (\Throwable $_) {}
|
||||
$_hasVideo = (bool)$_tvPlaylist;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
@@ -428,11 +433,7 @@ $_hasVideo = (bool)$_tvVideo;
|
||||
<div class="pac-nombre" id="pac-nombre"></div>
|
||||
</div>
|
||||
<div class="reel-wrap <?= $_hasVideo ? 'has-video' : '' ?>" id="reel-wrap">
|
||||
<div class="reel-inner">
|
||||
<video autoplay muted loop playsinline>
|
||||
<source src="<?= htmlspecialchars($_tvVideo) ?>">
|
||||
</video>
|
||||
</div>
|
||||
<div class="reel-inner" id="tv-playlist"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -456,6 +457,38 @@ $_hasVideo = (bool)$_tvVideo;
|
||||
<script>
|
||||
const BASE_API = '<?= BASE_URL ?>modules/turnero/api/';
|
||||
|
||||
/* ── Playlist TV (videos e imágenes en bucle) ── */
|
||||
const TV_PLAYLIST = <?= json_encode($_tvPlaylist, JSON_UNESCAPED_UNICODE) ?>;
|
||||
(function () {
|
||||
const wrap = document.getElementById('tv-playlist');
|
||||
if (!wrap || !TV_PLAYLIST.length) return;
|
||||
let idx = 0, imgTimer = null;
|
||||
|
||||
function mostrar(i) {
|
||||
clearTimeout(imgTimer);
|
||||
wrap.innerHTML = '';
|
||||
const item = TV_PLAYLIST[i];
|
||||
if (item.tipo === 'video') {
|
||||
const v = document.createElement('video');
|
||||
v.src = item.url; v.autoplay = true; v.muted = true; v.playsInline = true;
|
||||
v.addEventListener('ended', siguiente);
|
||||
v.addEventListener('error', siguiente);
|
||||
wrap.appendChild(v);
|
||||
} else {
|
||||
const img = document.createElement('img');
|
||||
img.src = item.url;
|
||||
img.style.cssText = 'width:100%;height:100%;object-fit:cover';
|
||||
wrap.appendChild(img);
|
||||
imgTimer = setTimeout(siguiente, Math.max(1, item.duracion_segundos || 8) * 1000);
|
||||
}
|
||||
}
|
||||
function siguiente() {
|
||||
idx = (idx + 1) % TV_PLAYLIST.length;
|
||||
mostrar(idx);
|
||||
}
|
||||
mostrar(idx);
|
||||
})();
|
||||
|
||||
function tick() {
|
||||
const d = new Date();
|
||||
document.getElementById('reloj').textContent =
|
||||
|
||||
Reference in New Issue
Block a user