最近维护博客的安徽 IPTV 共享页时,有部分小伙伴发现一个挺影响体验的问题:同一个频道的标清、高清、超高清源会默认全部显示,导致表格 rows 密密麻麻堆在一起,排版又乱又难查找。
作为有点强迫症的博主,肯定不能忍这种混乱,于是花了点时间写了个清晰度筛选功能,本文记录一下实现过程~
效果演示


筛选功能核心组件
筛选按钮区域
筛选按钮提供五种筛选模式,用户可根据需求灵活切换,按钮布局清晰、操作便捷:
<div class="iptv-filter-buttons">
<button class="iptv-filter-btn" data-type="all" title="显示所有清晰度的内容">全部显示</button>
<button class="iptv-filter-btn" data-type="clean" title="仅显示当前频道最高清晰度的内容">清爽模式</button>
<button class="iptv-filter-btn" data-type="sd" title="仅显示标清的内容">仅看标清</button>
<button class="iptv-filter-btn" data-type="hd" title="仅显示高清的内容">仅看高清</button>
<button class="iptv-filter-btn" data-type="uhd" title="仅显示超高清的内容">仅看超高清</button>
</div>
频道表格展示
表格采用标准化布局,清晰呈现频道关键信息,每行数据通过类名标记频道名称和清晰度,为筛选功能提供数据支撑:
<div class="iptv-table-wrapper">
<table class="iptv-table" width="100%" border="1" cellpadding="8" cellspacing="0">
<thead>
<tr>
<th width="10%"><strong>序号</strong></th>
<th width="20%"><strong>频道名称</strong></th>
<th width="10%"><strong>频道分类</strong></th>
<th width="10%"><strong>清晰度</strong></th>
<th width="auto"><strong>播放地址</strong></th>
<th width="15%"><strong>贡献者/最后更新</strong></th>
</tr>
</thead>
<tbody class="iptv-table-body multicast">
<tr class="iptv-row channel-安徽卫视 res-sd"><td></td><td>安徽卫视</td><td>卫视频道</td><td><em class="iptv-res sd" title="720 x 576">标清</em></td><td>rtp://238.1.78.42:6208</td><td style="text-align: center;">-<br />24/01/01</td></tr>
<tr class="iptv-row channel-安徽卫视 res-hd"><td></td><td>安徽卫视</td><td>卫视频道</td><td><em class="iptv-res fhd" title="1920 x 1080">高清</em></td><td>rtp://238.1.79.27:4328</td><td style="text-align: center;">-<br />24/01/01</td></tr>
<tr class="iptv-row channel-安徽卫视 res-uhd"><td></td><td>安徽卫视</td><td>卫视频道</td><td><em class="iptv-res fhd" title="3840 x 2160">超高清</em></td><td>rtp://238.1.78.150:7072</td><td style="text-align: center;">-<br />24/01/01</td></tr>
</tbody>
</table>
</div>
核心筛选 JavaScript 代码
JS 代码实现了筛选逻辑、表格样式更新、复制功能等核心交互,确保筛选操作流畅响应:
document.addEventListener('DOMContentLoaded', function() {
const tableBodies = document.querySelectorAll('tbody.iptv-table-body');
tableBodies.forEach(tableBody => {
tableBody.querySelectorAll('.iptv-row').forEach(row => {
row.classList.add('row-visible');
row.classList.remove('row-hidden')
});
updateRowNumbers(tableBody);
updateRowStriping(tableBody)
});
initAllFilters()
});
function updateRowNumbers(tableBody) {
if (!tableBody) return;
const rows = tableBody.querySelectorAll('.iptv-row:not([style*="display: none"])');
rows.forEach((row, index) => {
const firstCell = row.querySelector('td:first-child');
if (firstCell) firstCell.textContent = index + 1
})
}
function updateRowStriping(tableBody) {
if (!tableBody) return;
tableBody.querySelectorAll('.iptv-row').forEach(row => {
row.classList.remove('even-row', 'odd-row')
});
const visibleRows = tableBody.querySelectorAll('.iptv-row:not([style*="display: none"])');
visibleRows.forEach((row, index) => {
if (index % 2 === 0) {
row.classList.add('odd-row')
} else {
row.classList.add('even-row')
}
})
}
function initAllFilters() {
try {
const filterContainers = document.querySelectorAll('.iptv-filter-buttons');
filterContainers.forEach(container => {
const targetTable = container.nextElementSibling?.querySelector('tbody.iptv-table-body');
if (targetTable) {
container.querySelectorAll('.iptv-filter-btn').forEach(button => {
button.addEventListener('click', function() {
const filterType = this.getAttribute('data-type');
filterChannels(container, targetTable, filterType)
})
});
container.querySelector('.iptv-filter-btn[data-type="clean"]')?.click()
}
})
} catch (e) {
console.error('初始化筛选器错误:', e)
}
}
function applyCleanMode(tableBody) {
try {
const allRows = tableBody.querySelectorAll('.iptv-row');
allRows.forEach(row => {
row.style.display = 'none'
});
const channelMap = new Map();
allRows.forEach(row => {
const nameCell = row.querySelector('td:nth-child(2)');
if (nameCell) {
const channelName = nameCell.textContent.trim();
if (!channelMap.has(channelName)) {
channelMap.set(channelName, [])
}
channelMap.get(channelName).push(row)
}
});
channelMap.forEach(rows => {
const uhdRows = rows.filter(row => row.classList.contains('res-uhd'));
const hdRows = rows.filter(row => row.classList.contains('res-hd') || row.classList.contains('res-fhd'));
const sdRows = rows.filter(row => row.classList.contains('res-sd'));
if (uhdRows.length > 0) {
uhdRows.forEach(row => row.style.display = 'table-row');
hdRows.forEach(row => row.style.display = 'table-row')
} else if (hdRows.length > 0) {
hdRows.forEach(row => row.style.display = 'table-row')
} else if (sdRows.length > 0) {
sdRows.forEach(row => row.style.display = 'table-row')
}
});
updateRowNumbers(tableBody);
updateRowStriping(tableBody)
} catch (e) {
console.error('应用清爽模式错误:', e)
}
}
function filterChannels(buttonContainer, tableBody, filterType) {
try {
const allRows = tableBody.querySelectorAll('.iptv-row');
const filterButtons = buttonContainer.querySelectorAll('.iptv-filter-btn');
filterButtons.forEach(btn => {
btn.classList.remove('active');
btn.classList.add('default');
btn.style.backgroundColor = '';
btn.style.color = '';
btn.style.boxShadow = ''
});
const activeBtn = buttonContainer.querySelector(`.iptv-filter-btn[data-type="${filterType}"]`);
if (activeBtn) {
activeBtn.classList.remove('default');
activeBtn.classList.add('active')
}
allRows.forEach(row => {
row.style.display = 'none'
});
switch (filterType) {
case 'all':
allRows.forEach(row => row.style.display = 'table-row');
break;
case 'clean':
applyCleanMode(tableBody);
return;
case 'sd':
allRows.forEach(row => {
if (row.classList.contains('res-sd')) row.style.display = 'table-row'
});
break;
case 'hd':
allRows.forEach(row => {
if (row.classList.contains('res-hd') || row.classList.contains('res-fhd')) {
row.style.display = 'table-row'
}
});
break;
case 'uhd':
allRows.forEach(row => {
if (row.classList.contains('res-uhd')) row.style.display = 'table-row'
});
break
}
updateRowNumbers(tableBody);
updateRowStriping(tableBody)
} catch (e) {
console.error('筛选频道错误:', e)
}
}
筛选功能使用说明
筛选模式介绍
- 全部显示:默认模式,展示所有清晰度的频道资源,适合需要对比不同清晰度源的场景;
- 清爽模式:仅显示每个频道的最高清晰度资源(优先级:超高清>高清>标清),让页面排版最简洁;
- 仅看标清:仅展示标清(720x576)清晰度的频道;
- 仅看高清:仅展示高清(1920x1080)清晰度的频道;
- 仅看超高清:仅展示超高清(3840x2160)清晰度的频道。
筛选模式示例
比如一个频道有:
- 2个超高清版本
- 3个高清版本
- 1个标清版本
清爽模式下会显示:2个超高清 + 3个高清(共5行)
如果这个频道只有:
- 3个高清版本
- 1个标清版本
清爽模式下会显示:3个高清版本
如果这个频道只有:
- 2个标清版本
清爽模式下会显示:2个标清版本
默认模式自定义修改
当前页面加载后默认进入「全部显示」模式,若需改为默认进入「清爽模式」,可通过以下简单修改实现:
找到筛选按钮代码中的关键配置:
data-type="all"
将其中的all替换为clean,修改后代码如下:
data-type="clean"
修改完成后,页面加载时将自动触发「清爽模式」,直接展示各频道的最高清晰度资源,无需手动切换。
附加功能亮点
除核心筛选功能外,还内置了实用的辅助功能:
- 序号自动更新:筛选后可见行的序号会自动重新编排,保持序号连续性;
- 奇偶行条纹样式:筛选后可见行将保持奇偶行差异化样式,提升表格可读性;
写在最后
如果大家用的时候遇到问题,或者有其他想加的功能,欢迎在评论区告诉我~
后续还会继续优化博客的各种小细节,敬请期待~
本页面最后更新于:2025-12-05,距今已 307 天,若有链接失效或教程无效,欢迎留言反馈。






很厉害👍