// ==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();
}
//}
})();