[JavaScript] 纯文本查看 复制代码
// ==UserScript==
// @name CCTV、央视频节目过滤脚本
// @namespace http://tampermonkey.net/
// @version 2.3
// @description 过滤CCTV/央视频网页,只显示视频 + 右侧可滑出节目列表
// @author 作者:52PJ网Liuyang207
// @match https://tv.cctv.com/live/*
// @match https://www.yangshipin.cn/tv/*
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
const CHANNELS = [
{ n: 'CCTV-1 综合', u: '/live/cctv1/' },
{ n: 'CCTV-2 财经', u: '/live/cctv2/' },
{ n: 'CCTV-3 综艺', u: '/live/cctv3/' },
{ n: 'CCTV-4 中文国际', u: '/live/cctv4/' },
{ n: 'CCTV-5 体育', u: '/live/cctv5/' },
{ n: 'CCTV-5+ 体育赛事', u: '/live/cctv5plus/' },
{ n: 'CCTV-6 电影', u: '/live/cctv6/' },
{ n: 'CCTV-7 国防军事', u: '/live/cctv7/' },
{ n: 'CCTV-8 电视剧', u: '/live/cctv8/' },
{ n: 'CCTV-9 纪录', u: '/live/cctvjilu/' },
{ n: 'CCTV-10 科教', u: '/live/cctv10/' },
{ n: 'CCTV-11 戏曲', u: '/live/cctv11/' },
{ n: 'CCTV-12 社会与法', u: '/live/cctv12/' },
{ n: 'CCTV-13 新闻', u: '/live/cctv13/' },
{ n: 'CCTV-14 少儿', u: '/live/cctvchild/' },
{ n: 'CCTV-15 音乐', u: '/live/cctv15/' },
{ n: 'CCTV-16 奥林匹克', u: '/live/cctv16/' },
{ n: 'CCTV-17 农业农村', u: '/live/cctv17/' }
];
const YANG_CHANNELS = [
{ n: '--- 央视频道 ---', pid: null },
{ n: 'CCTV-1 综合', pid: '600001859' },
{ n: 'CCTV-2 财经', pid: '600001800' },
{ n: 'CCTV-3 综艺', pid: '600001801' },
{ n: 'CCTV-4 中文国际', pid: '600001814' },
{ n: 'CCTV-5 体育', pid: '600001818' },
{ n: 'CCTV-5+ 体育赛事', pid: '600001817' },
{ n: 'CCTV-6 电影', pid: '600108442' },
{ n: 'CCTV-7 国防军事', pid: '600004092' },
{ n: 'CCTV-8 电视剧', pid: '600001803' },
{ n: 'CCTV-9 纪录', pid: '600004078' },
{ n: 'CCTV-10 科教', pid: '600001805' },
{ n: 'CCTV-11 戏曲', pid: '600001806' },
{ n: 'CCTV-12 社会与法', pid: '600001807' },
{ n: 'CCTV-13 新闻', pid: '600001811' },
{ n: 'CCTV-14 少儿', pid: '600001809' },
{ n: 'CCTV-15 音乐', pid: '600001815' },
{ n: 'CCTV-16 奥林匹克', pid: '600098637' },
{ n: 'CCTV-16 4K', pid: '600099502' },
{ n: 'CCTV-17 农业农村', pid: '600001810' },
{ n: 'CCTV-4K 超高清', pid: '600002264' },
{ n: 'CCTV-8K 超高清', pid: '600156816' },
{ n: 'CGTN', pid: '600014550' },
{ n: 'CGTN法语', pid: '600084704' },
{ n: 'CGTN俄语', pid: '600084758' },
{ n: 'CGTN阿拉伯语', pid: '600084782' },
{ n: 'CGTN西班牙语', pid: '600084744' },
{ n: 'CGTN外语纪录', pid: '600084781' },
{ n: 'CCTV-风云剧场', pid: '600099658' },
{ n: 'CCTV-第一剧场', pid: '600099655' },
{ n: 'CCTV-怀旧剧场', pid: '600099620' },
{ n: 'CCTV-世界地理', pid: '600099637' },
{ n: 'CCTV-风云音乐', pid: '600099660' },
{ n: 'CCTV-兵器科技', pid: '600099649' },
{ n: 'CCTV-风云足球', pid: '600099636' },
{ n: 'CCTV-高尔夫', pid: '600099659' },
{ n: 'CCTV-女性时尚', pid: '600099650' },
{ n: 'CCTV-文化精品', pid: '600099653' },
{ n: 'CCTV-台球', pid: '600099652' },
{ n: 'CCTV-电视指南', pid: '600099656' },
{ n: 'CCTV-卫生健康', pid: '600099651' },
{ n: '--- 卫视频道 ---', pid: null },
{ n: '北京卫视', pid: '600002309' },
{ n: '江苏卫视', pid: '600002521' },
{ n: '东方卫视', pid: '600002483' },
{ n: '浙江卫视', pid: '600002520' },
{ n: '湖南卫视', pid: '600002475' },
{ n: '湖北卫视', pid: '600002508' },
{ n: '广东卫视', pid: '600002485' },
{ n: '广西卫视', pid: '600002509' },
{ n: '黑龙江卫视', pid: '600002498' },
{ n: '海南卫视', pid: '600002506' },
{ n: '重庆卫视', pid: '600002531' },
{ n: '深圳卫视', pid: '600002481' },
{ n: '四川卫视', pid: '600002516' },
{ n: '河南卫视', pid: '600002525' },
{ n: '东南卫视', pid: '600002484' },
{ n: '贵州卫视', pid: '600002490' },
{ n: '江西卫视', pid: '600002503' },
{ n: '辽宁卫视', pid: '600002505' },
{ n: '安徽卫视', pid: '600002532' },
{ n: '河北卫视', pid: '600002493' },
{ n: '山东卫视', pid: '600002513' },
{ n: '天津卫视', pid: '600152137' },
{ n: '吉林卫视', pid: '600190405' },
{ n: '陕西卫视', pid: '600190400' },
{ n: '宁夏卫视', pid: '600190737' },
{ n: '内蒙古卫视', pid: '600190401' },
{ n: '云南卫视', pid: '600190402' },
{ n: '山西卫视', pid: '600190407' },
{ n: '青海卫视', pid: '600190406' },
{ n: '西藏卫视', pid: '600190403' },
{ n: '新疆卫视', pid: '600152138' }
];
GM_addStyle(`
body.cctv-clean-mode > *:not(.cctv-clean-main):not(.cctv-list-container) {
display: none !important;
}
.cctv-clean-main {
display: flex !important;
flex-direction: row !important;
align-items: stretch !important;
gap: 30px !important;
width: 100% !important;
height: 100vh !important;
padding: 25px !important;
box-sizing: border-box !important;
background: linear-gradient(145deg, #1a202c 0%, #2d3748 50%, #4a5568 100%) !important;
perspective: 1200px !important;
transform-style: preserve-3d !important;
}
.cctv-video-card {
flex: 2.5 1 auto !important;
background: linear-gradient(145deg, #000000 0%, #111827 100%) !important;
border-radius: 20px !important;
box-shadow:
0 20px 40px rgba(0,0,0,0.6),
0 30px 60px rgba(0,0,0,0.4),
inset 0 0 20px rgba(255,255,255,0.1) !important;
overflow: hidden !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
border: 1px solid rgba(255,255,255,0.2) !important;
min-width: 0 !important;
max-width: 80vw !important;
transform-style: preserve-3d !important;
position: relative !important;
margin: 0 auto !important;
aspect-ratio: 16/9 !important;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
transform: translateZ(0) scale(1);
}
.cctv-video-card:hover {
transform: translateZ(20px) scale(1.01) !important;
box-shadow:
0 25px 50px rgba(0,0,0,0.7),
0 35px 70px rgba(0,0,0,0.5),
inset 0 0 25px rgba(255,255,255,0.15) !important;
}
.cctv-video-card::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
border-radius: 18px !important;
border: 1px solid rgba(255,255,255,0.1) !important;
pointer-events: none !important;
}
body:not(.yangshipin-layout) .cctv-video-card {
height: 100% !important;
}
.yangshipin-layout .cctv-clean-main {
padding: 20px 40px !important;
gap: 30px !important;
}
.yangshipin-layout .cctv-video-spacer {
flex: 1.2 !important;
min-width: 40px !important;
}
.yangshipin-layout .cctv-video-card {
flex: 3 1 auto !important;
max-width: 80vw !important;
width: auto !important;
min-width: 0 !important;
margin: 0 auto !important;
height: auto !important;
aspect-ratio: 16/9 !important;
}
.cctv-video-spacer {
flex: 1 !important;
min-width: 0 !important;
}
.cctv-video-wrap {
width: 100% !important;
height: 100% !important;
display: flex !important;
align-items: stretch !important;
justify-content: center !important;
background: #000 !important;
overflow: hidden !important;
}
.cctv-video-wrap video,
.cctv-video-wrap canvas,
.cctv-video-wrap iframe {
width: 100% !important; /* 恢复原始宽度 */
height: 100% !important;
object-fit: contain !important; /* 保持比例并完整显示 */
object-position: center !important;
/* 移除偏移,视频会自动居中 */
}
.cctv-video-wrap > div,
.cctv-video-wrap > * {
width: 100% !important;
height: 100% !important;
}
.cctv-list-container {
position: fixed !important;
right: -180px !important; /* 只隐藏菜单部分 */
z-index: 999999 !important;
display: flex !important;
flex-direction: row !important;
transition: right 0.3s cubic-bezier(0.165, 0.84, 0.44, 1) !important;
overflow: visible !important;
width: 222px !important;
}
.cctv-list-container:hover {
right: 0 !important;
}
.cctv-list-card {
width: 180px !important;
height: 100% !important;
background: linear-gradient(145deg, rgba(15, 23, 42, 0.98) 0%, rgba(30, 41, 59, 0.95) 100%) !important;
backdrop-filter: blur(25px) saturate(200%) !important;
-webkit-backdrop-filter: blur(25px) saturate(200%) !important;
border-radius: 0 24px 24px 0 !important;
box-shadow:
-10px 0 40px rgba(0,0,0,0.6),
inset 1px 0 0 rgba(255,255,255,0.15),
inset -3px 0 12px rgba(0,0,0,0.4) !important;
overflow: hidden !important;
display: flex !important;
flex-direction: column !important;
border: 1px solid rgba(255,255,255,0.25) !important;
border-left: none !important;
transform: perspective(1000px) rotateY(-5deg) translateZ(10px) !important;
transform-origin: left center !important;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
}
.cctv-list-container:hover .cctv-list-card {
transform: perspective(1000px) rotateY(0deg) !important;
box-shadow:
-5px 0 25px rgba(0,0,0,0.4),
inset 1px 0 0 rgba(255,255,255,0.1) !important;
}
.cctv-list-tab {
width: 42px !important;
background: linear-gradient(180deg, rgba(99, 179, 255, 0.95) 0%, rgba(59, 130, 246, 0.9) 50%, rgba(37, 99, 235, 0.85) 100%) !important;
color: #fff !important;
font-size: 14px !important;
font-weight: 700 !important;
writing-mode: vertical-rl !important;
letter-spacing: 4px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
cursor: pointer !important;
border-radius: 12px 0 0 12px !important;
box-shadow: -5px 0 25px rgba(59, 130, 246, 0.4), inset 0 1px 0 rgba(255,255,255,0.3) !important;
flex-shrink: 0 !important;
border: 1px solid rgba(255,255,255,0.3) !important;
border-right: none !important;
height: 100% !important;
transition: all 0.3s ease !important;
text-shadow: 0 1px 3px rgba(0,0,0,0.4) !important;
}
.cctv-list-tab:hover {
background: linear-gradient(180deg, rgba(120, 200, 255, 0.95) 0%, rgba(79, 150, 255, 0.9) 50%, rgba(47, 119, 245, 0.85) 100%) !important;
box-shadow: -5px 0 30px rgba(59, 130, 246, 0.5), inset 0 1px 0 rgba(255,255,255,0.4) !important;
}
.cctv-list-card-header {
padding: 12px 16px !important;
font-size: 14px !important;
font-weight: 600 !important;
color: rgba(255,255,255,0.95) !important;
border-bottom: 1px solid rgba(255,255,255,0.12) !important;
background: rgba(30, 41, 59, 0.4) !important;
flex-shrink: 0 !important;
text-align: center !important;
text-shadow: 0 1px 2px rgba(0,0,0,0.3) !important;
}
.cctv-platform-switch {
display: flex !important;
align-items: center !important;
justify-content: center !important;
gap: 8px !important;
padding: 10px 16px !important;
border-bottom: 1px solid rgba(255,255,255,0.1) !important;
background: rgba(15, 23, 42, 0.3) !important;
}
.cctv-platform-switch-btn {
flex: 1 !important;
padding: 8px 10px !important;
border: 1px solid rgba(255,255,255,0.18) !important;
border-radius: 8px !important;
background: rgba(30, 41, 59, 0.6) !important;
color: rgba(255,255,255,0.9) !important;
font-size: 12px !important;
font-weight: 500 !important;
text-decoration: none !important;
text-align: center !important;
cursor: pointer !important;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
position: relative !important;
overflow: hidden !important;
backdrop-filter: blur(8px) !important;
}
.cctv-platform-switch-btn::before {
content: '' !important;
position: absolute !important;
inset: 0 !important;
background: linear-gradient(135deg, rgba(0,212,255,0.15) 0%, transparent 50%, rgba(0,212,255,0.08) 100%) !important;
opacity: 0 !important;
transition: opacity 0.2s ease !important;
}
.cctv-platform-switch-btn:hover {
background: rgba(255,255,255,0.15) !important;
border-color: rgba(0,212,255,0.5) !important;
color: #00d4ff !important;
transform: translateY(-1px) !important;
box-shadow: 0 2px 8px rgba(0,212,255,0.2) !important;
}
.cctv-platform-switch-btn:hover::before {
opacity: 1 !important;
}
.cctv-platform-switch-btn:active {
transform: translateY(0) scale(0.98) !important;
}
.cctv-list-card-body {
flex: 1 !important;
overflow-y: auto !important;
scrollbar-width: none !important;
padding: 4px 8px !important;
}
.cctv-list-card-body::-webkit-scrollbar {
display: none !important;
}
.cctv-list-card-body a {
display: block !important;
padding: 6px 12px !important;
margin: 2px 0 !important;
border-radius: 10px !important;
color: rgba(255,255,255,0.9) !important;
text-decoration: none !important;
font-size: 13px !important;
line-height: 1.3 !important;
transition: all 0.2s ease !important;
}
.cctv-list-card-body a:hover {
background: rgba(59, 130, 246, 0.15) !important;
color: #fff !important;
transform: translateX(3px) !important;
}
.cctv-list-card-body a.cctv-active {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.25) 0%, rgba(37, 99, 235, 0.2) 100%) !important;
color: #fff !important;
border-left: 3px solid #3b82f6 !important;
padding-left: 9px !important;
font-weight: 600 !important;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.2) !important;
}
html, body {
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
height: 100% !important;
overflow: hidden !important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
}
/* 确保央视频区域鼠标指针可见 */
.yangshipin-layout .cctv-video-card,
.yangshipin-layout .cctv-video-wrap,
.yangshipin-layout .cctv-video-wrap video {
cursor: default !important;
}
/* 鼠标悬停时显示指针手型 */
.yangshipin-layout .cctv-video-card:hover,
.yangshipin-layout .cctv-video-wrap:hover {
cursor: pointer !important;
}
/* 背景区域显示标准鼠标指针 */
.cctv-clean-main {
cursor: default !important;
}
`);
// ────────────────────────────── CCTV 专用 ──────────────────────────────
function findCCTVVideoColumn() {
const video = document.querySelector('video');
if (!video) return null;
let el = video.parentElement;
const vw = window.innerWidth;
const vh = window.innerHeight;
let count = 0;
while (el && el !== document.body && count < 10) {
const rect = el.getBoundingClientRect();
if (rect.width > vw * 0.35 && rect.height > vh * 0.35) {
return el;
}
el = el.parentElement;
count++;
}
return video.parentElement || null;
}
function applyCCTVLayout() {
if (document.querySelector('.cctv-clean-main')) return;
const videoColumn = findCCTVVideoColumn();
if (!videoColumn) return;
let mainContainer = videoColumn.parentElement;
while (mainContainer && mainContainer !== document.body) {
const children = Array.from(mainContainer.children).filter(c => c.offsetWidth > 0);
if (children.length >= 2) break;
mainContainer = mainContainer.parentElement;
}
if (!mainContainer || mainContainer === document.body) mainContainer = document.body;
mainContainer.classList.add('cctv-clean-main');
videoColumn.classList.add('cctv-video-card');
if (!videoColumn.querySelector('.cctv-video-wrap')) {
const wrap = document.createElement('div');
wrap.className = 'cctv-video-wrap';
while (videoColumn.firstChild) {
wrap.appendChild(videoColumn.firstChild);
}
videoColumn.appendChild(wrap);
}
const listContainer = document.createElement('div');
listContainer.className = 'cctv-list-container';
const listTab = document.createElement('div');
listTab.className = 'cctv-list-tab';
listTab.textContent = 'CCTV频道列表 双击视频全屏 ';
const listCard = document.createElement('div');
listCard.className = 'cctv-list-card';
listCard.innerHTML = '<div class="cctv-list-card-header">频道列表</div><div class="cctv-platform-switch"><a href="https://www.yangshipin.cn/tv/" class="cctv-platform-switch-btn">跳转央视频</a></div><div class="cctv-list-card-body"></div>';
const body = listCard.querySelector('.cctv-list-card-body');
const curPath = location.pathname.replace(/\/$/, '').toLowerCase();
CHANNELS.forEach(channel => {
const a = document.createElement('a');
a.href = new URL(channel.u, location.origin).href;
a.textContent = channel.n;
const linkPath = new URL(a.href).pathname.replace(/\/$/, '').toLowerCase();
if (curPath === linkPath || curPath.startsWith(linkPath + '/')) {
a.classList.add('cctv-active');
}
body.appendChild(a);
});
listContainer.appendChild(listTab);
listContainer.appendChild(listCard);
document.body.appendChild(listContainer);
const spacerLeft = document.createElement('div');
spacerLeft.className = 'cctv-video-spacer';
const spacerRight = document.createElement('div');
spacerRight.className = 'cctv-video-spacer';
videoColumn.before(spacerLeft);
videoColumn.after(spacerRight);
Array.from(mainContainer.children).forEach(child => {
if (![spacerLeft, videoColumn, spacerRight].includes(child)) {
child.style.display = 'none';
}
});
document.body.prepend(mainContainer);
document.body.classList.add('cctv-clean-mode');
const videoWrap = videoColumn.querySelector('.cctv-video-wrap');
if (videoWrap) {
videoWrap.addEventListener('dblclick', () => {
const video = videoWrap.querySelector('video');
if (video) {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
videoWrap.requestFullscreen();
}
}
});
}
const syncList = () => {
const card = document.querySelector('.cctv-video-card');
const list = document.querySelector('.cctv-list-container');
if (card && list) {
const rect = card.getBoundingClientRect();
list.style.top = rect.top + 'px';
list.style.height = rect.height + 'px';
}
};
syncList();
window.addEventListener('resize', syncList);
}
// ────────────────────────────── 央视频 专用 ──────────────────────────────
function findYangVideoColumn() {
const video = document.querySelector('video');
if (!video) return null;
let el = video.parentElement;
const vw = window.innerWidth;
const vh = window.innerHeight;
let count = 0;
while (el && el !== document.body && count < 12) {
const rect = el.getBoundingClientRect();
const className = (el.className || '').toLowerCase();
if ((className.includes('player') || className.includes('video') || className.includes('container')) &&
rect.width > vw * 0.4 && rect.height > vh * 0.35) {
return el;
}
el = el.parentElement;
count++;
}
return video.parentElement || null;
}
function applyYangLayout() {
if (document.querySelector('.cctv-clean-main')) return;
document.body.classList.add('yangshipin-layout');
const videoColumn = findYangVideoColumn();
if (!videoColumn) return;
let mainContainer = videoColumn.parentElement;
while (mainContainer && mainContainer !== document.body) {
const children = Array.from(mainContainer.children).filter(c => c.offsetWidth > 0);
if (children.length >= 2) break;
mainContainer = mainContainer.parentElement;
}
if (!mainContainer || mainContainer === document.body) mainContainer = document.body;
mainContainer.classList.add('cctv-clean-main');
videoColumn.classList.add('cctv-video-card');
if (!videoColumn.querySelector('.cctv-video-wrap')) {
const wrap = document.createElement('div');
wrap.className = 'cctv-video-wrap';
while (videoColumn.firstChild) {
wrap.appendChild(videoColumn.firstChild);
}
videoColumn.appendChild(wrap);
}
const listContainer = document.createElement('div');
listContainer.className = 'cctv-list-container';
const listTab = document.createElement('div');
listTab.className = 'cctv-list-tab';
listTab.textContent = '央视频频道 双击视频全屏';
const listCard = document.createElement('div');
listCard.className = 'cctv-list-card';
listCard.innerHTML = '<div class="cctv-list-card-header">央视频频道</div><div class="cctv-platform-switch"><a href="https://tv.cctv.com/live/" class="cctv-platform-switch-btn">跳转CCTV</a></div><div class="cctv-list-card-body"></div>';
const body = listCard.querySelector('.cctv-list-card-body');
const currentUrl = location.href.toLowerCase();
YANG_CHANNELS.forEach(item => {
if (item.pid === null) {
const divider = document.createElement('div');
divider.style.cssText = 'padding: 6px 10px; font-size: 13px; color: rgba(255,255,255,0.7); font-weight: 600; margin: 8px 0 4px;';
divider.textContent = item.n;
body.appendChild(divider);
} else {
const a = document.createElement('a');
a.href = '/tv/home?pid=' + item.pid;
a.textContent = item.n;
if (currentUrl.includes('pid=' + item.pid)) {
a.classList.add('cctv-active');
}
body.appendChild(a);
}
});
listContainer.appendChild(listTab);
listContainer.appendChild(listCard);
document.body.appendChild(listContainer);
const spacerLeft = document.createElement('div');
spacerLeft.className = 'cctv-video-spacer';
const spacerRight = document.createElement('div');
spacerRight.className = 'cctv-video-spacer';
videoColumn.before(spacerLeft);
videoColumn.after(spacerRight);
Array.from(mainContainer.children).forEach(child => {
if (![spacerLeft, videoColumn, spacerRight].includes(child)) {
child.style.display = 'none';
}
});
document.body.prepend(mainContainer);
document.body.classList.add('cctv-clean-mode');
// 添加双击全屏功能(央视频)
const videoWrap = videoColumn.querySelector('.cctv-video-wrap');
if (videoWrap) {
videoWrap.addEventListener('dblclick', () => {
const video = videoWrap.querySelector('video');
if (video) {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
videoWrap.requestFullscreen();
}
}
});
}
const syncList = () => {
const card = document.querySelector('.cctv-video-card');
const list = document.querySelector('.cctv-list-container');
if (card && list) {
const rect = card.getBoundingClientRect();
list.style.top = rect.top + 'px';
list.style.height = rect.height + 'px';
}
};
syncList();
window.addEventListener('resize', syncList);
}
function tryApplyLayout() {
const host = location.hostname.toLowerCase();
if (host.includes('tv.cctv.com')) {
applyCCTVLayout();
} else if (host.includes('yangshipin.cn')) {
applyYangLayout();
}
}
if (document.readyState === 'complete') {
setTimeout(tryApplyLayout, 1800);
} else {
window.addEventListener('load', () => {
setTimeout(tryApplyLayout, 1800);
});
}
const observer = new MutationObserver(() => {
if (!document.querySelector('.cctv-clean-main') && document.querySelector('video')) {
tryApplyLayout();
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
})();