| <div class="channels-page">
|
| <div class="section-header">
|
| <div class="search-box" style="flex: 1; max-width: 400px;">
|
| <input
|
| type="text"
|
| id="channelSearch"
|
| placeholder="搜索频道..."
|
| class="form-control"
|
| >
|
| </div>
|
| <button id="refreshChannels" class="btn btn-primary">
|
| 🔄 刷新
|
| </button>
|
| </div>
|
|
|
| <div id="channelStats" class="stats-box">加载中...</div>
|
|
|
| <div id="channelList" class="channel-grid"></div>
|
| </div>
|
|
|
| <script>
|
| (function() {
|
| 'use strict';
|
|
|
| const API = window.location.origin;
|
| let channels = [];
|
| let searchTimeout;
|
|
|
| function renderBatch(list, startIdx = 0, batchSize = 50) {
|
| const el = document.getElementById('channelList');
|
| if (!el) return;
|
|
|
| if (startIdx === 0) {
|
| el.innerHTML = '';
|
| }
|
|
|
| const fragment = document.createDocumentFragment();
|
| const endIdx = Math.min(startIdx + batchSize, list.length);
|
|
|
| for (let i = startIdx; i < endIdx; i++) {
|
| const ch = list[i];
|
| const div = document.createElement('div');
|
| div.className = 'channel-card';
|
| div.innerHTML = `
|
| <div class="channel-name">${ch.name}</div>
|
| <div class="channel-actions">
|
| <button class="btn btn-success" data-no="${ch.no}" data-action="play">▶️ 播放</button>
|
| <button class="btn btn-primary" data-id="${ch.id}" data-action="epg">📅 节目表</button>
|
| </div>
|
| `;
|
| fragment.appendChild(div);
|
| }
|
|
|
| el.appendChild(fragment);
|
|
|
| if (endIdx < list.length) {
|
| requestAnimationFrame(() => renderBatch(list, endIdx, batchSize));
|
| }
|
| }
|
|
|
|
|
| document.addEventListener('click', (e) => {
|
| const btn = e.target.closest('button[data-action]');
|
| if (!btn) return;
|
|
|
| const action = btn.dataset.action;
|
|
|
| if (action === 'play') {
|
| const no = btn.dataset.no;
|
| console.log('🎬 频道列表点击播放,频道号:', no);
|
|
|
| if (window.navigateToPlayer) {
|
| console.log('✅ navigateToPlayer 存在,调用并传递 autoPlay=true');
|
|
|
| window.navigateToPlayer(no, true);
|
| } else {
|
| console.error('❌ navigateToPlayer 函数不存在');
|
| }
|
| } else if (action === 'epg') {
|
| const id = btn.dataset.id;
|
| const today = new Date();
|
| const jst = new Date(today.toLocaleString('en-US', { timeZone: 'Asia/Tokyo' }));
|
| const date = jst.toISOString().split('T')[0];
|
| if (window.navigateToEPG) {
|
| window.navigateToEPG(id, date);
|
| }
|
| }
|
| });
|
|
|
| async function load() {
|
| const stats = document.getElementById('channelStats');
|
| const list = document.getElementById('channelList');
|
|
|
| if (stats) stats.textContent = '加载中...';
|
| if (list) list.innerHTML = '<div class="skeleton skeleton-card"></div>'.repeat(4);
|
|
|
| try {
|
| const res = await fetch(`${API}/api/list`);
|
| if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
|
| const data = await res.json();
|
| if (!data.success) throw new Error(data.error || '加载失败');
|
|
|
| channels = data.channels || [];
|
|
|
| if (stats) {
|
| const cacheIcon = data.cached ? '✅' : '🔄';
|
| stats.innerHTML = `📊 共 <strong style="color: var(--primary);">${data.count || 0}</strong> 个频道 ${cacheIcon}`;
|
| }
|
|
|
| renderBatch(channels);
|
|
|
| if (window.MediaGatewayUtils) {
|
| window.MediaGatewayUtils.showNotification(`加载 ${data.count} 个频道`, 'success');
|
| }
|
| } catch (e) {
|
| if (list) list.innerHTML = `<div style="grid-column: 1/-1; text-align: center; padding: 40px; color: var(--danger);">❌ 加载失败: ${e.message}</div>`;
|
| if (stats) stats.innerHTML = '<strong style="color: var(--danger);">❌ 加载失败</strong>';
|
| }
|
| }
|
|
|
| function search(e) {
|
| clearTimeout(searchTimeout);
|
| searchTimeout = setTimeout(() => {
|
| const q = e.target.value.toLowerCase().trim();
|
|
|
| if (!q) {
|
| renderBatch(channels);
|
| return;
|
| }
|
|
|
| const filtered = channels.filter(ch =>
|
| ch.name.toLowerCase().includes(q) ||
|
| String(ch.no).includes(q)
|
| );
|
|
|
| renderBatch(filtered);
|
| }, 300);
|
| }
|
|
|
| window.initChannelsPage = function() {
|
| load();
|
|
|
| const searchInput = document.getElementById('channelSearch');
|
| const refreshBtn = document.getElementById('refreshChannels');
|
|
|
| if (searchInput) searchInput.addEventListener('input', search);
|
| if (refreshBtn) refreshBtn.addEventListener('click', load);
|
| };
|
|
|
| setTimeout(window.initChannelsPage, 0);
|
| })();
|
| </script> |