pc版boss直聘显示岗位时间插件

发布于:2024-04-30 ⋅ 阅读:(16) ⋅ 点赞:(0)

先看下插件效果 image.png

背景

最近被广进了,可以说是相当焦虑,疯狂刷各种招聘软件找面试机会,在刷 boss 直聘的时候发现有些岗位已经存在很久了,4年前我刚毕业时看到的岗位居然还在,属实有点离谱,想着有没有什么方式把岗位的时间给显示出来。

怎么获取时间

想要展示时间,那么第一步我得知道时间在哪,所以先去 web 端 boss 直聘去找接口,发现有个 joblist 接口返回列表数据,并且里面有个 lastModifyTime 的值,看名字应该是职位的最后修改时间,但不能确定这个时间就是岗位的修改时间。我这主要是对比了下 app 端有 new 标签的职位和 web 端这里的时间,看时间是否相近。对比下来感觉这个时间应该靠谱所以就使用了这个字段。(如果不对那就当熟悉下 chrome 插件的开发了😂

image.png

怎么展示时间

chrome 插件的基础开发就不介绍了,大家可以自己去找下相应的教程

1. 重写 XMLHttpRequest

既然需要数据那么就需要监听接口请求,这里是通过重写 XMLHttpRequest 来实现的,由于 content-script 脚本没办法直接修改原页面的 js,所以通过 script 标签插入自己的脚本(proxyAjax.js),在这个脚本里去重写 XMLHttpRequest。注意:proxyAjax 脚本必须插入在 head 标签第一个节点中,boss 直聘的页面里有也有重写 XMLHttpRequest 的操作,所以要提前去执行

let oldXHR = window.XMLHttpRequest;
 function newXHR() {
      let realXHR = new oldXHR();
      realXHR.addEventListener('readystatechange', function(e) { 
          // 自定义的事件,抛出去
          ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); 
      }, false);
  }

2. 获取职位的 DOM

拿到数据后开始分析数据和对应的 DOM 有什么关联?假如是我们自己开发这个业务,很显然会去用数组去循环生成视图,那么一般来说会用一个 id 来作为 key 值,所以找到这个关联的 id。

分析下图的数据,可以比较明显看出来 li 标签的 ka 属性用的是 itemId(截图里还不是很明显,往后翻一页就会发现这两个能对上), search_list_${itemId},所以就可以直接用选择器去获取对应的dom

node.querySelector(`[ka="search_list_${itemId}"]`);

image.png

image.png

3. 插入时间标签

在上一步我们分析了怎么去获取对应的 DOM,获取到了就可以给 DOM 插入标签了,对整个数据进行循环,对每个元素获取一次 DOM,然后创建 div 插入到 DOM 当中

// 获取职位列表节点
function getListByNode(node) {
    return function getListItem(itemId) {
        return node.querySelector(`[ka="search_list_${itemId}"]`);
    }
}
// 向 DOM 插入标签
function parseBossData(list, getListItem) {
    list.forEach(item => {
        const {
            itemId, lastModifyTime,
        }  = item;
        const time = dayjs(lastModifyTime).format('YYYY-MM-DD HH:mm:ss');
        // 获取 DOM 
        const dom = getListItem(itemId);
        // 生成标签
        let tag = createDOM(time); 
        // 插入 DOM 
        dom.appendChild(tag);
    });
}
// 生成标签
function createDOM(time) {
    const div = document.createElement('div');
    div.classList.add('__boss_time_tag');
    div.innerText = time;
    return div;
}

4. 结束了吗?

看上去好像完美了,但实际上发现没有生效,并且报错 node.querySelector is not a function。为什么会这样?如果看到这可以考虑下。

其实原因很简单,获取数据后到我们代码执行其实是同步的,此时视图对应的节点还没有创建出来,所以获取的 node 为 null。那么怎么保证 node 节点能拿到呢?js 提供了一个 MutationObserver api,通过这个来监听节点的变化,是否新增了节点,在确保新增之后再去运行我们之前的代码这样就保证了能拿到 node 节点。

// 监听 search-job-result 节点,判断职位列表是否被挂载
function mutationContainer () {
   return new Promise((resolve, reject) => {
        // 获取列表的父节点容器,监听该节点
        const dom = document.querySelector('.search-job-result');
        // 创建 MutationObserver 实例
        const observer = new MutationObserver(function(childList, obs) {
            (childList || []).forEach(item => {
                const {
                    addedNodes
                } = item;
                if(addedNodes && addedNodes.length > 0)  {
                    addedNodes.forEach(node => {
                        const {
                            className,
                        } = node;
                        if(className === 'job-list-box') {
                            observer.disconnect();
                            resolve(node);
                        }
                    })
                } 
            });
            return reject('未找到职位列表');

        })

        observer.observe(dom, {
            childList: true,
            subtree: false
        })
   })
}

// 回调的时候去执行插入标签操作
mutationContainer().then((node) => {
    parseBossData(data?.zpData?.jobList || [], getListByNode(node));
})

结尾:

代码我放在 github 仓库了,有需要的可以去看看,如果觉得还可以顺便点个 star 吧,求求了

切换分支 gh-page 有已经编译好的插件,可以直接下载使用

image.png

github仓库


网站公告

今日签到

点亮在社区的每一天
去签到