Greasy Fork is available in English.

BOSS 直聘岗位发布时间

Display last modify time for Boss job list items

// ==UserScript==
// @name         BOSS 直聘岗位发布时间
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  Display last modify time for Boss job list items
// @author       Your Name
// @match        https://*.zhipin.com/*   
// @icon         https://www.google.com/s2/favicons?sz=64&domain=zhipin.com
// @homepage     https://github.com/chengazhen/apply-to-jop
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  rewriteXHR()

  async function getBossJobListData(responseText) {
    try {
      const data = JSON.parse(responseText);
      const jopList = data?.zpData?.jobList || []
      const jobListContainer = await waitUntilJobListRendered()
      jopList.length && updateJobListItemsWithTime(jopList, jobListContainer);
    } catch (err) {
      console.error("reason:", err);
    }
  }

  function waitUntilJobListRendered() {
    return new Promise((resolve, reject) => {

      const jobResultContainer = document.querySelector(".search-job-result");
      if (!jobResultContainer) {
        return reject(new Error("未找到职位列表的容器"));
      }



      // 轮询职位列表是否渲染
      const intervalId = setInterval(() => {
        const jobListContainer = jobResultContainer.querySelector(".job-list-box");
        if (jobListContainer) {
          clearInterval(intervalId);
          return resolve(jobListContainer);
        }
      }, 100);

    });
  }

  function updateJobListItemsWithTime(jobList, jobListContainer) {
    jobList.forEach((job) => {
      const listItem = jobListContainer.querySelector(`[ka="search_list_${job.itemId}"]`);
      if (listItem) {
        const lastModifyTimeTag = createLastModifyTimeTag(job.lastModifyTime);
        //放在最上面
        listItem.insertBefore(lastModifyTimeTag, listItem.firstChild);
      }
    });
  }

  function createLastModifyTimeTag(timeStamp) {
    const timeString = formatDate(new Date(timeStamp), "YYYY-MM-DD HH:mm:ss");
    const timeTag = document.createElement("div");
    timeTag.style.color = "white";
    timeTag.style.padding = "0px 5px";
    timeTag.style.borderRadius = "4px 4px 0px 0px";

    const now = new Date();
    const modifyTime = new Date(timeStamp);
    const differenceInDays = diffDay(now, modifyTime);

    if (differenceInDays <= 14) {
      timeTag.style.background = "rgb(4, 197, 165)"; // 绿色,距今两周内
    } else if (differenceInDays > 14 && differenceInDays <= 45) {
      timeTag.style.background = "#F0AD4E"; // 暗橙色,两周到一个半月
    } else {
      timeTag.style.background = "red"; // 红色,超过一个半月
    }

    const dayPassed = diffDay(now, modifyTime);
    timeTag.textContent = `${timeString}(距今${dayPassed}天)`;
    return timeTag;
  }

  function formatDate(date, format) {
    const map = {
      'YYYY': date.getFullYear(),
      'MM': ('0' + (date.getMonth() + 1)).slice(-2),
      'DD': ('0' + date.getDate()).slice(-2),
      'HH': ('0' + date.getHours()).slice(-2),
      'mm': ('0' + date.getMinutes()).slice(-2),
      'ss': ('0' + date.getSeconds()).slice(-2)
    };
    return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (str) => map[str]);
  }

  function diffDay(date1, date2) {
    const diffInMs = Math.abs(date1 - date2);
    return Math.floor(diffInMs / (1000 * 60 * 60 * 24));
  }


  function rewriteXHR() {
    const realXHR = window.XMLHttpRequest;
    window.XMLHttpRequest = function () {
      const xhr = new realXHR();

      // 保留原始的open方法
      const oldOpen = xhr.open;
      xhr.open = function (method, url, async, user, password) {
        // 只在需要的时候添加load事件监听器
        if (url.includes('/list.json?') || url.includes('/joblist.json?')) {
          xhr.addEventListener('load', function () {
            if (this.status === 200) {
              getBossJobListData(this.responseText);
            } else {
              console.error('请求失败:', this.status);
            }
          }, false);
        }
        // 调用原始的open方法
        oldOpen.apply(this, arguments);
      };
      return xhr;
    };
  }
})();