// ==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 // @downloadURL none // ==/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; // 数据直接在标签上 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(); })();