diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0a94740..8e75dbb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,6 +4,8 @@ on: push: branches: - master + paths: + - src/** jobs: build: diff --git a/JudgmentConditions.md b/JudgmentConditions.md deleted file mode 100644 index 27e9a35..0000000 --- a/JudgmentConditions.md +++ /dev/null @@ -1,67 +0,0 @@ -# 判定条件 - -## 关键词判断 - -只要出现就认定存在可能,如果出现二次则默认 100%判定为,关键词如下: - -- 解决方案 -- 技术服务 -- 驻场 -- 出差 -- 现场 -- 派遣 -- 国内领先 -- 服务提供商 -- 数字化转型 -- 定制化系统 -- 一站式服务 -- 为客户提供 -- 一体化 - -参考: - -- https://www.zhihu.com/question/32123407 - -## 黑名单 - -对于出现的即认定是外包 - -- 博朗软件 -- 中软国际 -- 东软集团 -- 博彦科技 -- 中电金信 -- 法本信息 -- 浙大网新 -- 奥博杰天 -- 浪潮 -- 软通动力 -- 福瑞博德 -- 信必优 -- 大展科技 -- 恒生电子 -- 日电卓越软件 -- 大连华信 -- 中和软件 -- 新致软件 -- 艾斯克雷 -- 海隆软件 -- 大宇宙信息 -- 晟峰软件 -- 富士通信息 -- NTTDATA -- 宏智科技 -- 神州数码通用软件 -- 凌志软件 -- 音泰思 -- 微创软件 -- 开目佰钧成 -- 浩鲸智能 -- 诚迈科技 -- 润和软件 -- ST 新海 - -参考: - -- https://zhuanlan.zhihu.com/p/407777028 -- https://www.zvsts.com/article/news/1/4e347ffffe83fd932bcbbf4efafb0000.html diff --git a/README.md b/README.md index a3bd8bc..c5c8152 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ ![tips1](./tips1.png) ![tips2](./tips2.png) -> 如果你对它的判定规则好奇,你可以 [点击查看具体规则](./JudgmentConditions.md)。 -> 如果你有好的个规则补充,可以修改 [information.json](./src/information.json) 文件进行 PR,后续审核通过就会发版。 > 使用需要结合油猴插件使用 ## 使用方式 @@ -24,6 +22,18 @@ pnpm run build # 重复方法一 ``` +## 判定规则 + +采用黑名单 + 关键词的机制,如果公司名称出现在黑名单上则直接判定为黑名单,否则关键词出现一次,进行提示,出现两次则认定。 + +参考规则: + +- https://www.zhihu.com/question/32123407 +- https://zhuanlan.zhihu.com/p/407777028 +- https://www.zvsts.com/article/news/1/4e347ffffe83fd932bcbbf4efafb0000.html + +> 如果你有好的个规则补充,可以修改 [information.json](./src/information.json) 文件进行 PR,后续审核通过就会发版。 + ## 协议 MIT License diff --git a/package.json b/package.json index 322faa4..5764693 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "boss-outsourcing-tips", - "version": "1.0.1", + "version": "1.0.2", "description": "boss招聘对外包公司显式提醒", "main": "dist/index.js", "scripts": { diff --git a/src/KeyWords.ts b/src/KeyWords.ts index 26071fd..f4062bc 100644 --- a/src/KeyWords.ts +++ b/src/KeyWords.ts @@ -1,29 +1,72 @@ import { _ReturnType } from "./chain"; import information from "./information.json"; +const traverse = (dom: Element, fn: (el: ChildNode) => void): void => { + const arr = Array.from(dom.childNodes); + arr.forEach((item) => { + if (item.nodeType === Node.ELEMENT_NODE) { + traverse(item as Element, fn); + return; + } + fn(item); + }); +}; + export const keyWords = (): _ReturnType => { const selectors = [ - ".job-banner", - ".job-detail-section", - ".job-detail-company", + ".info-primary h1", + ".job-detail-section .job-sec-text", + ".job-detail-company .job-sec-text", ]; - const content = selectors.reduce((text, selector) => { - const dom = document.body.querySelector(selector); - return text + (dom?.textContent ?? ""); - }, ""); - // 如果出现一个则提示存在高危风险,两个则直接提示为外包公司谨慎选择 - let text = "该岗位描述符合外包定义,具体如下:\n"; - const frequency = information.KeyWords.reduce((count, KeyWord) => { - if (content.includes(KeyWord)) { - text += `${count + 1}. ${KeyWord}\n`; - return count + 1; + const store: Set = new Set(); + + const effect = (el: ChildNode) => { + if (el.nodeType !== Node.TEXT_NODE) { + return; + } + let content = el.textContent || ""; + + // 可能存在多个关键词都在一串文本出现 + information.KeyWords.forEach((KeyWord) => { + if (content.includes(KeyWord)) { + store.add(KeyWord); + content = content.replace( + new RegExp(KeyWord, "g"), + `${KeyWord}` + ); + } + }); + if (content === el.textContent) { + return; + } + const fragment = document.createDocumentFragment(); + const span = document.createElement("span"); + span.innerHTML = content; + while (span.firstChild) { + fragment.appendChild(span.firstChild); } - return count; - }, 0); + el.parentNode?.replaceChild(fragment, el); + }; + + selectors.forEach((text) => { + const dom = document.body.querySelector(text); + if (!dom) { + return; + } + traverse(dom, effect); + }); + // 如果没有匹配到,转移到下一个链条进行匹配 - if (!frequency) { + if (!store.size) { return true; } - return { grade: frequency === 1 ? 0 : 1, text: text.trim() }; + return { + grade: store.size === 1 ? 0 : 1, + text: `该岗位描述符合外包定义,出现了:\n${[...store] + .map((item, index) => { + return `${index + 1}. ${item}`; + }) + .join("\n")}`, + }; }; diff --git a/src/blacklist.ts b/src/blacklist.ts index fe55c0d..f154112 100644 --- a/src/blacklist.ts +++ b/src/blacklist.ts @@ -2,15 +2,22 @@ import { _ReturnType } from "./chain"; import information from "./information.json"; export const blacklist = (): _ReturnType => { - const content = - document.body.querySelector(`a[ka="job-detail-company_custompage"]`) - ?.textContent || ""; + const dom = document.body.querySelector( + `a[ka="job-detail-company_custompage"]` + ) as HTMLAreaElement | null; + + if (!dom) { + return true; + } + + const content = dom.textContent || ""; let text = ""; const frequency = information.blacklist.some((KeyWord) => { if (content.includes(KeyWord)) { text = `公司名称为外包:${KeyWord}`; + dom.style.color = "red"; return true; } return false; diff --git a/src/chain.ts b/src/chain.ts index d4f64a2..adf72f6 100644 --- a/src/chain.ts +++ b/src/chain.ts @@ -1,6 +1,6 @@ import { keyWords } from "./KeyWords"; import { blacklist } from "./blacklist"; -import { Props } from "./notify"; +import { Props } from "./pages/notify"; export type _ReturnType = (Props & { text: string }) | boolean; @@ -11,7 +11,8 @@ class Chain { next(): _ReturnType { const result = this.fn(); - if (result && this.chain) { + + if (result === true && this.chain) { return this.chain.next.apply(this.chain); } return result; @@ -26,4 +27,5 @@ class Chain { const chainKeyWords = new Chain(keyWords); const chainBlacklist = new Chain(blacklist); -export const result = chainBlacklist.setNext(chainKeyWords).next(); +chainBlacklist.setNext(chainKeyWords); +export const result = chainBlacklist.next(); diff --git a/src/index.ts b/src/index.ts index 29e2bd9..261b449 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,19 +1,11 @@ import { result } from "./chain"; -import { getHtml } from "./notify"; -import { addReminder } from "./utils"; +import { insertNotify } from "./pages/notify"; +import { addReminder } from "./pages/reminder"; (() => { if (typeof result === "boolean") { return; } - const html = getHtml(result); - const dom = document.body.querySelector(".btn-container"); - if (!dom) { - return; - } - const div = document.createElement("div"); - div.innerHTML = html; - dom.appendChild(div.firstElementChild!); - + insertNotify(result); addReminder(result.text); })(); diff --git a/src/information.json b/src/information.json index 6b833dd..db1d1e3 100644 --- a/src/information.json +++ b/src/information.json @@ -33,7 +33,11 @@ "浩鲸智能", "诚迈科技", "润和软件", - "ST 新海" + "ST 新海", + "慧博云通", + "天源迪科", + "上海思芮", + "塔塔" ], "KeyWords": [ "解决方案", diff --git a/src/notify.tsx b/src/pages/notify.tsx similarity index 67% rename from src/notify.tsx rename to src/pages/notify.tsx index e4eeb4f..42f8e22 100644 --- a/src/notify.tsx +++ b/src/pages/notify.tsx @@ -26,6 +26,14 @@ const Notify: FunctionComponent = (props) => { ); }; -export const getHtml = (props: Props) => { - return render(); +export const insertNotify = (props: Props) => { + const html = render(); + + const dom = document.body.querySelector(".btn-container"); + if (!dom) { + return; + } + const div = document.createElement("div"); + div.innerHTML = html; + dom.appendChild(div.firstElementChild!); }; diff --git a/src/pages/reminder.tsx b/src/pages/reminder.tsx new file mode 100644 index 0000000..b0d9e53 --- /dev/null +++ b/src/pages/reminder.tsx @@ -0,0 +1,26 @@ +import { FunctionComponent } from "preact"; +import { render } from "preact-render-to-string"; + +interface Props { + text: string; +} + +const Reminder: FunctionComponent = ({ text }) => { + return ( +
+ 查看具体判定规则 +

{text}

+
+ ); +}; + +export const addReminder = (text: string) => { + const dom = document.body.querySelector(".job-detail"); + if (!dom) { + return; + } + const html = render(); + const t = document.createElement("div"); + t.innerHTML = html; + dom.insertBefore(t, dom.firstChild); +}; diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index 1b2cad9..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const addReminder = (text: string) => { - const dom = document.body.querySelector(".job-detail"); - if (!dom) { - return; - } - const t = document.createElement("p"); - t.innerHTML = text; - t.style.cssText = `white-space: pre;`; - dom.insertBefore(t, dom.firstChild); -};