Merge branch 'feature/static-combine-job-filter' into feature/ui

This commit is contained in:
geekgeekrun
2025-11-01 23:14:47 +08:00
9 changed files with 494 additions and 74 deletions
@@ -124,3 +124,35 @@ export function checkAnyCombineBossRecommendFilterHasCondition(value) {
return !!value[k]?.length
})
}
export function getStaticCombineFilterKey(condition) {
const kAsO = {}
for (const key of Object.keys(condition ?? []).sort()) {
if (condition[key] === null || condition[key] === undefined) {
continue
}
kAsO[key] = condition[key]
}
return JSON.stringify(kAsO)
}
export function formatStaticCombineFilters(rawStaticCombineRecommendJobFilterConditions) {
rawStaticCombineRecommendJobFilterConditions = JSON.parse(JSON.stringify(rawStaticCombineRecommendJobFilterConditions))
const map = new Map()
for (const condition of rawStaticCombineRecommendJobFilterConditions ?? []) {
const key = getStaticCombineFilterKey(condition)
map.set(key, condition)
}
const conditions = Array.from(map.values())
const result = conditions.map((condition) => {
return {
salaryList: condition.salary ? [condition.salary] : [],
experienceList: condition.experience ? [condition.experience] : [],
degreeList: condition.degree ? [condition.degree] : [],
scaleList: condition.scale ? [condition.scale] : [],
industryList: condition.industry ? [condition.industry] : []
}
})
result.unshift(null)
return result
}
@@ -1,4 +1,5 @@
{
"combineRecommendJobFilterType": 1,
"anyCombineRecommendJobFilter": {
"salaryList": [],
"experienceList": [],
@@ -6,6 +7,7 @@
"scaleList": [],
"industryList": []
},
"staticCombineRecommendJobFilterConditions": [],
"isSkipEmptyConditionForCombineRecommendJobFilter": false,
"expectJobRegExpStr": "",
"jobNotMatchStrategy": 1,
@@ -15,12 +15,21 @@ import { readConfigFile, writeStorageFile, ensureConfigFileExist, readStorageFil
import {
calculateTotalCombinations,
combineFiltersWithConstraintsGenerator,
checkAnyCombineBossRecommendFilterHasCondition
checkAnyCombineBossRecommendFilterHasCondition,
formatStaticCombineFilters,
} from './combineCalculator.mjs'
import { default as jobFilterConditions } from './internal-config/job-filter-conditions-20241002.json'
import { default as rawIndustryFilterExemption } from './internal-config/job-filter-industry-filter-exemption-20241002.json'
import { ChatStartupFrom } from '@geekgeekrun/sqlite-plugin/dist/entity/ChatStartupLog'
import { MarkAsNotSuitReason, MarkAsNotSuitOp, StrategyScopeOptionWhenMarkJobNotMatch, SalaryCalculateWay, JobDetailRegExpMatchLogic, JobSource } from '@geekgeekrun/sqlite-plugin/dist/enums'
import {
MarkAsNotSuitReason,
MarkAsNotSuitOp,
StrategyScopeOptionWhenMarkJobNotMatch,
SalaryCalculateWay,
JobDetailRegExpMatchLogic,
JobSource,
CombineRecommendJobFilterType
} from '@geekgeekrun/sqlite-plugin/dist/enums'
import {
activeDescList,
RECOMMEND_JOB_ENTRY_SELECTOR,
@@ -85,8 +94,10 @@ const bossCookies = readStorageFile('boss-cookies.json')
const bossLocalStorage = readStorageFile('boss-local-storage.json')
const targetCompanyList = readConfigFile('target-company-list.json').filter(it => !!it.trim());
const combineRecommendJobFilterType = readConfigFile('boss.json').combineRecommendJobFilterType ?? CombineRecommendJobFilterType.ANY_COMBINE
const anyCombineRecommendJobFilter = readConfigFile('boss.json').anyCombineRecommendJobFilter
const staticCombineRecommendJobFilterConditions = readConfigFile('boss.json').staticCombineRecommendJobFilterConditions ?? []
let isSkipEmptyConditionForCombineRecommendJobFilter = readConfigFile('boss.json').isSkipEmptyConditionForCombineRecommendJobFilter
if (!checkAnyCombineBossRecommendFilterHasCondition(anyCombineRecommendJobFilter)) {
isSkipEmptyConditionForCombineRecommendJobFilter = false
@@ -359,7 +370,7 @@ export function testIfJobTitleOrDescriptionSuit (jobInfo, matchLogic) {
try {
if (expectJobNameRegExpStr.trim()) {
const regExp = new RegExp(expectJobNameRegExpStr, 'i')
isJobNameSuit = regExp.test(jobInfo.jobName)
isJobNameSuit = regExp.test(jobInfo.jobName?.replace(/\n/g, '') ?? '')
}
} catch {
}
@@ -367,7 +378,7 @@ export function testIfJobTitleOrDescriptionSuit (jobInfo, matchLogic) {
try {
if (expectJobTypeRegExpStr.trim()) {
const regExp = new RegExp(expectJobTypeRegExpStr, 'i')
isJobTypeSuit = regExp.test(jobInfo.positionName)
isJobTypeSuit = regExp.test(jobInfo.positionName?.replace(/\n/g, '') ?? '')
}
} catch {
}
@@ -375,7 +386,7 @@ export function testIfJobTitleOrDescriptionSuit (jobInfo, matchLogic) {
try {
if (expectJobDescRegExpStr.trim()) {
const regExp = new RegExp(expectJobDescRegExpStr, 'i')
isJobDescSuit = regExp.test(jobInfo.postDescription)
isJobDescSuit = regExp.test(jobInfo.postDescription?.replace(/\n/g, '') ?? '')
}
} catch {
}
@@ -662,11 +673,13 @@ async function toRecommendPage (hooks) {
}
}
const filterConditions =
combineRecommendJobFilterType === CombineRecommendJobFilterType.STATIC_COMBINE
? formatStaticCombineFilters(staticCombineRecommendJobFilterConditions)
: combineFiltersWithConstraintsGenerator(anyCombineRecommendJobFilter)
let expectJobList
iterateFilterCondition: for (
const filterCondition of combineFiltersWithConstraintsGenerator(
anyCombineRecommendJobFilter
)
const filterCondition of filterConditions
) {
findInCurrentFilterCondition: while(true) {
await sleepWithRandomDelay(2500)
@@ -691,11 +704,17 @@ async function toRecommendPage (hooks) {
break
}
}
if (
isSkipEmptyConditionForCombineRecommendJobFilter &&
Object.keys(filterCondition).length &&
Object.keys(filterCondition).every(k => !filterCondition[k]?.length)
(
combineRecommendJobFilterType === CombineRecommendJobFilterType.STATIC_COMBINE && filterCondition === null
)
||
(
combineRecommendJobFilterType === CombineRecommendJobFilterType.ANY_COMBINE &&
isSkipEmptyConditionForCombineRecommendJobFilter &&
Object.keys(filterCondition).length &&
Object.keys(filterCondition).every(k => !filterCondition[k]?.length)
)
) {
sleep(4000)
continue iterateFilterCondition
+5
View File
@@ -34,3 +34,8 @@ export enum JobSource {
recommend = 2,
search = 3,
}
export enum CombineRecommendJobFilterType {
ANY_COMBINE = 1,
STATIC_COMBINE = 2,
}
@@ -159,6 +159,13 @@ export default function initIpc() {
if (hasOwn(payload, 'jobSourceList')) {
bossConfig.jobSourceList = payload.jobSourceList
}
if (hasOwn(payload, 'combineRecommendJobFilterType')) {
bossConfig.combineRecommendJobFilterType = payload.combineRecommendJobFilterType
}
if (hasOwn(payload, 'staticCombineRecommendJobFilterConditions')) {
bossConfig.staticCombineRecommendJobFilterConditions =
payload.staticCombineRecommendJobFilterConditions
}
promiseArr.push(writeConfigFile('boss.json', bossConfig))
@@ -0,0 +1,264 @@
<template>
<div>
<el-button p-0 h-auto flex size="small" type="text" :icon="Plus" @click="addCondition"
>添加条件</el-button
>
<div class="job-combo-filter" mt-8px>
<el-table
size="small"
:data="props.modelValue"
border
:style="{ maxWidth: '100%' }"
:row-style="
({ row }) => {
return {
backgroundColor:
duplicatedMap.get(getStaticCombineFilterKey(row))?.length > 1
? '#fcd4b7'
: 'transparent'
}
}
"
>
<template #empty>
<div lh-1.5em>
列表中没有条件,将仅使用默认的“初始空条件”为您筛选职位<br />
你可以点击表格左上角“<el-button
p-0
h-auto
size="small"
type="text"
:icon="Plus"
@click="addCondition"
>添加条件</el-button
>”按钮,添加更多筛选条件。
</div>
</template>
<el-table-column :resizable="false" label="" :width="80">
<template #default="{ $index: index }">
<div
:style="{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '2px',
height: 'fit-content'
}"
>
<el-button
:disabled="index <= 0"
style="margin: 0"
circle
size="small"
:icon="ArrowUp"
@click="moveConditionUp(index)"
/>
<el-button
:disabled="index >= modelValue?.length - 1"
style="margin: 0"
circle
size="small"
:icon="ArrowDown"
@click="moveConditionDown(index)"
/>
<el-button
style="margin: 0"
circle
size="small"
:icon="Delete"
@click="removeCondition(index)"
/>
</div>
</template>
</el-table-column>
<el-table-column :resizable="false" label="薪资待遇" prop="salary">
<template #default="{ row }">
<el-select
v-model="row.salary"
:disabled="row.___itemType === 'empty-condition-placeholder'"
clearable
size="small"
>
<el-option
v-for="it in conditions.salaryList.filter((it) => it.code !== 0)"
:key="it.code"
:value="it.code"
:label="it.name"
/>
</el-select>
</template>
</el-table-column>
<el-table-column :resizable="false" label="工作经验" prop="experience">
<template #default="{ row }">
<el-select
v-model="row.experience"
:disabled="row.___itemType === 'empty-condition-placeholder'"
clearable
size="small"
>
<el-option
v-for="it in conditions.experienceList.filter((it) => it.code !== 0)"
:key="it.code"
:value="it.code"
:label="it.name"
/>
</el-select>
</template>
</el-table-column>
<el-table-column :resizable="false" label="学历要求" prop="degree">
<template #default="{ row }">
<el-select
v-model="row.degree"
:disabled="row.___itemType === 'empty-condition-placeholder'"
clearable
size="small"
>
<el-option
v-for="it in conditions.degreeList.filter((it) => it.code !== 0)"
:key="it.code"
:value="it.code"
:label="it.name"
/>
</el-select>
</template>
</el-table-column>
<el-table-column :resizable="false" label="公司行业" :width="200" prop="industry">
<template #default="{ row }">
<el-select
v-model="row.industry"
:disabled="row.___itemType === 'empty-condition-placeholder'"
clearable
size="small"
>
<el-option-group
v-for="group in industryFilterExemption"
:key="group.code"
:label="group.name"
>
<el-option
v-for="item in group.subLevelModelList"
:key="item.code"
:label="item.name"
:value="item.code"
/>
</el-option-group>
</el-select>
</template>
</el-table-column>
<el-table-column :resizable="false" label="公司规模" prop="scale">
<template #default="{ row }">
<el-select
v-model="row.scaleList"
:disabled="row.___itemType === 'empty-condition-placeholder'"
clearable
size="small"
>
<el-option
v-for="it in conditions.scaleList.filter((it) => it.code !== 0)"
:key="it.code"
:value="it.code"
:label="it.name"
/>
</el-select>
</template>
</el-table-column>
</el-table>
</div>
<div
v-if="
Array.from(duplicatedMap.values()).some((it) => {
return it.length > 1
})
"
color-orange
font-size-12px
>
列表中被橙色高亮的条件存在重复项,相关重复项将被合并,运行时遍历顺序以第一次出现为准
</div>
</div>
</template>
<script lang="ts" setup>
import conditions from '@geekgeekrun/geek-auto-start-chat-with-boss/internal-config/job-filter-conditions-20241002.json'
import industryFilterExemption from '@geekgeekrun/geek-auto-start-chat-with-boss/internal-config/job-filter-industry-filter-exemption-20241002.json'
import { ArrowUp, ArrowDown, Delete, Plus } from '@element-plus/icons-vue'
import { computed, PropType } from 'vue'
import { getStaticCombineFilterKey } from '@geekgeekrun/geek-auto-start-chat-with-boss/combineCalculator.mjs'
const props = defineProps({
modelValue: {
type: Array as PropType<
Array<{
salary: number | null
experience: number | null
degree: number | null
industry: number | null
scale: number | null
}>
>,
default: () => []
},
isSkipEmptyConditionForCombineRecommendJobFilter: {
type: Boolean
}
})
function getNewConditionItem() {
return {
salary: null,
experience: null,
degree: null,
industry: null,
scale: null
}
}
function addCondition() {
props.modelValue?.push(getNewConditionItem())
// gtagRenderer('resume_work_exp_added')
}
function moveConditionUp(index) {
;[props.modelValue[index], props.modelValue[index - 1]] = [
props.modelValue[index - 1],
props.modelValue[index]
]
// gtagRenderer('resume_work_exp_moved_up')
}
function moveConditionDown(index) {
;[props.modelValue[index], props.modelValue[index + 1]] = [
props.modelValue[index + 1],
props.modelValue[index]
]
// gtagRenderer('resume_work_exp_moved_down')
}
function removeCondition(index) {
props.modelValue?.splice(index, 1)
// gtagRenderer('resume_work_exp_removed')
}
const duplicatedMap = computed(() => {
const map = new Map()
for (const condition of props.modelValue ?? []) {
const key = getStaticCombineFilterKey(condition)
if (!map.has(key)) {
map.set(key, [])
}
const arr = map.get(key)
arr.push(condition)
}
return map
})
</script>
<style lang="scss" scoped>
.job-combo-filter {
display: flex;
width: 100%;
gap: 10px;
.filter-item {
flex: 1;
}
}
</style>
@@ -35,7 +35,7 @@ const expectJobFilterTemplateList = [
},
{
type: '互联网/AI',
name: '前端开发工程师、JavaScript',
name: '前端开发工程师',
config: {
expectJobNameRegExpStr: '前端|H5|\\bFE\\b',
expectJobTypeRegExpStr: '前端开发|javascript',
@@ -43,6 +43,17 @@ const expectJobFilterTemplateList = [
jobDetailRegExpMatchLogic: JobDetailRegExpMatchLogic.SOME
}
},
{
type: '互联网/AI',
name: '前端开发工程师(不考虑外包、兼职)',
config: {
expectJobNameRegExpStr: '^(?=.*(前端|H5|\\bFE\\b))(?!.*(?:外包|驻场|外派|兼职|短期))',
expectJobTypeRegExpStr: '前端开发|javascript',
expectJobDescRegExpStr:
'^(?=.*(前端|vue|react|node|\\bjs\\b|javascript|H5))(?!.*(?:外包|驻场|外派|兼职|短期))',
jobDetailRegExpMatchLogic: JobDetailRegExpMatchLogic.EVERY
}
},
{
type: '互联网/AI',
name: '测试工程师、测试开发',
@@ -193,7 +204,7 @@ const expectJobFilterTemplateList = [
expectJobNameRegExpStr: '招聘|高招|Recruiter|HR|人力|人资|人事',
expectJobTypeRegExpStr: '招聘|猎头|人力',
expectJobDescRegExpStr:
'招聘|高招|Recruiter|简历|面试|人才引进|Mapping|人才画像|offer|猎头|内推|外推|猎聘|Boss|拉勾|前程无忧|智联|58同城|领英|LinkedIn|ATS|人才库|Moka|北森|iTenant|倍罗|大易|伯乐',
'招聘|高招|Recruiter|简历|面试|人才引进|Mapping|人才画像|offer|猎头|内推|外推|猎聘|Boss|拉勾|前程无忧|智联|58同城|领英|LinkedIn|ATS|人才库|Moka|北森|iTenant|倍罗|大易',
jobDetailRegExpMatchLogic: JobDetailRegExpMatchLogic.EVERY
}
},
@@ -49,60 +49,99 @@
/>
</div>
</el-form-item>
<el-form-item prop="filter" mt18px>
<div font-size-16px>
你希望Boss直聘为你展示什么样的职位
<el-tooltip
effect="light"
placement="bottom-start"
@show="gtagRenderer('tooltip_show_about_wrongly_mark_not_suit')"
>
<template #content>
<ul m0 line-height-1.5em w-540px pl2em>
<li>
这个配置决定了下面列表中会展示哪些职位查找职位时会在Boss直聘页面上自动组合下方设置的筛选条件对应UI<br />
<img h-270px src="../resources/intro-of-job-filter-auto-change.png" />
</li>
<li color-orange>
建议不要筛选过多条件否则最终组合数会成为一个很大的数字这将在当前职位中尝试太多筛选条件不能及时进入下一个职位且会增加命中风控的概率
</li>
</ul>
</template>
<el-button type="text" font-size-12px
><span><QuestionFilled w-1em h-1em mr2px /></span
>这个配置是如何工作的</el-button
<el-form-item prop="filter" mt18px mb0px w-full>
<div flex-1>
<div font-size-16px>
你希望Boss直聘为你筛选出什么样的职位
<el-tooltip
effect="light"
placement="bottom-start"
@show="gtagRenderer('tooltip_show_about_wrongly_mark_not_suit')"
>
</el-tooltip>
<template #content>
<ul m0 line-height-1.5em w-540px pl2em>
<li>
这个配置决定了下面列表中会展示哪些职位查找职位时会在Boss直聘页面上自动组合下方设置的筛选条件对应UI<br />
<img h-270px src="../resources/intro-of-job-filter-auto-change.png" />
</li>
<li color-orange>
建议不要筛选过多条件否则最终组合数会成为一个很大的数字这将在当前职位中尝试太多筛选条件不能及时进入下一个职位且会增加命中风控的概率
</li>
</ul>
</template>
<el-button type="text" font-size-12px
><span><QuestionFilled w-1em h-1em mr2px /></span
>这个配置是如何工作的</el-button
>
</el-tooltip>
</div>
<div>
<div>
<div font-size-12px>筛选条件遍历方式</div>
<el-select
v-model="formContent.combineRecommendJobFilterType"
w-320px
@change="
(v) => {
gtagRenderer('crjf_type_changed', { v })
}
"
>
<el-option
v-for="op in combineRecommendJobFilterTypeOptions"
:key="op.value"
:value="op.value"
:label="op.name"
>{{ op.name }}</el-option
>
</el-select>
</div>
<div
v-if="
formContent.combineRecommendJobFilterType ===
CombineRecommendJobFilterType.STATIC_COMBINE
"
mt8px
>
<StaticCombineBossRecommendFilter
v-model="formContent.staticCombineRecommendJobFilterConditions"
/>
</div>
<div v-else mt8px>
<AnyCombineBossRecommendFilter
v-model="formContent.anyCombineRecommendJobFilter"
/>
<div mb0>
<el-checkbox
v-if="anyCombineBossRecommendFilterHasCondition"
v-model="formContent.isSkipEmptyConditionForCombineRecommendJobFilter"
@change="
(v) => {
gtagRenderer('is_skip_empty_condition_4crjf_changed', { v })
}
"
>
<span font-size-12px>跳过初始空条件,直接使用设置的条件查找职位</span>
</el-checkbox>
<el-checkbox v-else :model-value="false" disabled>
<span font-size-12px>跳过初始空条件,直接使用设置的条件查找职位</span>
</el-checkbox>
</div>
</div>
</div>
<div font-size-12px>
当前组合条件数:{{
currentAnyCombineRecommendJobFilterCombinationCount.toLocaleString()
}}
<span
v-if="currentAnyCombineRecommendJobFilterCombinationCount >= 5"
class="color-orange"
>不建议选择太多组合条件 -
否则将在当前职位中尝试太多筛选条件,不能及时进入下一个职位,且会增加命中风控的概率</span
>
</div>
</div>
<AnyCombineBossRecommendFilter v-model="formContent.anyCombineRecommendJobFilter" />
</el-form-item>
<el-form-item prop="filter" mb0>
<el-checkbox
v-if="anyCombineBossRecommendFilterHasCondition"
v-model="formContent.isSkipEmptyConditionForCombineRecommendJobFilter"
@change="
(v) => {
gtagRenderer('is_skip_empty_condition_4crjf_changed', { v })
}
"
>
<span font-size-12px>跳过初始空条件直接使用设置的条件查找职位</span>
</el-checkbox>
<el-checkbox v-else :model-value="false" disabled>
<span font-size-12px>跳过初始空条件直接使用设置的条件查找职位</span>
</el-checkbox>
</el-form-item>
<div font-size-12px mt10px>
当前组合条件数{{
currentAnyCombineRecommendJobFilterCombinationCount.toLocaleString()
}}
<span
v-if="currentAnyCombineRecommendJobFilterCombinationCount >= 5"
class="color-orange"
>不建议选择太多组合条件 -
否则将在当前职位中尝试太多筛选条件不能及时进入下一个职位且会增加命中风控的概率</span
>
</div>
</el-card>
<!-- <el-form-item
label="钉钉机器人 AccessToken(用于记录开聊,请勿使用公司内部群)"
@@ -926,15 +965,18 @@ 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 StaticCombineBossRecommendFilter from '@renderer/features/StaticCombineBossRecommendFilter/index.vue'
import { activeDescList } from '@geekgeekrun/geek-auto-start-chat-with-boss/constant.mjs'
import {
calculateTotalCombinations,
checkAnyCombineBossRecommendFilterHasCondition
checkAnyCombineBossRecommendFilterHasCondition,
formatStaticCombineFilters
} from '@geekgeekrun/geek-auto-start-chat-with-boss/combineCalculator.mjs'
import { gtagRenderer as baseGtagRenderer } from '@renderer/utils/gtag'
import defaultTargetCompanyListConf from '@geekgeekrun/geek-auto-start-chat-with-boss/default-config-file/target-company-list.json'
import { ArrowDown } from '@element-plus/icons-vue'
import {
CombineRecommendJobFilterType,
MarkAsNotSuitOp,
StrategyScopeOptionWhenMarkJobNotMatch,
SalaryCalculateWay,
@@ -960,6 +1002,8 @@ const formContent = ref({
dingtalkRobotAccessToken: '',
expectCompanies: '',
anyCombineRecommendJobFilter: {},
combineRecommendJobFilterType: 1,
staticCombineRecommendJobFilterConditions: [],
expectJobNameRegExpStr: '',
expectJobTypeRegExpStr: '',
expectJobDescRegExpStr: '',
@@ -1001,6 +1045,16 @@ const anyCombineBossRecommendFilterHasCondition = computed(() => {
})
const currentAnyCombineRecommendJobFilterCombinationCount = computed(() => {
if (
formContent.value.combineRecommendJobFilterType === CombineRecommendJobFilterType.STATIC_COMBINE
) {
if (!formContent.value.staticCombineRecommendJobFilterConditions?.length) {
return 1
}
return formatStaticCombineFilters(
formContent.value.staticCombineRecommendJobFilterConditions
)?.filter(Boolean).length
}
return calculateTotalCombinations(
formContent.value.anyCombineRecommendJobFilter,
anyCombineBossRecommendFilterHasCondition.value
@@ -1047,6 +1101,12 @@ electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => {
deep: true
}
)
formContent.value.combineRecommendJobFilterType =
res.config['boss.json']?.combineRecommendJobFilterType ?? 1
formContent.value.staticCombineRecommendJobFilterConditions = res.config['boss.json']
?.staticCombineRecommendJobFilterConditions?.length
? res.config['boss.json'].staticCombineRecommendJobFilterConditions
: []
if (
res.config['boss.json']?.expectJobRegExpStr &&
typeof res.config['boss.json']?.expectJobNameRegExpStr === 'undefined' &&
@@ -1128,6 +1188,7 @@ const jobSourceFormItemSectionEl = ref()
const jobDetailRegExpSectionEl = ref()
const formRules = {
expectJobNameRegExpStr: {
trigger: 'blur',
validator(_, value, cb) {
if (!value) {
cb()
@@ -1136,16 +1197,17 @@ const formRules = {
}
try {
new RegExp(value, 'ig')
gtagRenderer('valid_reg_exp_for_expect_job_name')
gtagRenderer('valid_reg_exp_for_expect_job_name', { v: value })
cb()
} catch (err) {
cb(new Error(`正则无效:${err?.message}`))
jobDetailRegExpSectionEl.value?.scrollIntoViewIfNeeded()
gtagRenderer('invalid_reg_exp_for_expect_job_name')
gtagRenderer('invalid_reg_exp_for_expect_job_name', { v: value })
}
}
},
expectJobTypeRegExpStr: {
trigger: 'blur',
validator(_, value, cb) {
if (!value) {
cb()
@@ -1154,16 +1216,17 @@ const formRules = {
}
try {
new RegExp(value, 'ig')
gtagRenderer('valid_reg_exp_for_expect_job_type')
gtagRenderer('valid_reg_exp_for_expect_job_type', { v: value })
cb()
} catch (err) {
cb(new Error(`正则无效:${err?.message}`))
jobDetailRegExpSectionEl.value?.scrollIntoViewIfNeeded()
gtagRenderer('invalid_reg_exp_for_expect_job_type')
gtagRenderer('invalid_reg_exp_for_expect_job_type', { v: value })
}
}
},
expectJobDescRegExpStr: {
trigger: 'blur',
validator(_, value, cb) {
if (!value) {
cb()
@@ -1172,12 +1235,12 @@ const formRules = {
}
try {
new RegExp(value, 'ig')
gtagRenderer('valid_reg_exp_for_expect_job_desc')
gtagRenderer('valid_reg_exp_for_expect_job_desc', { v: value })
cb()
} catch (err) {
cb(new Error(`正则无效:${err?.message}`))
jobDetailRegExpSectionEl.value?.scrollIntoViewIfNeeded()
gtagRenderer('invalid_reg_exp_for_expect_job_desc')
gtagRenderer('invalid_reg_exp_for_expect_job_desc', { v: value })
}
}
},
@@ -1217,8 +1280,14 @@ const formRules = {
const formRef = ref<InstanceType<typeof ElForm>>()
const handleSubmit = async () => {
gtagRenderer('save_config_and_launch_clicked', {
has_dingtalk_robot_token: !!formContent.value?.dingtalkRobotAccessToken
has_dingtalk_robot_token: !!formContent.value?.dingtalkRobotAccessToken,
expect_job_name_reg_exp_str: formContent.value?.expectJobNameRegExpStr,
expect_job_type_reg_exp_str: formContent.value?.expectJobTypeRegExpStr,
expect_job_desc_reg_exp_str: formContent.value?.expectJobDescRegExpStr,
crjf_type: formContent.value?.combineRecommendJobFilterType,
crjf_cc: currentAnyCombineRecommendJobFilterCombinationCount.value?.toLocaleString?.()
})
// remove the obsolete filter - expectJobRegExpStr
formContent.value.expectJobRegExpStr = undefined
try {
await formRef.value!.validate()
@@ -1574,6 +1643,17 @@ function formatJobSourceFormValueToConfig(formValue = []) {
return it
})
}
const combineRecommendJobFilterTypeOptions = [
{
name: '使用自由组合条件进行遍历',
value: 1
},
{
name: '使用固定组合条件进行遍历',
value: 2
}
]
</script>
<style scoped lang="scss">
@@ -1,6 +1,6 @@
<template>
<div class="flex h100vh">
<div class="flex flex-col w200px pt30px pl30px aside-nav of-hidden">
<div class="flex flex-col min-w200px w200px pt30px pl30px aside-nav of-hidden">
<div class="nav-list flex-1 of-auto">
<RouterLink to="./GeekAutoStartChatWithBoss">
Boss炸弹