add split filter for expectJobName/expectJobType/expectJobDesc

This commit is contained in:
geekgeekrun
2025-04-18 03:11:39 +08:00
parent e838f48b89
commit f4634c5305
5 changed files with 224 additions and 55 deletions
@@ -79,6 +79,21 @@ const targetCompanyList = readConfigFile('target-company-list.json').filter(it =
const anyCombineRecommendJobFilter = readConfigFile('boss.json').anyCombineRecommendJobFilter
const expectJobRegExpStr = readConfigFile('boss.json').expectJobRegExpStr
let {
expectJobNameRegExpStr,
expectJobTypeRegExpStr,
expectJobDescRegExpStr,
} = readConfigFile('boss.json')
if (
expectJobRegExpStr &&
!expectJobNameRegExpStr &&
!expectJobTypeRegExpStr &&
!expectJobDescRegExpStr
) {
expectJobNameRegExpStr = expectJobRegExpStr
expectJobTypeRegExpStr = expectJobRegExpStr
expectJobDescRegExpStr = expectJobRegExpStr
}
const localStoragePageUrl = `https://www.zhipin.com/desktop/`
const recommendJobPageUrl = `https://www.zhipin.com/web/geek/job-recommend`
@@ -191,22 +206,32 @@ async function markJobAsNotSuitInRecommendPage (reasonCode) {
return result
}
export function testIfJobTitleOrDescriptionSuit (jobInfo, regExpStr) {
if (!regExpStr) {
return true
}
export function testIfJobTitleOrDescriptionSuit (jobInfo) {
let isJobNameSuit = true
try {
const regExp = new RegExp(regExpStr, 'i')
if (
!regExp.test(jobInfo.jobName)
&& !regExp.test(jobInfo.positionName)
&& !regExp.test(jobInfo.postDescription)
) {
return false
if (expectJobNameRegExpStr.trim()) {
const regExp = new RegExp(expectJobNameRegExpStr, 'i')
isJobNameSuit = regExp.test(jobInfo.jobName)
}
} catch {
}
return true
let isJobTypeSuit = true
try {
if (expectJobTypeRegExpStr.trim()) {
const regExp = new RegExp(expectJobTypeRegExpStr, 'i')
isJobTypeSuit = regExp.test(jobInfo.positionName)
}
} catch {
}
let isJobDescSuit = true
try {
if (expectJobDescRegExpStr.trim()) {
const regExp = new RegExp(expectJobDescRegExpStr, 'i')
isJobDescSuit = regExp.test(jobInfo.postDescription)
}
} catch {
}
return isJobNameSuit && isJobTypeSuit && isJobDescSuit
}
async function setFilterCondition (selectedFilters) {
@@ -594,7 +619,7 @@ async function toRecommendPage (hooks) {
continue continueFind
}
if (
!testIfJobTitleOrDescriptionSuit(targetJobData.jobInfo, expectJobRegExpStr)
!testIfJobTitleOrDescriptionSuit(targetJobData.jobInfo)
) {
blockJobNotSuit.add(targetJobData.jobInfo.encryptId)
try {
@@ -612,7 +637,6 @@ async function toRecommendPage (hooks) {
)
} catch {
}
debugger
continue continueFind
}
const startChatButtonInnerHTML = await page.evaluate('document.querySelector(".job-detail-box .op-btn.op-btn-chat")?.innerHTML.trim()')
@@ -72,8 +72,15 @@ export default function initIpc() {
if (hasOwn(payload, 'anyCombineRecommendJobFilter')) {
bossConfig.anyCombineRecommendJobFilter = payload.anyCombineRecommendJobFilter
}
if (hasOwn(payload, 'expectJobRegExpStr')) {
bossConfig.expectJobRegExpStr = payload.expectJobRegExpStr
delete bossConfig.expectJobRegExpStr
if (hasOwn(payload, 'expectJobNameRegExpStr')) {
bossConfig.expectJobNameRegExpStr = payload.expectJobNameRegExpStr
}
if (hasOwn(payload, 'expectJobTypeRegExpStr')) {
bossConfig.expectJobTypeRegExpStr = payload.expectJobTypeRegExpStr
}
if (hasOwn(payload, 'expectJobDescRegExpStr')) {
bossConfig.expectJobDescRegExpStr = payload.expectJobDescRegExpStr
}
if (hasOwn(payload, 'autoReminder')) {
bossConfig.autoReminder = payload.autoReminder
@@ -1,58 +1,137 @@
<template>
<div class="form-wrap">
<div class="form-wrap geek-auto-start-run-with-boss">
<el-form ref="formRef" :model="formContent" label-position="top" :rules="formRules">
<el-form-item label="BOSS直聘 Cookie">
<el-button size="small" type="primary" @click="handleClickLaunchLogin"
>编辑Cookie</el-button
>
</el-form-item>
<el-form-item
<!-- <el-form-item
label="钉钉机器人 AccessToken(用于记录开聊,请勿使用公司内部群)"
prop="dingtalkRobotAccessToken"
>
<el-input v-model="formContent.dingtalkRobotAccessToken" />
</el-form-item> -->
<div>
<el-form-item mb0>
是否查看职位详情的条件
<span font-size-12px>以下条件为空表示不筛选</span>
<el-tooltip effect="light" placement="bottom-start" :enterable="false">
<template #content>
<img block h-270px src="./resources/intro-of-job-entry.png" />
</template>
<div>
<el-button type="text" font-size-12px ml4px
><span><QuestionFilled w-1em h-1em mr2px /></span>期望公司信息位置图示</el-button
>
</div>
</el-tooltip>
</el-form-item>
<el-form-item prop="expectCompanies" mb10px>
<div font-size-12px>期望公司以逗号分隔</div>
<el-input
v-model="formContent.expectCompanies"
:autosize="{ minRows: 4 }"
max-h-6lh
type="textarea"
@blur="normalizeExpectCompanies"
/>
</el-form-item>
</div>
<div mb36px>
<el-form-item mb0>
查看职位详情后是发起投递还是标记不合适的条件
<span font-size-12px>以下条件为空表示不筛选</span>
<el-tooltip effect="light" placement="bottom-start" :enterable="false">
<template #content>
<img block h-270px src="./resources/intro-of-job-info.png" />
</template>
<div>
<el-button type="text" font-size-12px ml4px
><span><QuestionFilled w-1em h-1em mr2px /></span
>职位名称/职位类型/职位描述信息位置图示</el-button
>
</div>
</el-tooltip>
</el-form-item>
<div
:style="{
display: 'grid',
gridTemplateColumns: '1fr 1em 1fr 1em 1fr',
gap: '5px',
width: '100%',
alignItems: 'end'
}"
>
<el-form-item mb0 prop="expectJobNameRegExpStr">
<div font-size-12px>职位名称正则不区分大小写</div>
<el-input
v-model="formContent.expectJobNameRegExpStr"
@blur="
formContent.expectJobNameRegExpStr =
formContent.expectJobNameRegExpStr?.trim() ?? ''
"
/>
</el-form-item>
<div mb10px font-size-12px flex flex-justify-center></div>
<el-form-item mb0 prop="expectJobTypeRegExpStr">
<div font-size-12px>职位类型正则不区分大小写</div>
<el-input
v-model="formContent.expectJobTypeRegExpStr"
@blur="
formContent.expectJobTypeRegExpStr =
formContent.expectJobTypeRegExpStr?.trim() ?? ''
"
/>
</el-form-item>
<div mb10px font-size-12px flex flex-justify-center></div>
<el-form-item mb0 prop="expectJobDescRegExpStr">
<div font-size-12px>职位描述正则不区分大小写</div>
<el-input
v-model="formContent.expectJobDescRegExpStr"
@blur="
formContent.expectJobDescRegExpStr =
formContent.expectJobDescRegExpStr?.trim() ?? ''
"
/>
</el-form-item>
</div>
</div>
<el-form-item pt10px mb10px>
<div style="--font-size: 12px; font-size: var(--font-size)" line-height-1.5em>
<div class="color-orange mb4px">标记不合适机制</div>
<ol m0 line-height-1.5em>
<li>
如果查找到的职位职位名称职位类型职位描述与如上正则不匹配则这个职位将被标记为不合适
</li>
<li>如果查找到的职位活跃时间为本月活跃或更往前的时间则这个职位将被标记为不合适</li>
<li>
如有错误标记请在左侧<a
href="javascript:void(0)"
style="color: var(--el-color-primary)"
@click.prevent="$router.push('/main-layout/MarkAsNotSuitRecord')"
>标记不合适</a
>记录中找到相关记录手动对这些职位发起会话
</li>
</ol>
</div>
</el-form-item>
<el-form-item
label="期望职位白名单正则(按照职位名称+职位描述筛选职位,为空时将不按此条件筛选"
prop="expectJobRegExpStr"
>
<el-input v-model="formContent.expectJobRegExpStr" />
</el-form-item>
<el-form-item label="期望公司(以逗号分隔,为空时将不按此条件筛选)" prop="expectCompanies">
<el-input
v-model="formContent.expectCompanies"
:autosize="{ minRows: 4 }"
type="textarea"
@blur="normalizeExpectCompanies"
/>
</el-form-item>
<el-form-item
label="推荐职位筛选器(当前求职期望找不到合适职位时,将尝试所有可能的筛选组合,查找新工作)"
label="职位备选筛选条件(当前求职期望无合适职位时,自动更改Boss筛选条件,查找新工作"
prop="filter"
mb0
>
<AnyCombineBossRecommendFilter v-model="formContent.anyCombineRecommendJobFilter" />
<div>
当前组合条件数{{ currentAnyCombineRecommendJobFilterCombinationCount.toLocaleString() }}
<span
v-if="
currentAnyCombineRecommendJobFilterCombinationCount >= 10 &&
currentAnyCombineRecommendJobFilterCombinationCount < 100
"
v-if="currentAnyCombineRecommendJobFilterCombinationCount >= 20"
class="color-orange"
>组合条件太多,建议选择一些</span
>
<span
v-if="currentAnyCombineRecommendJobFilterCombinationCount >= 100"
class="color-orange"
>你开心就好</span
>建议选择太多组合条件</span
>
</div>
</el-form-item>
<el-form-item label="标记不合适机制" class="color-orange">
1. 如果查找到的职位活跃时间为“本月活跃”或更往前的时间,则这个职位将被标记为不合适<br />
2. 如果查找到的职位,职位名称、职位类型、职位描述与期望职位白名单正则不匹配,则这个职位将被标记为不合适
</el-form-item>
<el-form-item class="last-form-item">
<el-form-item class="last-form-item mb0">
<el-button @click="handleSave">仅保存配置</el-button>
<el-button type="primary" @click="handleSubmit"> 保存配置并开始求职 </el-button>
</el-form-item>
@@ -63,6 +142,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { ElForm, ElMessage } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import AnyCombineBossRecommendFilter from '@renderer/features/AnyCombineBossRecommendFilter/index.vue'
import { calculateTotalCombinations } from '@geekgeekrun/geek-auto-start-chat-with-boss/combineCalculator.mjs'
@@ -73,7 +153,9 @@ const formContent = ref({
dingtalkRobotAccessToken: '',
expectCompanies: '',
anyCombineRecommendJobFilter: {},
expectJobRegExpStr: ''
expectJobNameRegExpStr: '',
expectJobTypeRegExpStr: '',
expectJobDescRegExpStr: ''
})
const currentAnyCombineRecommendJobFilterCombinationCount = computed(() => {
@@ -92,24 +174,71 @@ electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => {
scaleList: [],
industryList: []
}
formContent.value.expectJobRegExpStr = res.config['boss.json']?.expectJobRegExpStr ?? ''
//
if (
res.config['boss.json']?.expectJobRegExpStr &&
typeof res.config['boss.json']?.expectJobNameRegExpStr === 'undefined' &&
typeof res.config['boss.json']?.expectJobTypeRegExpStr === 'undefined' &&
typeof res.config['boss.json']?.expectJobDescRegExpStr === 'undefined'
) {
res.config['boss.json'].expectJobNameRegExpStr = res.config['boss.json'].expectJobRegExpStr
res.config['boss.json'].expectJobTypeRegExpStr = res.config['boss.json'].expectJobRegExpStr
res.config['boss.json'].expectJobDescRegExpStr = res.config['boss.json'].expectJobRegExpStr
}
formContent.value.expectJobNameRegExpStr = res.config['boss.json'].expectJobNameRegExpStr?.trim()
formContent.value.expectJobTypeRegExpStr = res.config['boss.json'].expectJobTypeRegExpStr?.trim()
formContent.value.expectJobDescRegExpStr = res.config['boss.json'].expectJobDescRegExpStr?.trim()
})
const formRules = {
expectJobRegExpStr: {
expectJobNameRegExpStr: {
validator(_, value, cb) {
if (!value) {
cb()
gtagRenderer('empty_reg_exp_for_expect_job')
gtagRenderer('empty_reg_exp_for_expect_job_name')
return
}
try {
new RegExp(value, 'ig')
gtagRenderer('valid_reg_exp_for_expect_job')
gtagRenderer('valid_reg_exp_for_expect_job_name')
cb()
} catch (err) {
cb(new Error(`正则无效:${err?.message}`))
gtagRenderer('invalid_reg_exp_for_expect_job')
gtagRenderer('invalid_reg_exp_for_expect_job_name')
}
}
},
expectJobTypeRegExpStr: {
validator(_, value, cb) {
if (!value) {
cb()
gtagRenderer('empty_reg_exp_for_expect_job_type')
return
}
try {
new RegExp(value, 'ig')
gtagRenderer('valid_reg_exp_for_expect_job_type')
cb()
} catch (err) {
cb(new Error(`正则无效:${err?.message}`))
gtagRenderer('invalid_reg_exp_for_expect_job_type')
}
}
},
expectJobDescRegExpStr: {
validator(_, value, cb) {
if (!value) {
cb()
gtagRenderer('empty_reg_exp_for_expect_job_desc')
return
}
try {
new RegExp(value, 'ig')
gtagRenderer('valid_reg_exp_for_expect_job_desc')
cb()
} catch (err) {
cb(new Error(`正则无效:${err?.message}`))
gtagRenderer('invalid_reg_exp_for_expect_job_desc')
}
}
}
@@ -120,7 +249,7 @@ const handleSubmit = async () => {
gtagRenderer('save_config_and_launch_clicked', {
has_dingtalk_robot_token: !!formContent.value?.dingtalkRobotAccessToken
})
formContent.value.expectJobRegExpStr = (formContent.value.expectJobRegExpStr || '').trim()
formContent.value.expectJobRegExpStr = undefined
await formRef.value!.validate()
await electron.ipcRenderer.invoke('save-config-file-from-ui', JSON.stringify(formContent.value))
router.replace({
@@ -175,3 +304,12 @@ const handleClickLaunchLogin = () => {
}
}
</style>
<style lang="scss">
.form-wrap.geek-auto-start-run-with-boss {
.el-form-item__error.el-form-item__error {
font-size: 12px;
line-height: 1.2em;
}
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB