// ==UserScript==
// @license GPL-3.0
// @name Bilibili 分区显示v1
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 移除所有实验性优化,回归最原始、最稳定的扫描逻辑。修复个人空间、首页、播放页、历史记录的所有显示问题。
// @author ai and xiaojuqs
// @match https://www.bilibili.com/*
// @match https://space.bilibili.com/*
// @match https://member.bilibili.com/*
// @icon https://www.bilibili.com/favicon.ico
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @downloadURL https://update.greasyfork.icu/scripts/557548/Bilibili%20%E5%88%86%E5%8C%BA%E6%98%BE%E7%A4%BAv1.user.js
// @updateURL https://update.greasyfork.icu/scripts/557548/Bilibili%20%E5%88%86%E5%8C%BA%E6%98%BE%E7%A4%BAv1.meta.js
// ==/UserScript==
(function() {
'use strict';
// ================= 1. 开关配置 =================
const defaultConfig = {
home: true, mainTitle: true, sideBar: true, history: true, space: true
};
const config = {
home: GM_getValue('switch_home', defaultConfig.home),
mainTitle: GM_getValue('switch_mainTitle', defaultConfig.mainTitle),
sideBar: GM_getValue('switch_sideBar', defaultConfig.sideBar),
history: GM_getValue('switch_history', defaultConfig.history),
space: GM_getValue('switch_space', defaultConfig.space)
};
function registerMenu() {
GM_registerMenuCommand(`${config.home ? '✅' : '❌'} 首页分区`, () => toggle('home', 'switch_home'));
GM_registerMenuCommand(`${config.mainTitle ? '✅' : '❌'} 播放页主标题`, () => toggle('mainTitle', 'switch_mainTitle'));
GM_registerMenuCommand(`${config.sideBar ? '✅' : '❌'} 播放页侧边栏`, () => toggle('sideBar', 'switch_sideBar'));
GM_registerMenuCommand(`${config.history ? '✅' : '❌'} 历史记录页`, () => toggle('history', 'switch_history'));
GM_registerMenuCommand(`${config.space ? '✅' : '❌'} 个人空间页`, () => toggle('space', 'switch_space'));
}
function toggle(key, k2) { GM_setValue(k2, !config[key]); alert('设置已保存,请刷新页面生效。'); }
registerMenu();
// ================= 2. 核心工具 =================
const API_DELAY = 450;
const CACHE_KEY = 'gemini_bili_partition_v12_cache';
function getCache(bvid) {
try { return JSON.parse(sessionStorage.getItem(CACHE_KEY) || '{}')[bvid]; } catch (e) { return null; }
}
function setCache(bvid, data) {
try {
const cache = JSON.parse(sessionStorage.getItem(CACHE_KEY) || '{}');
cache[bvid] = data;
// 简单清理
if (Object.keys(cache).length > 1500) {
const keys = Object.keys(cache);
for (let i = 0; i < 500; i++) delete cache[keys[i]];
}
sessionStorage.setItem(CACHE_KEY, JSON.stringify(cache));
} catch (e) {}
}
async function fetchPartitionInfo(bvid) {
try {
const res = await fetch(`https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`);
const json = await res.json();
if (json.code === 0 && json.data) {
return { tname: json.data.tname, tname_v2: json.data.tname_v2 };
}
} catch (e) { console.warn('API Fail:', e); }
return null;
}
// ================= 3. 队列与渲染 =================
const queue = [];
let isProcessing = false;
async function processQueue() {
if (queue.length === 0) { isProcessing = false; return; }
isProcessing = true;
const { bvid, insertTarget, styleType } = queue.shift();
// 检查元素是否还在
if (document.body.contains(insertTarget)) {
const nextNode = insertTarget.nextElementSibling;
// 防止重复
if (!nextNode || !nextNode.classList.contains('gemini-list-tag')) {
const cached = getCache(bvid);
if (cached) {
renderListTag(insertTarget, cached, styleType);
setTimeout(processQueue, 50);
} else {
const data = await fetchPartitionInfo(bvid);
if (data) {
setCache(bvid, data);
renderListTag(insertTarget, data, styleType);
}
setTimeout(processQueue, API_DELAY);
}
} else { processQueue(); }
} else { processQueue(); }
}
function addQueue(bvid, insertTarget, styleType = 'normal') {
if (insertTarget.dataset.geminiQ) return;
insertTarget.dataset.geminiQ = 'true';
queue.push({ bvid, insertTarget, styleType });
if (!isProcessing) processQueue();
}
function renderListTag(target, data, styleType) {
const div = document.createElement('div');
div.className = 'gemini-list-tag';
// 样式
if (styleType === 'compact') {
div.style.cssText = `font-size:12px;color:#9499A0;display:flex;align-items:center;margin-top:4px;line-height:1.2;width:100%;`;
div.innerHTML = `${data.tname}|${data.tname_v2}`;
} else {
div.style.cssText = `font-size:12px;color:#9499A0;display:flex;align-items:center;margin-top:4px;line-height:1.2;`;
div.innerHTML = `${data.tname}${data.tname_v2}`;
}
if (target.parentNode) {
target.parentNode.insertBefore(div, target.nextSibling);
// --- 暴力修复高度 (针对个人空间) ---
// 只要检测到是 small-item (个人空间卡片),强制 height: auto
const card = target.closest('.small-item, .history-record-item, .bili-video-card__info');
if(card) {
// 如果是个人空间,必须解锁高度,否则内容会被遮挡
if (window.location.host === 'space.bilibili.com') {
card.style.height = 'auto';
card.style.minHeight = '100px'; // 防止塌陷
} else if (!window.location.host.includes('www.bilibili.com')) {
card.style.height = 'auto';
}
}
}
}
// ================= 4. 全局暴力扫描 (无视路由,全扫) =================
function scanAll() {
// 1. 【个人空间】(优先级调高)
if (config.space) {
// 扫描个人空间常见的所有标题结构
const selectors = [
'.small-item a.title', // 投稿列表
'.list-item a.title', // 列表模式
'.channel-video-card .title', // 频道/合集
'.i-pin-title' // 置顶视频
];
document.querySelectorAll(selectors.join(',')).forEach(title => {
const link = title.tagName === 'A' ? title : title.querySelector('a');
if (link && link.href) {
const match = link.href.match(/(BV\w+)/);
if (match) addQueue(match[1], title, 'compact');
}
});
}
// 2. 【首页】
if (config.home) {
document.querySelectorAll('.bili-video-card .bili-video-card__info--tit').forEach(title => {
const card = title.closest('.bili-video-card');
const link = card ? card.querySelector('a[href*="/video/BV"]') : null;
if (link && link.href) {
const match = link.href.match(/(BV\w+)/);
if (match) addQueue(match[1], title, 'compact');
}
});
}
// 3. 【侧边栏】
if (config.sideBar) {
document.querySelectorAll('.rec-list .video-page-card-small, .rec-list .video-card, .recommend-video-card').forEach(card => {
const link = card.querySelector('a[href*="/video/BV"]');
if (!link) return;
const match = link.href.match(/(BV\w+)/);
if (!match) return;
let target = card.querySelector('.title') || card.querySelector('.info');
if (target) addQueue(match[1], target, 'compact');
});
}
// 4. 【历史记录】
if (config.history) {
document.querySelectorAll('.bili-video-card__details .bili-video-card__title, .history-record-item .title').forEach(title => {
const link = title.querySelector('a') || (title.tagName === 'A' ? title : null);
if (link && link.href && link.href.match(/(BV\w+)/)) {
addQueue(link.href.match(/(BV\w+)/)[1], title, 'normal');
}
});
}
}
// 主标题逻辑
let lastMainBvid = '';
async function handleMainTitle() {
if (!config.mainTitle) return;
if (!location.href.includes('/video/')) return;
const match = location.pathname.match(/(BV\w+)/);
if (!match) return;
const currentBvid = match[1];
const titleEl = document.querySelector('h1.video-title') || document.querySelector('.video-info-title-inner');
if (!titleEl) return;
const existing = document.getElementById('gemini-main-tag');
if (existing) { if (lastMainBvid === currentBvid) return; existing.remove(); }
lastMainBvid = currentBvid;
let data = getCache(currentBvid);
if (!data) {
data = await fetchPartitionInfo(currentBvid);
if (data) setCache(currentBvid, data);
}
if (!data) return;
const div = document.createElement('div');
div.id = 'gemini-main-tag';
div.style.cssText = `display: flex; align-items: center; margin: 8px 0; font-size: 13px; color: #61666d;`;
div.innerHTML = `${data.tname}>${data.tname_v2}`;
titleEl.insertAdjacentElement('afterend', div);
}
// ================= 5. 启动 =================
console.log('B站分区助手 v11 已启动');
// 主标题检查
setInterval(handleMainTitle, 1000);
// 全局扫描 (无视任何条件,每800ms强制扫一遍)
let scanTimer = null;
const observer = new MutationObserver(() => {
if (scanTimer) clearTimeout(scanTimer);
scanTimer = setTimeout(scanAll, 800);
});
observer.observe(document.body, { childList: true, subtree: true });
// 保底:即使 MutationObserver 漏了,也强制扫
setTimeout(scanAll, 1000);
setInterval(scanAll, 2000);
})();