// ==UserScript==
// @name Boss直聘活跃度显示
// @namespace http://tampermonkey.net/
// @version 0.7
// @description Boss直聘显示活跃时间,鼠标点击顶部导航栏栏即可显示出全部职位活跃度:
// @author Winlam
// @match https://www.zhipin.com/web/geek/job*
// @icon https://www.google.com/s2/favicons?sz=64&domain=zhipin.com
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let styles = document.createElement("style");
styles.textContent=`
#wl_action_button{ width: 25px;
height: 25px;
background: #4c9696;
border-radius: 50%;
box-shadow: 1px 1px 2px 1px #ffffff;cursor: pointer;}
#wl_tagsbar{ display: flex;align-items: end;
position: absolute;
color: #fff;
top: 32%;
margin-left: 15px;
text-shadow: 1px 1px 7px #fdfdfd;
}
.w_active{ /*职位链接标签 是否已经设置过*/
padding-bottom: 10px !important;
height:auto !important;
}
.acvt,.wl_juli{ /*默认*/
padding: 3px 8px;
background: #f8f8f8;
width: fit-content;
border-radius: 8px;
margin-top: 9px;
font-size: 14px;
}
.wl_juli{padding:0;}
.acvt-new{ /*日*/
background: #6dd0d0;
}
.acvt-online{
background: #e5f4e3;
color: #40b14f;
}
`;
document.head.appendChild(styles);
let bossactive = {}; //encryptJobId:活跃字
let mlinkdata = new Map();//joblist api链接:对应的数据数组
let flag_doing = true;
let headerbar,tags,currentLat,currentLon,action_button,showtags;
// let headerbar = document.querySelector("#header");
// let tags = document.createElement("div");
// tags.id="wl_tagsbar";
// headerbar.prepend(tags);
function toRadians(degrees) {
return degrees * (Math.PI / 180);
}
function haversineDistance(lat1, lon1, lat2, lon2) {
const R = 6371;
const dLat = toRadians(lat2 - lat1);
const dLon = toRadians(lon2 - lon1);
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c; //千米
return distance;
}
function getjuli(lat,log){
return new Promise(function(res,rej){
let distance = 0;
if(currentLat==null||currentLon==null){
res(distance);
}
if (navigator.geolocation) {
if(!currentLat && !currentLon){
navigator.geolocation.getCurrentPosition(
(position) => {
currentLat = position.coords.latitude; // 获取纬度
currentLon = position.coords.longitude; // 获取经度
// 你可以在这里调用计算距离的函数
distance = haversineDistance(currentLat, currentLon, lat, log);
res(distance);
},
(error) => {
console.error('获取位置失败', error);
},
{
enableHighAccuracy: true, // 使能高精度定位
timeout: 5000, // 超时时间
maximumAge: 0 // 不使用缓存
}
);
}
//console.log(currentLat, currentLon, lat, log);
distance = haversineDistance(currentLat, currentLon, lat, log);
res(distance);
} else {
console.log("浏览器不支持地理位置服务。");
}
res(distance);
})
}
function refresh_tags(text){
//if(!text){return;}
if(!headerbar){
headerbar = document.querySelector("#header");
}
if(!tags){
tags = document.createElement("div");
tags.id="wl_tagsbar";
action_button = document.createElement("div");
action_button.id="wl_action_button";
tags.prepend(action_button);
showtags = document.createElement("div");
showtags.id="wl_showtags";
tags.append(showtags);
headerbar.prepend(tags);
}
let wl_showtags = document.querySelector("#wl_showtags");
if(wl_showtags){
wl_showtags.innerHTML = text;
}
}
//从网络中获得列表数组
function getlinks() {
let data = window.performance
.getEntries()
.filter((item) => item.name.includes("/search/joblist.json?")).map((item) => item.name);
return data[data.length - 1];
}
//ul 工作列表 job-list-box
function sortlist(ul){
refresh_tags("排序中...")
// 给定的顺序
var order = ["在线","刚刚活跃","今日活跃","本周活跃", "3日内活跃","本月活跃","2月内活跃","3月内活跃","4月内活跃","5月内活跃","半年前活跃",""];
var orderMap = order.reduce((acc, item, index) => {
acc[item] = index;
return acc;
}, {});
var liElements = Array.from(ul.children);
// 对 <li> 元素进行排序
liElements.sort((a, b) => {
// 获取每个 <li> 内的 .acvt 元素
let a_acvt = a.querySelector(".acvt");
let b_acvt = b.querySelector(".acvt");
// 获取文本内容,如果 .acvt 元素不存在则使用空字符串
let a_text = a_acvt ? a_acvt.innerText : "";
let b_text = b_acvt ? b_acvt.innerText : "";
return orderMap[a_text] - orderMap[b_text];
});
// 清空 <ul> 内容
ul.innerHTML = '排序中...';
//ul = document.querySelector(".job-list-box");
setTimeout(function(){
ul.innerHTML = '';
liElements.forEach((li,index) => {
ul.appendChild(li);
refresh_tags("排序中("+(index+1)+"/"+(liElements.length)+")");
});
//推荐
if(window.location.pathname=='/web/geek/job-recommend'){
document.querySelector(`.rec-job-list>.active`)?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
refresh_tags("排序已完成");
},1000)
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/*通过iframe获取页面*/
async function iframefun_get(url){
return new Promise((resolve,reject)=>{
let bossact_iframe = document.querySelector(".bossact_iframe");
if(bossact_iframe==undefined || bossact_iframe==null){ //不存在-创建
bossact_iframe = document.createElement('iframe');
}
bossact_iframe.id = 'bossact_iframe';
bossact_iframe.style.display = 'none';
bossact_iframe.src = url;
document.body.appendChild(bossact_iframe);
bossact_iframe.onload = function() {
try {
const iframeDocument = bossact_iframe.contentDocument || bossact_iframe.contentWindow.document;
const targetElement = iframeDocument.querySelector(".boss-active-time") || iframeDocument.querySelector(".boss-online-tag");
let latlog = iframeDocument.querySelector(".job-location-map[data-lat]");
if (targetElement) {
resolve({targetElement,latlog});
} else {
resolve(false)
}
} catch (error) {
resolve(false)
}
};
})
}
function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
// 清除之前的定时器
clearTimeout(timeout);
// 设定新的定时器
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}
async function render_datas(jobas_main) {
refresh_tags("开始处理列表...");
let jobas_index = 0;
for (const jobas of jobas_main) {
let hasacvt = jobas.querySelector(".acvt");
let hasacvts = jobas.querySelectorAll(".acvt");
if(hasacvts.length>1){
hasacvts[hasacvts.length-1].remove();
}
//是否已经w_active
if (!jobas.classList.contains("w_active") && !hasacvt) {
try {
refresh_tags(jobas.innerText+"-处理中("+(jobas_index+1)+"/"+(jobas_main.length)+")");
let parsedUrl = new URL(jobas.href);
// 获取不带参数的 URL
let urlWithoutParams = parsedUrl.origin + parsedUrl.pathname;
let response = await fetch(urlWithoutParams);
let html = await response.text();
let parser = new DOMParser();
let doc = parser.parseFromString(html, "text/html");
let activetime_dom = doc.querySelector(".boss-active-time") || doc.querySelector(".boss-online-tag");
let latlog = doc.querySelector(".job-location-map[data-lat]")||null;
if(activetime_dom==undefined || activetime_dom==null){
console.log("超时,继续寻找")
let againb = await iframefun_get(urlWithoutParams);
activetime_dom = againb?.activetime_dom;
latlog = againb?.latlog;
console.log("ok",activetime_dom)
}
if (activetime_dom) {
let acvt = document.createElement("div");
acvt.className="acvt";
if(activetime_dom.innerHTML.indexOf("刚") !=-1){
acvt.classList.add("acvt-new")
}else if(activetime_dom.innerHTML.indexOf("在线") !=-1){
acvt.classList.add("acvt-online")
}
acvt.innerText = activetime_dom.innerHTML;
let juli_dom = document.createElement("div");
//创建距离
if(latlog){
let latlog_text = latlog.dataset.lat.split(",");
let juli = await getjuli(latlog_text[1]||0,latlog_text[0]||0);
if(juli!=0){
juli_dom.className="wl_juli";
juli_dom.innerText="直线距离:"+juli.toFixed(2)+"km";
}
}
//首页的
if(jobas.classList.contains("job-name") && jobas.parentNode.parentNode.classList.contains("job-info")){
jobas.parentNode.parentNode.append(acvt);
jobas.parentNode.parentNode.append(juli_dom);
}else{
jobas.append(acvt);
jobas.append(juli_dom);
}
let parts = parsedUrl.pathname.split('/');
let encryptJobId = parts[2].split('.')[0];
bossactive[encryptJobId] = activetime_dom.innerHTML;
jobas.classList.add("w_active");
jobas.classList.add("jobas_mouseenter");
refresh_tags(jobas.innerText+"-完成");
}
} catch (err) {
refresh_tags(jobas.innerText+"-处理失败");
console.log('Failed to fetch page: ', err);
}
}
jobas_index++;
}
}
function render_all(selector,ul){
let jobas_main = Array.from(document.querySelectorAll(selector));
render_datas(jobas_main).then(() => {
refresh_tags('所有项目处理完成');
console.log('所有项目处理完成');
sortlist(ul);
//推荐
if(window.location.pathname=='/web/geek/job-recommend'){
document.querySelector(`.rec-job-list>.active`)?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
setTimeout(function(){
refresh_tags("");
},5000);
flag_doing = true;
});
}
function mouse_addactivetime(){
console.log("mouse_addactivetime");
let jobas_main = Array.from(document.querySelectorAll(`a[href^="/job_detail/"]:not(.jobas_mouseenter_begin):not(.w_active)`));
jobas_main.forEach((item)=>{
item.classList.add("jobas_mouseenter_begin");
let debouncedResize = debounce(async function(event){
item.classList.add("jobas_mouseenter");
let jobas = event.target;
let hasacvt = jobas.querySelector(".acvt");
let hasacvts = jobas.querySelectorAll(".acvt");
if(hasacvts.length>1){
hasacvts[hasacvts.length-1].remove();
}
if (!jobas.classList.contains("w_active") && !hasacvt) {
try {
refresh_tags(jobas.innerText+"-处理中");
let parsedUrl = new URL(jobas.href);
// 获取不带参数的 URL
let urlWithoutParams = parsedUrl.origin + parsedUrl.pathname;
let response = await fetch(urlWithoutParams);
let html = await response.text();
let parser = new DOMParser();
let doc = parser.parseFromString(html, "text/html");
let activetime_dom = doc.querySelector(".boss-active-time") || doc.querySelector(".boss-online-tag");
let latlog = doc.querySelector(".job-location-map[data-lat]")||null;
if(activetime_dom==undefined || activetime_dom==null){
console.log("超时,继续寻找")
let againb = await iframefun_get(urlWithoutParams);
activetime_dom = againb?.activetime_dom;
latlog = againb?.latlog;
console.log("ok",activetime_dom)
}
if (activetime_dom) {
let acvt = document.createElement("div");
acvt.className="acvt";
if(activetime_dom.innerHTML.indexOf("刚") !=-1){
acvt.classList.add("acvt-new")
}else if(activetime_dom.innerHTML.indexOf("在线") !=-1){
acvt.classList.add("acvt-online")
}
acvt.innerText = activetime_dom.innerHTML;
let juli_dom = document.createElement("div");
//创建距离
if(latlog){
let latlog_text = latlog.dataset.lat.split(",");
let juli = await getjuli(latlog_text[1]||0,latlog_text[0]||0);
if(juli!=0){
juli_dom.className="wl_juli";
juli_dom.innerText="直线距离:"+juli.toFixed(2)+"km";
}
}
//首页的
if(jobas.classList.contains("job-name") && jobas.parentNode.parentNode.classList.contains("job-info")){
jobas.parentNode.parentNode.append(acvt);
jobas.parentNode.parentNode.append(juli_dom);
}else{
jobas.append(acvt);
jobas.append(juli_dom);
}
let parts = parsedUrl.pathname.split('/');
let encryptJobId = parts[2].split('.')[0];
bossactive[encryptJobId] = activetime_dom.innerHTML;
jobas.classList.add("w_active");
jobas.classList.add("jobas_mouseenter");
refresh_tags(jobas.innerText+"-完成");
}
} catch (err) {
refresh_tags(jobas.innerText+"-处理失败");
console.log('Failed to fetch page: ', err);
}
}
}, 300);
item.addEventListener('mouseenter',debouncedResize);
})
}
// setTimeout(function(){
// flag_doing = false;
// //搜索
// if(window.location.pathname=='/web/geek/job'){
// //搜索
// render_all(`.job-list-box a[href^="/job_detail/"]:not(.jobas_mouseenter):not(.w_active)`,document.querySelector('.job-list-box'));
// //历史记录
// render_all(`.history-job-list a[href^="/job_detail/"]:not(.jobas_mouseenter):not(.w_active)`,document.querySelector('.history-job-list'));
// }
// //推荐
// if(window.location.pathname=='/web/geek/job-recommend'){
// render_all(`.rec-job-list a[href^="/job_detail/"]:not(.jobas_mouseenter):not(.w_active)`,document.querySelector('.rec-job-list'));
// }
// },3000)
setTimeout(async function(){
let testlolat = await getjuli(0,0);
console.log(testlolat);
refresh_tags("Boss直聘活跃度显示已完成准备");
setTimeout(function(){
refresh_tags("");
},3000);
document.querySelector("#wl_action_button").addEventListener('click',function(event){
event.stopPropagation();
if(!flag_doing){
refresh_tags("Boss直聘活跃度显示已在运行中");
return;
}
flag_doing = false;
//搜索
if(window.location.pathname=='/web/geek/job'){
//搜索
render_all(`.job-list-box a[href^="/job_detail/"]:not(.jobas_mouseenter):not(.w_active)`,document.querySelector('.job-list-box'));
//历史记录
render_all(`.history-job-list a[href^="/job_detail/"]:not(.jobas_mouseenter):not(.w_active)`,document.querySelector('.history-job-list'));
}
//推荐
if(window.location.pathname=='/web/geek/job-recommend'){
render_all(`.rec-job-list a[href^="/job_detail/"]:not(.jobas_mouseenter):not(.w_active)`,document.querySelector('.rec-job-list'));
}
})
mouse_addactivetime();
},2000)
let debouncedResize = debounce(mouse_addactivetime,300);
document.addEventListener('click',debouncedResize);
//mouse_addactivetime();
})();