Greasy Fork

Greasy Fork is available in English.

前程无忧(51job)增强工具

在前程无忧(51job)职位列表中显示学历、工作经验年限、发布时间、职位区域和关键词,个人简历页面优化样式,导航可隐藏,岗位页面显示竞争力分析,支持公司职位列表页

当前为 2025-03-17 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         前程无忧(51job)增强工具
// @namespace    http://tampermonkey.net/
// @version      2.5.16
// @description  在前程无忧(51job)职位列表中显示学历、工作经验年限、发布时间、职位区域和关键词,个人简历页面优化样式,导航可隐藏,岗位页面显示竞争力分析,支持公司职位列表页
// @author       johnchan1017
// @match        https://we.51job.com/*
// @match        https://jobs.51job.com/*
// @match        https://i.51job.com/*
// @run-at       document-idle
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        GM_xmlhttpRequest
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let currentpath = window.location.pathname;

    // 显示附加信息的函数(适用于职位列表页面)
    function displayAttachInfo() {
        if (currentpath.startsWith('/users/') || currentpath.match(/^\/[a-z]+-[a-z]+\/\d+\.html$/)) return;

        // 处理搜索结果页 (/pc/search)
        if (currentpath === "/pc/search") {
            const jobItems = document.querySelectorAll('#app > div > div.post > div > div > div.j_result > div > div:nth-child(2) > div > div:nth-child(2) > div.joblist > div');
            if (!jobItems.length) {
                console.log("搜索结果页没有找到职位列表项");
                return;
            }

            jobItems.forEach((item, index) => {
                let sensorsElement = item.querySelector('div[sensorsname]');
                if (!sensorsElement) {
                    console.log(`搜索结果页第 ${index + 1} 个职位项没有找到带数据的节点`);
                    return;
                }

                let jsonObject;
                try {
                    jsonObject = JSON.parse(sensorsElement.getAttribute("sensorsdata"));
                } catch (e) {
                    console.log(`搜索结果页第 ${index + 1} 个职位项的sensorsdata解析失败:`, e);
                    return;
                }

                let jobListItemTopElements = sensorsElement.querySelector('.joblist-item-top');
                if (!jobListItemTopElements) {
                    console.log(`搜索结果页第 ${index + 1} 个职位项没有找到顶部元素`);
                    return;
                }

                let attachInfoSpan = jobListItemTopElements.querySelector('.custom-attach-span');
                if (!attachInfoSpan) {
                    attachInfoSpan = document.createElement('span');
                    attachInfoSpan.classList.add('custom-attach-span');
                    let displayContent = "";

                    if (jsonObject.jobDegree) displayContent += jsonObject.jobDegree + " | ";
                    if (jsonObject.jobYear) displayContent += jsonObject.jobYear + " | ";
                    if (jsonObject.jobTime) displayContent += jsonObject.jobTime + " | ";
                    if (jsonObject.jobArea) displayContent += jsonObject.jobArea + " | ";
                    if (jsonObject.keyword) displayContent += jsonObject.keyword;

                    attachInfoSpan.textContent = displayContent || "无附加信息";
                    attachInfoSpan.style.color = '#2AC08E';
                    attachInfoSpan.style.fontSize = '13px';
                    attachInfoSpan.style.fontWeight = '600';
                    attachInfoSpan.style.marginLeft = '16px';
                    jobListItemTopElements.appendChild(attachInfoSpan);
                    console.log(`搜索结果页第 ${index + 1} 个职位项已添加附加信息: ${displayContent}`);
                }
            });
        }

        // 处理公司职位列表页 (/all/co*.html)
        else if (currentpath.match(/^\/all\/co.*\.html$/)) {
            const jobItems = document.querySelectorAll('.job-list.fb-jobs > a.job-item.sensors_exposure');
            if (!jobItems.length) {
                console.log("公司职位列表页没有找到职位列表项");
                return;
            }

            jobItems.forEach((item, index) => {
                let sensorsElement = item; // 数据直接在<a>标签上
                if (!sensorsElement || !sensorsElement.getAttribute("sensorsdata")) {
                    console.log(`公司职位列表页第 ${index + 1} 个职位项没有找到带数据的节点`);
                    return;
                }

                let jsonObject;
                try {
                    jsonObject = JSON.parse(sensorsElement.getAttribute("sensorsdata"));
                } catch (e) {
                    console.log(`公司职位列表页第 ${index + 1} 个职位项的sensorsdata解析失败:`, e);
                    return;
                }

                let attachInfoSpan = item.querySelector('.custom-attach-span');
                if (!attachInfoSpan) {
                    attachInfoSpan = document.createElement('span');
                    attachInfoSpan.classList.add('custom-attach-span');
                    let displayContent = "";

                    if (jsonObject.jobDegree) displayContent += jsonObject.jobDegree + " | ";
                    if (jsonObject.jobTime) displayContent += jsonObject.jobTime + " | ";
                    if (jsonObject.jobArea) displayContent += jsonObject.jobArea + " | ";
                    if (jsonObject.jobYear) displayContent += jsonObject.jobYear;

                    attachInfoSpan.textContent = displayContent || "无附加信息";
                    attachInfoSpan.style.color = '#2AC08E';
                    attachInfoSpan.style.fontSize = '13px';
                    attachInfoSpan.style.fontWeight = '600';
                    attachInfoSpan.style.marginLeft = '16px';
                    attachInfoSpan.style.display = 'block'; // 新行显示
                    attachInfoSpan.style.padding = '5px 0'; // 美化间距
                    item.appendChild(attachInfoSpan);
                    console.log(`公司职位列表页第 ${index + 1} 个职位项已添加附加信息: ${displayContent}`);
                }
            });
        }

        // 处理申请成功页 (/applysuccess.php)
        else if (currentpath === "/applysuccess.php") {
            const jobItems = document.querySelectorAll('#similar > div.j_joblist > div:nth-child(odd) > a');
            if (!jobItems.length) {
                console.log("申请成功页没有找到职位列表项");
                return;
            }

            jobItems.forEach((item, index) => {
                let sensorsElement = item.querySelector('div[sensorsname]');
                if (!sensorsElement) {
                    console.log(`申请成功页第 ${index + 1} 个职位项没有找到带数据的节点`);
                    return;
                }

                let jsonObject;
                try {
                    jsonObject = JSON.parse(sensorsElement.getAttribute("sensorsdata"));
                } catch (e) {
                    console.log(`申请成功页第 ${index + 1} 个职位项的sensorsdata解析失败:`, e);
                    return;
                }

                let jobListItemTopElements = item.querySelector('p');
                if (!jobListItemTopElements) {
                    console.log(`申请成功页第 ${index + 1} 个职位项没有找到顶部元素`);
                    return;
                }

                let attachInfoSpan = jobListItemTopElements.querySelector('.custom-attach-span');
                if (!attachInfoSpan) {
                    attachInfoSpan = document.createElement('span');
                    attachInfoSpan.classList.add('custom-attach-span');
                    let displayContent = "";

                    if (jsonObject.jobDegree) displayContent += jsonObject.jobDegree + " | ";
                    if (jsonObject.jobYear) displayContent += jsonObject.jobYear + " | ";
                    if (jsonObject.jobTime) displayContent += jsonObject.jobTime + " | ";
                    if (jsonObject.jobArea) displayContent += jsonObject.jobArea + " | ";
                    if (jsonObject.keyword) displayContent += jsonObject.keyword;

                    attachInfoSpan.textContent = displayContent || "无附加信息";
                    attachInfoSpan.style.color = '#2AC08E';
                    attachInfoSpan.style.fontSize = '13px';
                    attachInfoSpan.style.fontWeight = '600';
                    attachInfoSpan.style.marginLeft = '16px';
                    jobListItemTopElements.appendChild(attachInfoSpan);
                    console.log(`申请成功页第 ${index + 1} 个职位项已添加附加信息: ${displayContent}`);
                }
            });
        }
    }

    // 处理简历页面样式优化(适用于 i.51job.com)
    function handleResumePage() {
        if (!currentpath.startsWith('/users/')) return;

        const nav = document.querySelector('.nav');
        if (nav) {
            nav.style.transition = 'all 0.3s ease';
            nav.style.display = 'block';
            nav.dataset.hidden = 'false';
            console.log('导航元素 (.nav) 已找到,正在应用隐藏功能');
        } else {
            console.warn('未找到导航元素 (.nav),隐藏功能无法应用');
        }

        const mainContent = document.querySelector('#maincontent');
        if (mainContent) {
            const columns = mainContent.querySelectorAll('.column');
            if (columns.length > 0) {
                columns.forEach(column => {
                    column.style.float = 'none';
                    console.log('已移除 .column 的 float: right 样式');
                });
            } else {
                console.warn('未在 #maincontent 中找到 .column 元素');
            }
        } else {
            console.warn('未找到 #maincontent 元素,无法调整样式');
        }

        const top = document.querySelector('#top');
        if (top) {
            const innerDiv = top.querySelector('.in');
            if (innerDiv && !document.querySelector('#toggleStyleBtn')) {
                const button = document.createElement('button');
                button.id = 'toggleStyleBtn';
                button.innerHTML = '隐藏导航';
                button.style.position = 'fixed';
                button.style.right = '20px';
                button.style.top = '10px';
                button.style.zIndex = '9999';
                button.style.backgroundColor = '#2AC08E';
                button.style.borderRadius = '4px';
                button.style.color = 'white';
                button.style.padding = '4px 8px';

                button.addEventListener('click', () => {
                    if (nav) {
                        if (nav.dataset.hidden === 'false') {
                            nav.style.display = 'none';
                            nav.dataset.hidden = 'true';
                            button.innerHTML = '显示导航';
                            console.log('导航已隐藏');
                        } else {
                            nav.style.display = 'block';
                            nav.dataset.hidden = 'false';
                            button.innerHTML = '隐藏导航';
                            console.log('导航已显示');
                        }
                    } else {
                        console.warn('导航元素 (.nav) 未找到,无法切换');
                    }
                });

                innerDiv.appendChild(button);
                console.log('样式切换按钮已添加到 #top 的 .in 中');
            } else if (!innerDiv) {
                console.warn('未找到 #top 中的 .in 元素,按钮无法添加');
            }
        } else {
            console.warn('未找到 #top 元素,无法添加切换按钮');
        }
    }

    // 获取岗位页面竞争力分析信息
    function fetchCompetitivenessInfo() {
        if (!currentpath.match(/^\/[a-z]+-[a-z]+\/\d+\.html$/)) return;

        const link = document.querySelector('a.icon_b.i_upline');
        if (!link) {
            console.warn('未找到竞争力分析链接');
            return;
        }

        let href = link.getAttribute('href');
        if (!href) {
            console.warn('竞争力分析链接缺少 href 属性');
            return;
        }

        href = href.startsWith('//') ? 'https:' + href : (href.startsWith('/') ? 'https://i.51job.com' + href : href);

        GM_xmlhttpRequest({
            method: 'GET',
            url: href,
            responseType: 'blob',
            headers: {
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
                'Accept-Language': 'zh-CN,zh;q=0.9',
            },
            onload: function(response) {
                const reader = new FileReader();
                reader.onload = function() {
                    const text = reader.result;
                    console.log('解码后响应(前200字符):', text.substring(0, 200));

                    const parser = new DOMParser();
                    const doc = parser.parseFromString(text, 'text/html');
                    const h2Element = doc.querySelector('.h2');
                    const displayText = h2Element ? h2Element.textContent.trim() : '未找到 h2 元素';

                    const msgElement = document.querySelector('.msg.ltype');
                    if (msgElement) {
                        if (!msgElement.querySelector('#competitiveness-info')) {
                            const competitivenessSpan = document.createElement('span');
                            competitivenessSpan.id = 'competitiveness-info';
                            competitivenessSpan.textContent = ` | 竞争力分析: ${displayText}`;
                            competitivenessSpan.style.color = '#ff6000';
                            competitivenessSpan.style.overflow = 'hidden';
                            competitivenessSpan.style.margin = '0 10px 10px 0';
                            competitivenessSpan.style.padding = '0 5px';
                            competitivenessSpan.style.backgroundColor = '#FFF2E3';

                            msgElement.appendChild(competitivenessSpan);
                            console.log('竞争力分析信息已追加到 .msg.ltype:', displayText);
                        }
                    } else {
                        console.warn('未找到 .msg.ltype 元素,无法追加竞争力分析信息');
                    }
                };
                reader.onerror = function() {
                    console.warn('FileReader 读取失败');
                };
                reader.readAsText(response.response, 'gbk');
            },
            onerror: function() {
                console.warn('获取竞争力分析页面失败,可能需要登录或存在跨域限制');
            }
        });
    }

    // MutationObserver 监听 DOM 变化
    const observer = new MutationObserver(mutationsList => {
        mutationsList.forEach(mutation => {
            if (mutation.type === 'childList') {
                console.log('DOM has been modified');
                displayAttachInfo();
                handleResumePage();
                fetchCompetitivenessInfo();
            }
        });
    });

    const config = { attributes: true, childList: true, subtree: true };
    observer.observe(document.body, config);

    displayAttachInfo();
    handleResumePage();
    fetchCompetitivenessInfo();
})();