您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
此脚本是在作者hi94740的脚本基础上作了一点点布局上的优化,这个脚本能帮你通过关注分组筛选b站时间线上的动态
// ==UserScript== // @name bilibili时间线筛选——分组查看b站动态(布局优化版,原脚本作者hi94740) // @namespace GZ2000COM // @author GZ2000COM // @version 2.0.3.3 // @license MIT // @description 此脚本是在作者hi94740的脚本基础上作了一点点布局上的优化,这个脚本能帮你通过关注分组筛选b站时间线上的动态 // @icon https://www.bilibili.com//favicon.ico // @include https://t.bilibili.com/* // @run-at document-idle // @noframes // @grant unsafeWindow // @grant GM.getResourceUrl // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/lib/vant.min.js // @resource css https://cdn.jsdelivr.net/npm/[email protected]/lib/index.css // ==/UserScript== if (document.URL == "https://t.bilibili.com/" || document.URL.startsWith("https://t.bilibili.com/?")) { var vmTab; var vmBWList; var validTagIDs; var tagged; var selectedUp; var cardObserver; var tabObserver; const darkStyle = '<style id="btf-dark-style" type="text/css">\ .van-collapse{background-color:#444!important}\ .van-cell__title{color:white!important}\ .van-switch__node{background-color:#444!important}\ .van-checkbox__label{color:white!important}\ .van-tab{color:#aaa!important}\ .van-tabs__nav{background-color:#444!important}\ .van-tab.van-tab--active{color:#00aeec!important}\ </style>'; // 新增的用于存放dark模式状态的变量,初始设为false表示非dark模式 //let isDarkMode = false; let isDarkMode = localStorage.getItem('isDarkMode') === 'true'; if (isDarkMode) { document.head.appendChild(document.createRange().createContextualFragment(darkStyle)); } else { const darkStyleElement = document.getElementById('btf-dark-style'); if (darkStyleElement) { darkStyleElement.remove(); } } // 新增的创建dark模式切换按钮的函数 function createDarkModeSwitchButton() { const switchButton = document.createElement('button'); switchButton.id = 'dark-mode-switch'; switchButton.className = 'bili-dyn-sidebar__btn'; switchButton.textContent = '暗黑模式'; switchButton.style.border = 'none'; switchButton.addEventListener('click', toggleDarkMode); // 设置一个延时函数,等待目标元素加载完成后再执行插入按钮操作 const waitForElementAndInsertButton = () => { const interval = setInterval(() => { const biliDynSidebar = document.querySelector('.bili-dyn-sidebar'); if (biliDynSidebar) { const firstChild = biliDynSidebar.firstChild; if (firstChild) { biliDynSidebar.insertBefore(switchButton, firstChild); } else { biliDynSidebar.appendChild(switchButton); } clearInterval(interval); // 插入完成后清除定时器 } }, 100); // 每隔100毫秒检查一次元素是否加载完成,可根据实际情况调整这个时间间隔 }; // 根据当前的dark模式状态设置按钮的文本内容,直观展示当前模式 if (isDarkMode) { switchButton.textContent = '暗黑模式'; } else { switchButton.textContent = '明亮模式'; } // 获取.bili-dyn-sidebar元素,确保其存在后插入按钮到其内部第一个子元素位置 const biliDynSidebar = document.querySelector('.bili-dyn-sidebar'); if (biliDynSidebar) { const firstChild = biliDynSidebar.firstChild; if (firstChild) { biliDynSidebar.insertBefore(switchButton, firstChild); } else { biliDynSidebar.appendChild(switchButton); } } } // 新增的切换dark模式的函数 function toggleDarkMode() { isDarkMode =!isDarkMode; // 将当前的dark模式状态保存到localStorage中 localStorage.setItem('isDarkMode', isDarkMode.toString()); if (isDarkMode) { const darkStyleElement = document.getElementById('btf-dark-style'); if (!darkStyleElement) { document.head.appendChild(document.createRange().createContextualFragment(darkStyle)); } // 获取按钮元素并更新其文本内容为“关闭Dark模式” const switchButton = document.getElementById('dark-mode-switch'); if (switchButton) { switchButton.textContent = '暗黑模式'; } } else { const darkStyleElement = document.getElementById('btf-dark-style'); if (darkStyleElement) { darkStyleElement.remove(); } // 获取按钮元素并更新其文本内容为“切换Dark模式” const switchButton = document.getElementById('dark-mode-switch'); if (switchButton) { switchButton.textContent = '明亮模式'; } } } // 调用函数创建dark模式切换按钮 createDarkModeSwitchButton(); // 新增的隐藏元素函数 function hideElements() { const elementsToHide = ['.left', '.right', '.bili-dyn-home--member main section:first-of-type']; elementsToHide.forEach(selector => { $(selector).each((index, element) => { $(element).hide(); }); }); } const filterDynamicWithTags = function(selections, excluded) { cardObserver.disconnect(); if (selections == "shamiko") { clearFilters(); autoPadding(); } else { selections = _.castArray(selections).filter(t => validTagIDs.includes(t)); excluded = _.castArray(excluded).filter(t => validTagIDs.includes(t)); let excludedUp = excluded.map(t => (tagged[t] || { list: [] }).list).flat(); let newSelectedUp = _.difference(_.uniq(selections.map(t => (tagged[t] || { list: [] }).list).flat()), excludedUp); if (newSelectedUp.length > 0) { selectedUp = newSelectedUp; console.log(selections); new Promise(res => { let siid = setInterval(function () { if ($(".bili-dyn-item").length > 0) { clearInterval(siid); res(); } }); }).then(function () { clearFilters(); filterWorker(); cardObserver.observe($(".bili-dyn-item").parent().parent()[0], { childList: true, subtree: true }); }); } } }; function filterWorker() { $(".bili-dyn-item").toArray().forEach(c => { let author = c.__vue__.author; if (!(selectedUp.some(up => up.mid == author.mid || author.label == "番剧"))) $(c)[0].hidden = true; }); loadMoreDynamics(); autoPadding(); } function loadMoreDynamics() { if ($(window).height() / ($(document).height() - $(document).scrollTop()) > 0.2) { $(".load-more").click(); setTimeout(loadMoreDynamics, 100); } else { if ($(".skeleton").length > 0) { if (($($(".skeleton")[0]).offset().top - $(document).scrollTop()) < ($(window).height() + 1000)) { forceLoad(); setTimeout(loadMoreDynamics, 100); } } } } function forceLoad() { let currentY = $(document).scrollTop(); $(document).scrollTop($(document).height()); $(document).scrollTop(currentY); } function clearFilters() { $(".bili-dyn-item").toArray().forEach(c => c.hidden = false); } function autoPadding() { $("#btf-tab-area").css("padding", ($(".bili-dyn-item")[0] && $(".new-notice-bar").length == 0)? ($(".bili-dyn-item")[0].hidden? "0px 0px 0px 0px" : "0px 0px 0px 0px") : "0px 0px 0px 0px"); } function isBangumiTimeline() { if ($(".selected").text().includes("番") || $(".selected").text().includes("剧")) { $("#btf-tab-area")[0].hidden = true; $("#btf-bwlist-area")[0].hidden = true; cardObserver.disconnect(); clearFilters(); } else { $("#btf-tab-area")[0].hidden = false; $("#btf-bwlist-area")[0].hidden = false; vmTab.activeName = "shamiko"; if (vmTab.complexMode) vmBWList.changed(); } } const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + (i * step)); function ajaxWithCredentials(url) { return new Promise((res, rej) => { $.ajax({ url: url, xhrFields: { withCredentials: true }, success: res, error: rej }); }); } function fetchTags(requestWithCredentials) { let tags = {}; return requestWithCredentials("https://api.live.bilibili.com/User/getUserInfo") .then(data => { let uid = data.data.uid; console.log("uid: " + uid); let followingsRequests = requestWithCredentials("https://api.bilibili.com/x/relation/followings?vmid=" + uid + "&pn=1&ps=50") .then(data => { let gf = range(2, Math.ceil(data.data.total / 50), 1) .map(i => { return requestWithCredentials("https://api.bilibili.com/x/relation/followings?vmid=" + uid + "&pn=" + i + "&ps=50") }); gf.unshift(Promise.resolve(data)); return gf; }) return requestWithCredentials("https://api.bilibili.com/x/relation/tags?vmid=" + uid) .then(data => { let tagsList = data.data; tagsList.map(tag => { tag.list = []; return tag; }).forEach(tag => tags[tag.tagid] = tag); return { tags: tagsList, tagged: followingsRequests.then(gf => { return Promise.all(gf.map(request => { return request.then(data => { let followings = data.data.list; followings.forEach(f => { if (f.tag) { let noAliveTag = true; f.tag.forEach(t => { if (tags[t]) { tags[t].list.push(f); noAliveTag = false; } else console.log("迷之tag:" + t); }); if (noAliveTag) tags[0].list.push(f); } else { tags[0].list.push(f); } }); }) })).then(() => tags); }) } }) }) } Promise.all([ fetchTags(ajaxWithCredentials), GM.getResourceUrl("css") .then(u => $("head").append([ '<link rel="stylesheet" href="' + u + '">', '<style type="text/css">', '.van-collapse-item__title,.van-collapse-item__content {background-color:rgba(0,0,0,0)!important}', '.van-cell__value {height:24px;overflow:visible!important}', '.van-tab.van-tab--active{color:#00aeec!important}', '</style>' ].join("\n"))), new Promise(res => { cardObserver = new MutationObserver(filterWorker); tabObserver = new MutationObserver(isBangumiTimeline); Vue.use(vant.Tab); Vue.use(vant.Tabs); let siid = setInterval(function () { if ($(".bili-dyn-list-tabs").length == 1 && $(".bili-dyn-live-users").length == 1) { clearInterval(siid); res(); } }); }).then(function () { $(".bili-dyn-list-tabs").after('<div id="btf-tab-area"><div id="btf-tab"></div></div>'); $(".bili-dyn-live-users").after('<div id="btf-bwlist-area" style="padding-top:8px"><div id="btf-bwlist"></div></div>'); $("#btf-tab-area")[0].hidden = true; $("#btf-bwlist-area")[0].hidden = true; autoPadding(); tabObserver.observe($(".bili-dyn-list-tabs")[0], { childList: true, subtree: true, attributes: true }); // 使用事件委托,在document上监听点击事件(也可以选择更合适的父元素,比如包含这些元素的某个具体容器元素) $(document).on('click', '.bili-dyn-up-list__item__face.all', function () { location.reload(); }); }) ]).then(data => { // 使用CSS方法添加样式,为van-tabs__line类设置width和margin-bottom属性 $('<style type="text/css">.van-tabs__line{width: 13px!important;margin-bottom: 8px;}</style>').appendTo('head'); $('<style type="text/css">.van-tabs__wrap--scrollable{height: 48px!important;}</style>').appendTo('head'); $('<style type="text/css">.bili-dyn-list-tabs{border-radius: 6px 6px 0 0!important;}</style>').appendTo('head'); $('<style type="text/css">#btf-tab-area{margin-top: 1px;}</style>').appendTo('head'); // 使用CSS方法添加样式,为van-tab类设置flex-basis属性,并添加!important提高优先级(可根据实际情况决定是否添加!important) $('<style type="text/css">.van-tab{flex-basis: 7.1%!important;}</style>').appendTo('head'); // 调用隐藏元素的函数 hideElements(); // 获取页面中的main元素并修改其宽度为60% $('main').css('width', '60%'); let tagOptions = data[0].tags.filter(t => t.count!= 0); validTagIDs = tagOptions.map(t => t.tagid); let loadCompleted = false; vmTab = new Vue({ el: "#btf-tab", template: '<van-tabs v-model="activeName" line-height="2px" color="#00aeec" title-inactive-color="#6d757a" swipe-threshold="10" :border="false" @click="onClick"><van-tab v-for="tag in (complexMode? [{tagid:\'shamiko\',name:\'已启用高级筛选\'}] : tags)" :title="tag.name" :name="tag.tagid"></van-tab></van-tabs>', data: { activeName: "shamiko", tags: [{ tagid: "shamiko", name: "全部" }].concat(tagOptions), complexMode: false }, methods: { onClick: s => { if (loadCompleted) setTimeout(filterDynamicWithTags, 300, s); else { setTimeout(() => { vmTab.activeName = "shamiko" }, 100); vant.Toast.fail("分组名单尚未加载完成,请稍后再试!"); } } } }); vmBWList = new Vue({ el: "#btf-bwlist", template: '<van-collapse v-model="nc" :border="false" style="border-radius:4px;background-color:white;" @change="switched"><van-collapse-item title="高级筛选" :border="true" :is-link="false" name="1"><template #value><van-switch :value="sw" size="22px"/></template><div style="display:flex"><van-checkbox-group v-model="blackList" checked-color="#ff2d55" style="padding-right:8px" @change="changed"><van-checkbox v-for="tag in tags" :name="tag.tagid" style="height:40px"><template #icon="{checked}"><van-icon name="cross" :color="checked?\'white\':\'#c8c9cc\'" style="line-height:19.9px" /></template></van-checkbox></van-checkbox-group><van-checkbox-group v-model="whiteList" style="flex-grow:1" @change="changed"><van-checkbox v-for="tag in tags" :name="tag.tagid" style="height:40px">{{tag.name}}<template #icon="{checked}"><van-icon name="success" :color="checked?\'white\':\'#c8c9cc\'" /></template></van-checkbox></van-checkbox-group></div></van-collapse-item></van-collapse>', data: { nc: [], tags: tagOptions, whiteList: tagOptions.map(t => t.tagid), blackList: [] }, methods: { switched: function (sw) { console.log(sw); if (sw.length > 0) { console.log("on"); vmTab.activeName = "shamiko"; vmTab.complexMode = true; this.changed(); } else { console.log("off"); vmTab.complexMode = false; filterDynamicWithTags("shamiko"); } }, changed: function () { setTimeout(filterDynamicWithTags, 300, this.whiteList, this.blackList); } }, computed: { sw: function () { return this.nc.length > 0; } }, watch: { whiteList: function (n, o) { if (n.length > o.length) this.blackList = this.blackList.filter(b => b!= n.filter(t =>!o.includes(t))); }, blackList: function (n, o) { if (n.length > o.length) this.whiteList = this.whiteList.filter(w => w!= n.filter(t =>!o.includes(t))); } } }); isBangumiTimeline(); data[0].tagged.then(data => { tagged = data; loadCompleted = true; }); $(".van-tabs__wrap")[0].style["border-radius"] = "0 0 6px 6px"; try { if (unsafeWindow.bilibiliEvolved.settings.useDarkStyle) $("head").append(darkStyle); unsafeWindow.bilibiliEvolved.addSettingsListener("useDarkStyle", value => value? $("head").append(darkStyle) : $("#btf-dark-style").remove()); } catch (e) { console.log("dark mode error: ", e); } }).catch(err => { console.error(err); alert("【b站时间线筛选】脚本出错了!\n请查看控制台以获取错误信息"); }) }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址