mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-08 00:47:15 +08:00
add core logic for job source
This commit is contained in:
@@ -23,5 +23,11 @@
|
|||||||
"recentMessageQuantityForLlm": 8,
|
"recentMessageQuantityForLlm": 8,
|
||||||
"rechatLlmFallback": 1,
|
"rechatLlmFallback": 1,
|
||||||
"onlyRemindBossWithExpectJobType": true
|
"onlyRemindBossWithExpectJobType": true
|
||||||
}
|
},
|
||||||
|
"jobSourceList": [
|
||||||
|
{
|
||||||
|
"type": "expect",
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
@@ -152,6 +152,54 @@ if (
|
|||||||
jobDetailRegExpMatchLogic = JobDetailRegExpMatchLogic.EVERY
|
jobDetailRegExpMatchLogic = JobDetailRegExpMatchLogic.EVERY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
jobSourceList
|
||||||
|
} = readConfigFile('boss.json')
|
||||||
|
|
||||||
|
if (!jobSourceList?.length) {
|
||||||
|
jobSourceList = [
|
||||||
|
{
|
||||||
|
type: "expect",
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const normalizedJobSource = []
|
||||||
|
const addedSourceSet = new Set()
|
||||||
|
for (const source of jobSourceList) {
|
||||||
|
if (addedSourceSet.has(source.type)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!source?.enabled) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (source.type === 'search') {
|
||||||
|
for (const searchOption of (source.children ?? [])) {
|
||||||
|
if (!searchOption.enabled || !searchOption.keyword?.trim()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const key = [
|
||||||
|
source.type,
|
||||||
|
searchOption.keyword.trim()
|
||||||
|
].join('__')
|
||||||
|
if (addedSourceSet.has(key)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
normalizedJobSource.push({
|
||||||
|
type: 'search',
|
||||||
|
keyword: searchOption.keyword.trim()
|
||||||
|
})
|
||||||
|
addedSourceSet.add(key)
|
||||||
|
}
|
||||||
|
addedSourceSet.add(source.type)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
normalizedJobSource.push({
|
||||||
|
type: source.type,
|
||||||
|
})
|
||||||
|
addedSourceSet.add(source.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
const localStoragePageUrl = `https://www.zhipin.com/desktop/`
|
const localStoragePageUrl = `https://www.zhipin.com/desktop/`
|
||||||
const recommendJobPageUrl = `https://www.zhipin.com/web/geek/jobs`
|
const recommendJobPageUrl = `https://www.zhipin.com/web/geek/jobs`
|
||||||
|
|
||||||
@@ -443,23 +491,6 @@ async function setFilterCondition (selectedFilters) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const jobSource = [
|
|
||||||
{
|
|
||||||
name: 'recommendJob'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'userSetExpectJob'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'searchJob',
|
|
||||||
keyword: 'HRBP'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'searchJob',
|
|
||||||
keyword: '招聘'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
async function toRecommendPage (hooks) {
|
async function toRecommendPage (hooks) {
|
||||||
let userInfoPromise = page.waitForResponse((response) => {
|
let userInfoPromise = page.waitForResponse((response) => {
|
||||||
if (response.url().startsWith('https://www.zhipin.com/wapi/zpuser/wap/getUserInfo.json')) {
|
if (response.url().startsWith('https://www.zhipin.com/wapi/zpuser/wap/getUserInfo.json')) {
|
||||||
@@ -512,11 +543,11 @@ async function toRecommendPage (hooks) {
|
|||||||
const SEARCH_BOX_SELECTOR = `.c-search-input .search-input-box`
|
const SEARCH_BOX_SELECTOR = `.c-search-input .search-input-box`
|
||||||
|
|
||||||
const computedSourceList = []
|
const computedSourceList = []
|
||||||
for (const source of jobSource) {
|
for (const source of normalizedJobSource) {
|
||||||
switch (source.name) {
|
switch (source.type) {
|
||||||
case 'recommendJob': {
|
case 'recommend': {
|
||||||
computedSourceList.push({
|
computedSourceList.push({
|
||||||
sourceName: source.name,
|
type: source.type,
|
||||||
selector: RECOMMEND_JOB_ENTRY_SELECTOR,
|
selector: RECOMMEND_JOB_ENTRY_SELECTOR,
|
||||||
async getIsCurrentActiveSource () {
|
async getIsCurrentActiveSource () {
|
||||||
return await page.evaluate(
|
return await page.evaluate(
|
||||||
@@ -536,12 +567,12 @@ async function toRecommendPage (hooks) {
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case 'userSetExpectJob': {
|
case 'expect': {
|
||||||
await page.waitForSelector(USER_SET_EXPECT_JOB_ENTRIES_SELECTOR)
|
await page.waitForSelector(USER_SET_EXPECT_JOB_ENTRIES_SELECTOR)
|
||||||
const allExpectJobEntryHandles = await page.$$(USER_SET_EXPECT_JOB_ENTRIES_SELECTOR)
|
const allExpectJobEntryHandles = await page.$$(USER_SET_EXPECT_JOB_ENTRIES_SELECTOR)
|
||||||
allExpectJobEntryHandles.forEach((it, index) => {
|
allExpectJobEntryHandles.forEach((it, index) => {
|
||||||
computedSourceList.push({
|
computedSourceList.push({
|
||||||
sourceName: source.name,
|
type: source.type,
|
||||||
selector: `${USER_SET_EXPECT_JOB_ENTRIES_SELECTOR}:nth-child(${index + 1})`,
|
selector: `${USER_SET_EXPECT_JOB_ENTRIES_SELECTOR}:nth-child(${index + 1})`,
|
||||||
async getIsCurrentActiveSource () {
|
async getIsCurrentActiveSource () {
|
||||||
return await page.evaluate(
|
return await page.evaluate(
|
||||||
@@ -566,9 +597,9 @@ async function toRecommendPage (hooks) {
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'searchJob': {
|
case 'search': {
|
||||||
computedSourceList.push({
|
computedSourceList.push({
|
||||||
sourceName: source.name,
|
type: source.type,
|
||||||
async getIsCurrentActiveSource () {
|
async getIsCurrentActiveSource () {
|
||||||
const elHandle = await page.$(`.page-jobs-main`)
|
const elHandle = await page.$(`.page-jobs-main`)
|
||||||
const currentKeyWord = await elHandle?.evaluate((el) => {
|
const currentKeyWord = await elHandle?.evaluate((el) => {
|
||||||
|
|||||||
@@ -44,7 +44,8 @@
|
|||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"puppeteer": "20.1.0",
|
"puppeteer": "20.1.0",
|
||||||
"puppeteer-extra-plugin-stealth": "2.11.2",
|
"puppeteer-extra-plugin-stealth": "2.11.2",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0",
|
||||||
|
"vuedraggable": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-toolkit/eslint-config": "^1.0.2",
|
"@electron-toolkit/eslint-config": "^1.0.2",
|
||||||
|
|||||||
@@ -156,6 +156,9 @@ export default function initIpc() {
|
|||||||
bossConfig.isSkipEmptyConditionForCombineRecommendJobFilter =
|
bossConfig.isSkipEmptyConditionForCombineRecommendJobFilter =
|
||||||
payload.isSkipEmptyConditionForCombineRecommendJobFilter
|
payload.isSkipEmptyConditionForCombineRecommendJobFilter
|
||||||
}
|
}
|
||||||
|
if (hasOwn(payload, 'jobSourceList')) {
|
||||||
|
bossConfig.jobSourceList = payload.jobSourceList
|
||||||
|
}
|
||||||
|
|
||||||
promiseArr.push(writeConfigFile('boss.json', bossConfig))
|
promiseArr.push(writeConfigFile('boss.json', bossConfig))
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,245 @@
|
|||||||
|
<template>
|
||||||
|
<draggable
|
||||||
|
:model-value="modelValue"
|
||||||
|
class="list-group"
|
||||||
|
:component-data="{
|
||||||
|
tag: 'ul',
|
||||||
|
type: 'transition-group',
|
||||||
|
name: !drag ? 'flip-list' : null
|
||||||
|
}"
|
||||||
|
:group="{ name: 'parent', put: ['parent'] }"
|
||||||
|
v-bind="dragOptions"
|
||||||
|
handle=".drag-handle-wrap"
|
||||||
|
@update:model-value="emit('update:model-value', $event)"
|
||||||
|
@start="drag = true"
|
||||||
|
@end="drag = false"
|
||||||
|
>
|
||||||
|
<template #item="{ element }">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<div flex flex-items-center>
|
||||||
|
<span class="drag-handle-wrap">
|
||||||
|
<span class="drag-handle" />
|
||||||
|
</span>
|
||||||
|
<span class="inner-content">
|
||||||
|
<div flex w-full flex-1>
|
||||||
|
<template
|
||||||
|
v-if="
|
||||||
|
element.item.type === 'search' &&
|
||||||
|
(!element.item?.children?.length ||
|
||||||
|
!element.item?.children?.some((it) => it.enabled) ||
|
||||||
|
!element.item?.children?.some((it) => !!it.keyword?.trim()))
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
model-value="false"
|
||||||
|
mr10px
|
||||||
|
disabled
|
||||||
|
active-text="启用"
|
||||||
|
inactive-text="禁用"
|
||||||
|
inline-prompt
|
||||||
|
/>
|
||||||
|
{{ element.label }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-switch
|
||||||
|
v-model="element.item.enabled"
|
||||||
|
mr10px
|
||||||
|
active-text="启用"
|
||||||
|
inactive-text="禁用"
|
||||||
|
inline-prompt
|
||||||
|
/>
|
||||||
|
{{ element.label }}
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div v-if="element.item.type === 'search'">
|
||||||
|
<div flex flex-items-center>
|
||||||
|
<span color-orange align-self-end mr10px>
|
||||||
|
<template v-if="!element.item?.children?.length">
|
||||||
|
添加一个关键词后方可启用->
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
v-else-if="
|
||||||
|
element.item?.children?.every((it) => !(it.enabled && !!it.keyword?.trim()))
|
||||||
|
"
|
||||||
|
>
|
||||||
|
至少启用下方任意一个不为空的关键词后方可启用
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
v-else-if="element.item?.children?.some((it) => it.enabled && !it.keyword?.trim())"
|
||||||
|
>
|
||||||
|
留空的关键词会被跳过
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
<el-button p-0 h-fit type="text" @click="addSearchKeyword(element.item)"
|
||||||
|
>添加关键词</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="element.item.type === 'search' && element.item?.children?.length">
|
||||||
|
<draggable
|
||||||
|
v-model="element.item.children"
|
||||||
|
class="list-group"
|
||||||
|
:component-data="{
|
||||||
|
tag: 'ul',
|
||||||
|
type: 'transition-group',
|
||||||
|
name: !drag ? 'flip-list' : null
|
||||||
|
}"
|
||||||
|
:group="{ name: 'child', put: ['child'] }"
|
||||||
|
v-bind="dragOptions"
|
||||||
|
handle=".drag-handle-wrap"
|
||||||
|
@start="drag = true"
|
||||||
|
@end="drag = false"
|
||||||
|
>
|
||||||
|
<template #item="{ element: searchItem, index }">
|
||||||
|
<li class="list-group-item">
|
||||||
|
<div flex flex-items-center>
|
||||||
|
<span class="drag-handle-wrap">
|
||||||
|
<span class="drag-handle" />
|
||||||
|
</span>
|
||||||
|
<span class="inner-content">
|
||||||
|
<div flex w-full>
|
||||||
|
<el-switch
|
||||||
|
v-if="element.item.enabled"
|
||||||
|
v-model="searchItem.enabled"
|
||||||
|
mr10px
|
||||||
|
active-text="启用"
|
||||||
|
inactive-text="禁用"
|
||||||
|
inline-prompt
|
||||||
|
/>
|
||||||
|
<el-switch
|
||||||
|
v-else
|
||||||
|
disabled
|
||||||
|
:model-value="false"
|
||||||
|
mr10px
|
||||||
|
active-text="启用"
|
||||||
|
inactive-text="禁用"
|
||||||
|
inline-prompt
|
||||||
|
/>
|
||||||
|
<el-input
|
||||||
|
v-model="searchItem.keyword"
|
||||||
|
maxlength="100"
|
||||||
|
@blur="() => (searchItem.keyword = searchItem.keyword?.trim() ?? '')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
p-0
|
||||||
|
ml-10px
|
||||||
|
h-fit
|
||||||
|
type="danger"
|
||||||
|
link
|
||||||
|
@click="removeSearchKeywordByIndex(element.item, index)"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</draggable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:model-value'])
|
||||||
|
|
||||||
|
const drag = ref(false)
|
||||||
|
|
||||||
|
const dragOptions = computed(() => {
|
||||||
|
return {
|
||||||
|
animation: 200,
|
||||||
|
disabled: false,
|
||||||
|
ghostClass: 'ghost'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function addSearchKeyword(item) {
|
||||||
|
if (!item.children) {
|
||||||
|
item.children = []
|
||||||
|
}
|
||||||
|
item.children.push({
|
||||||
|
type: 'search-kw',
|
||||||
|
enabled: true,
|
||||||
|
keyword: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeSearchKeywordByIndex(item, index) {
|
||||||
|
item.children?.splice(index, 1)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.ghost {
|
||||||
|
opacity: 0.5;
|
||||||
|
filter: blur(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group {
|
||||||
|
line-height: 32px;
|
||||||
|
min-height: 20px;
|
||||||
|
.list-group {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
.list-group-item {
|
||||||
|
background-color: #fff;
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 6px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
padding-right: 10px;
|
||||||
|
border: 1px solid var(--el-card-border-color);
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
box-shadow: var(--el-box-shadow-light);
|
||||||
|
border-radius: 4px;
|
||||||
|
.inner-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
::v-deep(.el-checkbox) {
|
||||||
|
.el-checkbox__label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.drag-handle-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 25px;
|
||||||
|
height: 1em;
|
||||||
|
cursor: grab;
|
||||||
|
margin-right: 4px;
|
||||||
|
.drag-handle {
|
||||||
|
width: 20px;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 35%,
|
||||||
|
var(--el-card-border-color) 35%,
|
||||||
|
var(--el-card-border-color) 45%,
|
||||||
|
transparent 45%,
|
||||||
|
transparent 55%,
|
||||||
|
var(--el-card-border-color) 55%,
|
||||||
|
var(--el-card-border-color) 65%,
|
||||||
|
transparent 65%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -17,6 +17,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
<el-card class="config-section">
|
||||||
|
<el-form-item prop="filter" mb0>
|
||||||
|
<div w-full>
|
||||||
|
<div font-size-16px>职位来源及查找顺序</div>
|
||||||
|
<JobSourceDragOrderer v-model="formContent.__jobSourceList" />
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-card>
|
||||||
<el-card class="config-section">
|
<el-card class="config-section">
|
||||||
<el-form-item prop="filter">
|
<el-form-item prop="filter">
|
||||||
<div font-size-16px>
|
<div font-size-16px>
|
||||||
@@ -885,6 +893,7 @@ import { debounce } from 'lodash-es'
|
|||||||
import mittBus from '../../../utils/mitt'
|
import mittBus from '../../../utils/mitt'
|
||||||
import CityChooser from './components/CityChooser.vue'
|
import CityChooser from './components/CityChooser.vue'
|
||||||
import conditions from '@geekgeekrun/geek-auto-start-chat-with-boss/internal-config/job-filter-conditions-20241002.json'
|
import conditions from '@geekgeekrun/geek-auto-start-chat-with-boss/internal-config/job-filter-conditions-20241002.json'
|
||||||
|
import JobSourceDragOrderer from '../../../features/JobSourceDragOrderer/index.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -917,7 +926,13 @@ const formContent = ref({
|
|||||||
StrategyScopeOptionWhenMarkJobNotMatch.ONLY_COMPANY_MATCHED_JOB,
|
StrategyScopeOptionWhenMarkJobNotMatch.ONLY_COMPANY_MATCHED_JOB,
|
||||||
jobDetailRegExpMatchLogic: JobDetailRegExpMatchLogic.EVERY,
|
jobDetailRegExpMatchLogic: JobDetailRegExpMatchLogic.EVERY,
|
||||||
|
|
||||||
isSkipEmptyConditionForCombineRecommendJobFilter: false
|
isSkipEmptyConditionForCombineRecommendJobFilter: false,
|
||||||
|
__jobSourceList: formatJobSourceConfigToFormValue([
|
||||||
|
{
|
||||||
|
type: 'expect',
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
const anyCombineBossRecommendFilterHasCondition = computed(() => {
|
const anyCombineBossRecommendFilterHasCondition = computed(() => {
|
||||||
@@ -1032,6 +1047,9 @@ electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => {
|
|||||||
res.config['boss.json'].jobDetailRegExpMatchLogic ?? JobDetailRegExpMatchLogic.EVERY
|
res.config['boss.json'].jobDetailRegExpMatchLogic ?? JobDetailRegExpMatchLogic.EVERY
|
||||||
formContent.value.isSkipEmptyConditionForCombineRecommendJobFilter =
|
formContent.value.isSkipEmptyConditionForCombineRecommendJobFilter =
|
||||||
res.config['boss.json'].isSkipEmptyConditionForCombineRecommendJobFilter ?? false
|
res.config['boss.json'].isSkipEmptyConditionForCombineRecommendJobFilter ?? false
|
||||||
|
formContent.value.__jobSourceList = formatJobSourceConfigToFormValue(
|
||||||
|
res.config['boss.json'].jobSourceList || []
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const formRules = {
|
const formRules = {
|
||||||
@@ -1104,7 +1122,12 @@ const handleSubmit = async () => {
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await electron.ipcRenderer.invoke('save-config-file-from-ui', JSON.stringify(formContent.value))
|
const clonedFormContent = JSON.parse(JSON.stringify(formContent.value))
|
||||||
|
clonedFormContent.jobSourceList = formatJobSourceFormValueToConfig(
|
||||||
|
clonedFormContent.__jobSourceList
|
||||||
|
)
|
||||||
|
delete clonedFormContent.__jobSourceList
|
||||||
|
await electron.ipcRenderer.invoke('save-config-file-from-ui', JSON.stringify(clonedFormContent))
|
||||||
mittBus.emit('auto-start-chat-with-boss-config-saved')
|
mittBus.emit('auto-start-chat-with-boss-config-saved')
|
||||||
router.replace({
|
router.replace({
|
||||||
path: '/geekAutoStartChatWithBoss/prepareRun',
|
path: '/geekAutoStartChatWithBoss/prepareRun',
|
||||||
@@ -1129,7 +1152,12 @@ const handleSave = async () => {
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await electron.ipcRenderer.invoke('save-config-file-from-ui', JSON.stringify(formContent.value))
|
const clonedFormContent = JSON.parse(JSON.stringify(formContent.value))
|
||||||
|
clonedFormContent.jobSourceList = formatJobSourceFormValueToConfig(
|
||||||
|
clonedFormContent.__jobSourceList
|
||||||
|
)
|
||||||
|
delete clonedFormContent.__jobSourceList
|
||||||
|
await electron.ipcRenderer.invoke('save-config-file-from-ui', JSON.stringify(clonedFormContent))
|
||||||
mittBus.emit('auto-start-chat-with-boss-config-saved')
|
mittBus.emit('auto-start-chat-with-boss-config-saved')
|
||||||
ElMessage.success('配置保存成功')
|
ElMessage.success('配置保存成功')
|
||||||
gtagRenderer('config_saved')
|
gtagRenderer('config_saved')
|
||||||
@@ -1438,6 +1466,55 @@ function getJobDetailRegExpMatchLogicConfig() {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatJobSourceConfigToFormValue(config = []) {
|
||||||
|
const typeToNameKey = {
|
||||||
|
recommend: '推荐列表中的职位',
|
||||||
|
expect: '根据设置的求职期望推荐的职位',
|
||||||
|
search: '通过搜索找到的职位'
|
||||||
|
}
|
||||||
|
const isInitEmpty = !config?.length
|
||||||
|
config = config.filter((it) => Object.hasOwn(typeToNameKey, it.type))
|
||||||
|
|
||||||
|
const addedSet = new Set()
|
||||||
|
const tempArr = []
|
||||||
|
config.forEach((it) => {
|
||||||
|
if (!Object.hasOwn(typeToNameKey, it.type)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tempArr.push(it)
|
||||||
|
addedSet.add(it.type)
|
||||||
|
})
|
||||||
|
config = tempArr
|
||||||
|
Object.keys(typeToNameKey).forEach((k) => {
|
||||||
|
if (addedSet.has(k)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// handle init value
|
||||||
|
tempArr.push({
|
||||||
|
type: k,
|
||||||
|
enabled: isInitEmpty && k === 'expect'
|
||||||
|
})
|
||||||
|
addedSet.add(k)
|
||||||
|
})
|
||||||
|
|
||||||
|
return config.map((outerItem) => {
|
||||||
|
return {
|
||||||
|
item: outerItem,
|
||||||
|
label: typeToNameKey[outerItem.type],
|
||||||
|
children:
|
||||||
|
outerItem.children && outerItem.type === 'search'
|
||||||
|
? (outerItem.children || []).map((innerItem) => ({
|
||||||
|
item: innerItem
|
||||||
|
}))
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatJobSourceFormValueToConfig(formValue = []) {
|
||||||
|
return formValue.map((it) => it.item)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
Generated
+16
@@ -150,6 +150,9 @@ importers:
|
|||||||
uuid:
|
uuid:
|
||||||
specifier: ^11.1.0
|
specifier: ^11.1.0
|
||||||
version: 11.1.0
|
version: 11.1.0
|
||||||
|
vuedraggable:
|
||||||
|
specifier: ^4.1.0
|
||||||
|
version: 4.1.0(vue@3.4.15)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@electron-toolkit/eslint-config':
|
'@electron-toolkit/eslint-config':
|
||||||
specifier: ^1.0.2
|
specifier: ^1.0.2
|
||||||
@@ -5821,6 +5824,10 @@ packages:
|
|||||||
ip: 2.0.0
|
ip: 2.0.0
|
||||||
smart-buffer: 4.2.0
|
smart-buffer: 4.2.0
|
||||||
|
|
||||||
|
/sortablejs@1.14.0:
|
||||||
|
resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/source-map-js@1.0.2:
|
/source-map-js@1.0.2:
|
||||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -6625,6 +6632,15 @@ packages:
|
|||||||
'@vue/shared': 3.4.15
|
'@vue/shared': 3.4.15
|
||||||
typescript: 5.3.3
|
typescript: 5.3.3
|
||||||
|
|
||||||
|
/vuedraggable@4.1.0(vue@3.4.15):
|
||||||
|
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.1
|
||||||
|
dependencies:
|
||||||
|
sortablejs: 1.14.0
|
||||||
|
vue: 3.4.15(typescript@5.3.3)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/web-streams-polyfill@3.3.3:
|
/web-streams-polyfill@3.3.3:
|
||||||
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|||||||
Reference in New Issue
Block a user