Greasy Fork is available in English.

bili - b站 - 搜索过滤up

搜索页增搜索过滤up

// ==UserScript==
// @name         bili - b站 - 搜索过滤up
// @version      2.0.4
// @description  搜索页增搜索过滤up
// @author       会飞的蛋蛋面
// @match        https://search.bilibili.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        unsafeWindow
// @require      https://code.jquery.com/jquery-3.6.4.slim.min.js
// @require      https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.min.js
// @require      https://cdn.jsdelivr.net/npm/element-ui@2.15.13/lib/index.min.js
// @namespace http://tampermonkey.net/
// ==/UserScript==

(() => {
    'use strict'
    // 加载element-ui
    function loadElement() {
        $('<link>').attr({
            rel: 'stylesheet',
            type: 'text/css',
            href: 'https://cdn.jsdelivr.net/npm/element-ui@2.15.13/lib/theme-chalk/index.min.css',
        }).appendTo(document.documentElement);
    }

    // 睡觉
    async function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    function loadingObserver(selector, callback) {
        const observer = new MutationObserver(async () => {
            if ($(selector).length !== 0) {
                observer.disconnect();  // 停止监听
                await callback();
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });  // 监听 body 元素的子元素变化
    }

    loadElement();
    // 监听视频列表是否加载
    loadingObserver("bili-video-card__info--author", () => {
    })

    $(".search-input-wrap.flex_between").css({ "margin": 0 })
    let div = `
        <div id="app" class="flex_between" style="padding-left:20px;">
            <i class="el-icon-delete" @click="inputVisible=!inputVisible" style="padding-right: 20px;font-size: 20px;"></i>
            <template v-if="inputVisible">
                <el-input placeholder="up name" v-model="submitUpName" @keyup.enter.native="filterSubmit">
                    <el-select v-model="fuzzyMode" slot="prepend" style="width:80px">
                        <el-option label="精准" value="0"></el-option>
                        <el-option label="模糊" value="1"></el-option>
                    </el-select>
                    <el-button slot="append" icon="el-icon-upload" size="small"  @click="saveUp">提交</el-button>
                </el-input>
                <i class=el-icon-toilet-paper size="small" style="padding-left: 20px;font-size: 20px;" @click="filterListButton"></i>
            </template>
            <el-dialog title="过滤列表" :visible.sync="filterDialogVisible" width="30%" append-to-body>
                <el-table :data="ignoredUpList">
                    <el-table-column property="upName" label="up"></el-table-column>
                    <el-table-column label="模式" >
                        <template slot-scope="scope">
                            <el-tag v-if="scope.row.fuzzyMode == 0">
                                精准
                            </el-tag>
                            <el-tag v-else-if="scope.row.fuzzyMode == 1">
                                模糊
                            </el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column fixed="right" label="操作" width="100">
                        <template slot-scope="scope">
                            <el-button @click="deleteUp(scope.row)" type="text" size="small">删除</el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </el-dialog>
        </div>`
    $(".flex_center").append(div)

    // 初始化vue
    new Vue({
        el: '#app',
        data: {
            inputVisible: false,
            filterDialogVisible: false,
            submitUpName: '',
            fuzzyMode: '0',
            ignoredUpList: [],
        },

        async mounted() {
            await this.getIgnoredUp()
            this.filterUpName()
            this.insertListen()
        },

        methods: {
            // 打开过滤列表
            filterListButton() {
                this.filterDialogVisible = true;
            },

            // 获取需要过滤的up主
            async getIgnoredUp() {
                this.ignoredUpList = JSON.parse(localStorage.getItem('ignoredUpList')) || [];
            },

            saveUp() {
                // 参数校验
                if (this.submitUpName.replace(/(^s*)|(s*$)/g, "").length == 0) {
                    this.$message.warning('up name不能为空');
                    return;
                }

                this.ignoredUpList.push({ upName: this.submitUpName, fuzzyMode: this.fuzzyMode });
                localStorage.setItem('ignoredUpList', JSON.stringify(this.ignoredUpList));
                this.$message.success('保存成功')
                this.filterUpName()
            },

            deleteUp(row) {
                this.ignoredUpList = this.ignoredUpList.filter(item => item.upName !== row.upName || item.fuzzyMode !== row.fuzzyMode);
                localStorage.setItem('ignoredUpList', JSON.stringify(this.ignoredUpList));
            },

            // 页码按钮监听事件
            insertListen() {
                $(".search-page-wrapper").bind("DOMNodeInserted", () => this.filterUpName());
            },

            // 过滤up
            filterUpName() {
                let upNameList = $('.bili-video-card__info--author')
                this.ignoredUpList.forEach(up => {
                    let mode = up.fuzzyMode
                    let ignoredName = up.upName
                    upNameList.each((i, element) => {
                        let upName = element.innerText
                        if ((mode == 0 && upName == ignoredName) || (mode == 1 && upName.search(ignoredName) != -1)) {
                            $(element).parents(".col_3.col_xs_1_5.col_md_2.col_xl_1_7.mb_x40").remove()
                        }
                    })
                })
            }
        }
    })
})()