Greasy Fork

Greasy Fork is available in English.

BOSS 直聘助手魔改中

(1)搜索页面增加按钮:只显示当前 HR 在线的职位。(2)职位详情页面增加浮窗显示:HR 是否最近活跃;是否接受应届生。以下是新增功能 还在完善中 1 改进了去世相关的 2 可以隐藏职业跟行业 我用了其他人搞的好多都会封号我就魔改了下不会封号版本的 自用中

当前为 2025-01-04 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         BOSS 直聘助手魔改中
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  (1)搜索页面增加按钮:只显示当前 HR 在线的职位。(2)职位详情页面增加浮窗显示:HR 是否最近活跃;是否接受应届生。以下是新增功能  还在完善中 1 改进了去世相关的  2 可以隐藏职业跟行业  我用了其他人搞的好多都会封号我就魔改了下不会封号版本的  自用中
// @author       Rostal
// @license      MIT
// @icon         https://www.zhipin.com/favicon.ico
// @match        https://www.zhipin.com/job_detail/*
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';
    let document1, document2;
    let listPageDocument = null;



    // 创建置于最顶层的悬浮弹窗
    function createFloatingPopup(text, textColor) {
        var iframe = document.createElement('iframe');
        iframe.style.position = 'fixed';
        iframe.style.top = '10px';
        iframe.style.left = '50%';
        iframe.style.transform = 'translateX(-50%)';
        iframe.style.width = '80%';
        iframe.style.height = 'auto';
        iframe.style.backgroundColor = 'transparent'; // 透明背景
        iframe.style.border = 'none';
        iframe.style.zIndex = '2147483647'; // 保证弹窗在最上层
        iframe.style.boxShadow = '0 5px 15px rgba(0,0,0,0.5)';
        iframe.style.borderRadius = '10px';
        //iframe.sandbox = 'allow-same-origin'; // 添加 sandbox 属性
        // 将 iframe 添加到页面中
        //document.body.appendChild(iframe);
        /*
        var style = `
                #floatingPopup {
                    position: fixed;
                    top: 10px;
                    left: 50%;
                    transform: translateX(-50%);
                    width: 80%;
                    background: rgba(0, 0, 0, 0.9);
                    color: white;
                    padding: 20px;
                    box-sizing: border-box;
                    text-align: center;
                    border-radius: 10px;
                    box-shadow: 0 5px 15px rgba(0,0,0,0.5);
                    z-index: 2147483647;
                    transition: opacity 0.3s ease-in-out;
                    filter: grayscale(0%) !important;
                }
                #floatingPopup div {
            filter: none; /* 取消文本的灰色滤镜 */
        //  color: ${textColor}!important; /* 文本颜色 */
        /* }
                #closePopup {
                    position: absolute;
                    top: 5px;
                    right: 10px;
                    cursor: pointer;
                    font-size: 1.5em;
                    font-weight: bold;
                }
                #closePopup:hover {
                    color: #ddd;
                }
            `;*/
        const randomParam = Math.random();
        let iframeSrcdoc = `
        <html>
            <head>
             </head>
            <body>
                <span id="closePopup">X</span>
                <div id="popupContent">
                    ${text}
                </div>
                <script>
                    document.getElementById('closePopup').addEventListener('click', function() {
                        parent.document.body.removeChild(document.getElementById('iframePopup'));
                    });
                </script>
            </body>
        </html>
    `;
        iframe.srcdoc = `${iframeSrcdoc}?${randomParam}`;

        //iframe.srcdoc = iframeSrcdoc;
        document.body.appendChild(iframe);
        iframe.onload = function() {
            const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
            if (iframeDocument) {
                const style = document.createElement('style');
                style.textContent = `
                    html, body {
                            background-color: rgba(0, 0, 0, 0.9);
                            font-family: Arial, sans-serif;
                         }
                        body {
                           color: ${textColor};
                           fill: ${textColor};
                        }
                        #closePopup {
                            position: absolute;
                            top: 5px;
                            right: 10px;
                            cursor: pointer;
                            font-size: 1.5em;
                            font-weight: bold;
                            background: rgba(0, 0, 0, 0.6);
                            border-radius: 50%;
                            width: 30px;
                            height: 30px;
                            text-align: center;
                            color: white;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            transition: background 0.3s;
                        }
                        #closePopup:hover {
                           background: rgba(0, 0, 0, 0.8);
                        }
                        #popupContent {
                            margin-top: 30px;
                            font-size: 2em;
                            font-weight: bold;
                            padding: 10px;
                            color: ${textColor};
                            fill: ${textColor};
                        }
                   `;
           iframeDocument.head.appendChild(style);
       }
        };
        /*
        iframe.onload = function() {
            const setIframeStyles = () => {
                try {
                      const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

                      if(iframeDocument && iframeDocument.body){
                         const body = iframeDocument.body;
                            body.style.color = `${textColor} !important`;
                              const popupContent = iframeDocument.getElementById('popupContent');
                              if(popupContent){
                                popupContent.style.color = `${textColor} !important`;
                             }
                       } else {
                          requestAnimationFrame(setIframeStyles);
                       }
                } catch (e) {
                    console.error('Failed to apply styles to iframe:', e);
                }
            };
       requestAnimationFrame(setIframeStyles);
    };*/
        // iframe 内的内容,使用 srcdoc 来定义 HTML 内容
        //iframe.srcdoc = iframeSrcdoc;
        // 给 iframe 添加 ID 方便关闭时引用
        iframe.id = 'iframePopup';
        // 将 iframe 添加到页面中
        //document.body.appendChild(iframe);
        /*
        iframe.onload = function() {
       // 创建独立的样式表
        const style = document.createElement('style');
         style.textContent = `
             body {
               font-family: Arial, sans-serif;
                        margin: 0;
                        padding: 0;
                        background-color: rgba(0, 0, 0, 0.9);
                        color: ${textColor} !important; /* 明确设置文字颜色为红色 */
        /*       text-align: center;
                        overflow: hidden;
                    }
           #closePopup {
                        position: absolute;
                        top: 5px;
                        right: 10px;
                        cursor: pointer;
                        font-size: 1.5em;
                        font-weight: bold;
                        background: rgba(0, 0, 0, 0.6);
                        border-radius: 50%;
                        width: 30px;
                        height: 30px;
                        text-align: center;
                        color: white;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        transition: background 0.3s;
                    }
                    #closePopup:hover {
                        background: rgba(0, 0, 0, 0.8);
                    }
                    #popupContent {
                        margin-top: 30px;
                        font-size: 2.0em;
                        padding: 10px;
                    }
        `;
            // 使用 DOMParser 解析 srcdoc
            /*
        const parser = new DOMParser();
        const doc = parser.parseFromString(iframeSrcdoc, 'text/html');
        const head = doc.querySelector('head');
       head.appendChild(style);
        iframe.srcdoc = doc.documentElement.outerHTML
        */
    };


    /*iframe.srcdoc = `
                <div id="floatingPopup">
            <span id="closePopup">X</span>
            <div style="margin-top: 20px; font-size: 2.0em;">${text}</div>
        </div>
            `;*/
    // 给 iframe 添加 ID 方便关闭时引用
    /*iframe.id = 'iframePopup';
         // 将 iframe 添加到页面中
    document.body.appendChild(iframe);
        // 在父页面中取消滤镜影响
        setTimeout(() => { // 使用 setTimeout 确保 iframe 已经插入 DOM
        const popups = document.querySelectorAll('iframe');
        popups.forEach(popup => {
            popup.style.filter = 'invert(100%)'; // 使用 invert 反转滤镜
        });
        }, 0)
/*
        // 添加样式
        var styleElement = document.createElement('style');
        styleElement.type = 'text/css';
        styleElement.innerHTML = style;
        document.head.appendChild(styleElement);
*/
    // 将弹窗添加到页面中
    //document.body.insertAdjacentHTML('afterbegin', popupHTML);
    /*
        // 关闭弹窗的事件处理
        document.getElementById('closePopup').addEventListener('click', function () {
            var popup = document.getElementById('floatingPopup');
            popup.style.opacity = '0';
            setTimeout(function () {
                popup.style.display = 'none';
            }, 300);
        });*/

    function createGrayOverlay() {
        // 创建一个全屏的灰色遮罩层
        let overlay = document.createElement('div');
        overlay.id = 'grayOverlay';
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100vw';
        overlay.style.height = '100vh';
        overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
        overlay.style.zIndex = '9999';
        overlay.style.display = 'none';
        document.body.appendChild(overlay);
        return overlay;
    }
    function showGrayOverlay() {
        let overlay = document.getElementById('grayOverlay');
        if (!overlay) {
            overlay = createGrayOverlay();
        }
        overlay.style.display = 'block';
    }
    function enableGrayMode() {
        // 获取 body 或 html 元素
        let body = document.body;
        let overlay = document.createElement('div');
        // 设置全局样式,应用灰色滤镜,并禁用页面交互(如果需要)
        body.style.filter = 'grayscale(100%)';
        body.style.pointerEvents = 'none'; // 禁用交互,如果需要
        /*
        let popups = document.querySelectorAll('iframe');
        popups.forEach(popup => {
        popup.style.filter = 'none'; // 取消弹窗的灰色滤镜
        popup.style.pointerEvents = 'auto'; // 重新启用弹窗的交互
    });*/
    }


    function runJobDetail() {
        console.log('jrxq');
        // ======== HR 是否最近活跃 ========

        let hrDeadTexts = ["在线", "刚刚活跃", "今日活跃"];
        let bossActiveTime = document1.querySelector('div.job-boss-info span.boss-active-time');
        let bossname = document1.querySelector('div.job-boss-info h2.name');
        let gtButton = document1.querySelector('a.btn.btn-startchat');
        let salaryText = document1.querySelector('span.salary');
        let bossInfoAttr = document1.querySelector('div.boss-info-attr');
        let salary = salaryText ? salaryText.textContent.trim() : '';
        let bossInfo = bossInfoAttr ? bossInfoAttr.textContent.trim().split('·')[0] : '';
        let nameText = bossname ? bossname.textContent.trim().split(' ')[0].split('\n')[0] : null;
        if (bossActiveTime) {
            let bossActiveTimeText = bossActiveTime.textContent;
            if (!hrDeadTexts.includes(bossActiveTimeText)) {
                enableGrayMode();
                createFloatingPopup("SB"+nameText+"已去世| 请允许我们在此献上最后的告别,以纪念其在Boss直聘中留下的足迹与回忆🕯🕯🕯", "red");
                return;
            }
        }
        // 如果按钮是“继续沟通”,就存储职位信息
        if (gtButton && gtButton.textContent.trim() === "继续沟通") {
            console.log('检测到继续沟通1,执行存储职位信息');
            window.localStorage.setItem('jobDetailInfo', JSON.stringify({ salary, bossInfo, nameText })); // 将信息存储到localStorage
            window.localStorage.setItem('jobDetailProcessed', 'true'); // 标记数据已处理
            console.log('localStorage',localStorage)
            runGeekJob()
            //window.location.href = '/geek/job'; // 跳转到列表页面
        } else if (gtButton) {
            // 按钮是"立即沟通",我们需要监听它的变化
            console.log('按钮是“立即沟通”');
            console.log('window.localStorage',window.localStorage)
            const observer = new MutationObserver(() => {
                if (gtButton.textContent.trim() === "继续沟通") {
                    console.log('检测到继续沟通2,执行存储职位信息');
                    window.localStorage.setItem('jobDetailInfo', JSON.stringify({ salary, bossInfo, nameText })); // 将信息存储到localStorage
                    window.localStorage.setItem('jobDetailProcessed', 'true'); // 标记数据已处理
                    //window.location.href = '/geek/job'; // 跳转到列表页面
                    runGeekJob()
                }
            });
            // 监听按钮文本的变化
            observer.observe(gtButton, {
                childList: true,
                subtree: true,
            });
        }
        // ======== 是否接受应届生 ========

        let jobName = document1.querySelector('div.info-primary > div.name');
        if (jobName) {
            let jobNameText = jobName.textContent;

            let regex = /应届.*生?/;
            if (regex.test(jobNameText)) {
                createFloatingPopup("接受应届生", "green");
                return;
            }
        }

        let jobDetail = document1.querySelector('div.job-detail div.job-sec-text');
        if (jobDetail) {
            let jobDetailText = jobDetail.textContent;

            let regex = /接受.*应届.*生/;
            let regex2 = /应届.*生.*可/;
            let regex3 = /欢迎.*应届.*生/;
            let regex4 = /应届.*生.*优先/;
            if (regex.test(jobDetailText) || regex2.test(jobDetailText) || regex3.test(jobDetailText) || regex4.test(jobDetailText)) {
                createFloatingPopup("接受应届生", "green");
                return;
            }
        }
    }
    function onlineFilter() {
        console.log('1. bfEle 不存在,执行添加');
        const bfEle = document.querySelector('.__boss_filter.condition-filter-select');
        if (bfEle) {
            console.log('1. bfEle 已经存在');
            // 先移除选中样式
            bfEle.classList.remove('is-select');
        } else {
            // 不存在则创建并添加到DOM树中
            try {
                runGeekJob();
            } catch (error) {
                console.log('新增筛选出错', error);
            }
        }
    }


    function runGeekJob() {
        console.log('dyrunGeekJob')
        // 保存原始的 XMLHttpRequest
        const originalXHR = XMLHttpRequest;

        // 重写 XMLHttpRequest 构造函数
        XMLHttpRequest = function() {
            const xhr = new originalXHR();

            // 重写 open 方法
            const originalOpen = xhr.open;
            xhr.open = function(method, url) {
                //console.log('捕获到请求 URL:', url); // 输出请求的 URL
                if (url.includes('joblist.json')) {
                    //console.log('捕获到 joblist.json 请求:', url);
                }
                return originalOpen.apply(this, arguments);  // 调用原始的 open 方法
            };
            // 重写 send 方法
            const originalSend = xhr.send;
            xhr.send = function(data) {
                // 在请求完成时处理响应
                xhr.onload = function() {
                    if (xhr.status === 200) {
                        try {
                            // 确保响应类型是 JSON 格式
                            const data = JSON.parse(xhr.responseText);
                            //console.log('解析后的数据:', data);

                            if (data.zpData && data.zpData.jobList) {
                                const jobList = data.zpData.jobList;
                                jobList.forEach((job, index) => {
                                    //console.log('job',job)
                                    //console.log('职位名称:', job.jobName);
                                    //console.log('公司名称:', job.brandName);
                                    //console.log('bossName',job.bossName)
                                    //console.log('ProxyJob:', job.proxyJob); // 若该字段存在
                                    //console.log('ProxyType:', job.proxyType); // 若该字段
                                    window.localStorage.setItem('jobListData', JSON.stringify(data.zpData.jobList));
                                });
                            }
                        } catch (e) {
                            console.error('解析 joblist.json 响应出错:', e);
                        }
                    } else {
                        console.error('请求失败,状态码:', xhr.status);
                    }
                };
                return originalSend.apply(this, arguments); // 调用原始的 send 方法
            }

            return xhr;
        };
        // 从localStorage获取职位信息
        /*  const jobDetailProcessed = window.localStorage.getItem('jobDetailProcessed');
        if (jobDetailProcessed === 'true') {
            console.log('jobDetailProcessed')
            //try {
            let jobDetailInfo = JSON.parse(window.localStorage.getItem('jobDetailInfo'));
            console.log('jobDetailInfo',jobDetailInfo)
            if (jobDetailInfo) {
                // 提取相关的职位信息
                let { salary, bossInfo, nameText } = jobDetailInfo;
                console.log('czlistItems');
                console.log('document',document);
                console.log('document.querySelectorAll',document.querySelectorAll);
                console.log('window.onload',document.referrer)
                //window.onload = function() {
        const savedLIState = JSON.parse(localStorage.getItem('liState'));
                console.log('savedLIState',savedLIState)
                console.log('savedLIState.length',savedLIState.length)
                    if (savedLIState && savedLIState.length > 0) {
                        console.log('jrpd',window.opener.document)
            savedLIState.forEach(savedState => {
                const li = window.opener.document.querySelectorAll('li')[savedState.index];
                if (li) {
                    li.style.display = 'none'; // 修改原页面的 <li> 元素
                }
            });
                let listItems = document.querySelectorAll('ul.job-list-box > li');
                //console.log('listItems',listItems);
                listItems.forEach(function (item) {
                    let itemSalary = item.querySelector('span.salary') ? item.querySelector('span.salary').textContent.trim() : '';
                    let itemBossInfo = item.querySelector('div.boss-info-attr') ? item.querySelector('div.boss-info-attr').textContent.trim() : '';
                    let itemName = item.querySelector('h2.name') ? item.querySelector('h2.name').textContent.trim().split(' ')[0] : '';
                    // 比对 salary、bossInfo 和 name,如果都相同,则隐藏该职位项
                    if (itemSalary === salary && itemBossInfo === bossInfo && itemName === nameText) {
                        console.log('找到匹配项,隐藏该职位');
                        item.style.display = 'none';
                        // 强制浏览器重新渲染,确保隐藏生效
                                  //item.offsetHeight; // 调用强制重排的方法
                    }
                });
            //}
                }
            }
        } */
        /*}catch (error) {
    // 捕获错误时,打印错误并跳过
    console.error('Error parsing jobDetailInfo from localStorage:', error);
}*/
        console.log('2. bfEle 不存在,执行添加');
        // 创建按钮元素
        let button = document.createElement('div');
        button.innerHTML = `<div class="current-select">
    <span class="placeholder-text">浪费时间GUN</span>
</div>`;
        button.classList.add('condition-filter-select', '__boss_filter');
        //let button = document.createElement('button');
        //button.innerHTML = '隐藏浪费时间货色'; // 设置按钮显示的文本
        //button.style.position = 'fixed'; // 设置按钮位置为固定
        //button.style.left = '0'; // 将按钮放置在页面的最左侧
        //button.style.top = '50%'; // 将按钮垂直居中
        //button.style.transform = 'translateY(-50%)'; // 垂直居中的偏移量
        //button.style.zIndex = '2147483647'; // 设置按钮的z-index为最大值,确保其在最高层级
        //button.style.padding = '10px'; // 设置按钮的内边距
        //button.style.cursor = 'pointer'; // 设置鼠标悬停时的光标样式
        // button.style.fontSize = '12px'; // 设置按钮字体大小

        // 添加点击事件监听器
        button.addEventListener('click', function () {
            // 获取所有的 <li> 元素
            let listItems = document.querySelectorAll('ul.job-list-box > li');
            const jobListData = JSON.parse(window.localStorage.getItem('jobListData')) || [];
            const keywords = ['主播', '直播', '不露脸','打字聊天','老师','讲师','教师'];
            const brandIndustrykey = ['即时配送','培训/辅导机构']

            // 遍历每个 <li> 元素
            listItems.forEach(function (item, index) {
                let bossOnlineTag = item.querySelector('span.boss-online-tag');
                console.log('bossOnlineTag',bossOnlineTag);
                let dz = item.querySelector('img.job-tag-icon');
                console.log('dz',dz);
                let jobname = item.querySelector('span.job-name').firstChild.textContent.trim();
                console.log('jobname',jobname);
                const bossname = item.querySelector('div.info-public').firstChild.textContent.trim();
                console.log('bossname',bossname);
                console.log('jobListDataxbossname',jobListData[index].bossName);
                const job = jobListData[index];
                console.log('job',job)
                const brandIndustry = job.brandIndustry
                console.log('brandIndustry',brandIndustry)
                // 获取当前元素的样式
                let style = window.getComputedStyle(item);
                const jobname1 = "需要一位程序员";
                const brandIndustry1 = "软件开发,互联网";

                // 如果没有找到 boss-online-tag 并且元素是可见的,则隐藏该 <li> 元素
                // 如果元素是隐藏的,则显示它
                console.log('keyword',keywords.some(keyword => jobname1.includes(keyword)));
                console.log('bossOnlineTag',!bossOnlineTag);
                console.log('dz',dz);
                console.log('job.proxyJob',job.proxyJob === 1);
                console.log('brandIndustryItem',brandIndustrykey.some(brandIndustryItem => brandIndustry1.includes(brandIndustryItem)));
                if ((brandIndustrykey.some(brandIndustryItem => brandIndustry.includes(brandIndustryItem)) || keywords.some(keyword => jobname.includes(keyword)) || !bossOnlineTag || dz || job.proxyJob === 1) && style.display !== 'none') {
                    item.style.display = 'none';
                } else if (style.display === 'none') {
                    item.style.display = ''; // 使用空字符串将元素的display属性恢复到默认值
                }
            });
        });

        // 将按钮添加到页面中
        document.body.appendChild(button);
        // 插入到父元素 .search-condition-wrapper 最后一个元素之前
        const observer = new MutationObserver(function(mutationsList, observer) {
            let parentNode = document.querySelector('.search-condition-wrapper');
            console.log('parentNode',parentNode)
            if (parentNode !== null) {
                let lastChild = parentNode.lastChild;
                parentNode.insertBefore(button, lastChild);
                observer.disconnect();
            } else {
                console.log('3. parentNode 不存在,无法插入filter');
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });
    }
    // 确保页面完全加载后再执行逻辑
    //window.onload = function () {
    let currentUrl = window.location.href;
    console.log('currentUrl',currentUrl)
    if (currentUrl.includes("/job_detail/")) {
        document1 = document;
        //console.log('document1',document1)
        runJobDetail();
    } else if (currentUrl.includes("/geek/job")) {
        console.log('jrzys')
        const observer = new MutationObserver(() => {
            document2 = document
            // 确保 DOM 加载完毕再执行 runGeekJob
            //console.log('12. bfEle 不存在,执行添加');
            //console.log('document',document.querySelector);
            //if (document.querySelector('ul.job-list-box')) {
            //console.log('23. bfEle 不存在,执行添加');
            //window.addEventListener('storage', function (event) {
            //if (event.key === 'jobDetailProcessed' && event.newValue === 'true') {
            console.log('jrzy');
            const liElements = document.querySelectorAll('li');
            const liState = [];

            liElements.forEach((li, index) => {
                liState.push({
                    index: index,
                    id: li.id,
                    style: li.style.display // 保存 display 样式
                });
            });

            // 使用 localStorage 保存状态
            localStorage.setItem('liState', JSON.stringify(liState));
            //console.log('document2',document2)
            runGeekJob();
            observer.disconnect(); // 断开观察,避免重复触发
            //};
            //});
            //};
        });
        // 配置 MutationObserver 来观察 DOM 变化
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
        //runGeekJob();
    }
    //}
})();