move stop button into dialog

This commit is contained in:
geekgeekrun
2026-01-17 22:53:40 +08:00
parent 754f942c86
commit 351f30b824
5 changed files with 1342 additions and 1234 deletions
@@ -0,0 +1,61 @@
<template>
<el-dialog
modal-class="runing-overlay__modal"
:model-value="runingTaskInfo"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
>
<div flex justify-between items-center w-full>
<div>任务运行中!</div>
<div>
<slot name="op-buttons" />
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { useTaskManagerStore } from '@renderer/store'
import { computed } from 'vue'
const props = defineProps({
workerId: {
type: String
}
})
const taskManagerStore = useTaskManagerStore()
const runingTaskInfo = computed(() => {
return taskManagerStore.runningTasks?.find(it => {
return it.workerId === props.workerId
})
})
</script>
<style lang="scss">
.el-overlay.runing-overlay__modal {
position: absolute;
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
.el-overlay-dialog {
position: absolute;
pointer-events: all;
}
.el-dialog {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.el-dialog__header {
display: none;
}
.el-dialog__body {
overflow: hidden;
}
}
}
</style>
@@ -14,5 +14,5 @@ import { computed } from 'vue'
import TaskManagerItem from './Item.vue' import TaskManagerItem from './Item.vue'
const taskManagerStore = useTaskManagerStore() const taskManagerStore = useTaskManagerStore()
const runningTasks = computed(() => taskManagerStore.runningTasks?.workers || []) const runningTasks = computed(() => taskManagerStore.runningTasks || [])
</script> </script>
File diff suppressed because it is too large Load Diff
@@ -1,228 +1,239 @@
<template> <template>
<div class="form-wrap"> <div class="read-no-reply-reminder__wrap">
<el-form <div class="form-wrap">
ref="formRef" <el-form
:rules="formRules" ref="formRef"
:model="formContent.autoReminder" :rules="formRules"
label-position="top" :model="formContent.autoReminder"
> label-position="top"
<el-form-item label="BOSS直聘 Cookie"> >
<el-button size="small" type="primary" @click="handleClickLaunchLogin" <el-form-item label="BOSS直聘 Cookie">
>编辑Cookie</el-button <el-button size="small" type="primary" @click="handleClickLaunchLogin"
> >编辑Cookie</el-button
</el-form-item> >
<el-form-item> </el-form-item>
<div> <el-form-item>
<el-checkbox v-if="!expectJobTypeRegExpStr?.trim()" :model-value="false" disabled> <div>
发送提醒消息前先按照Boss炸弹-职位类型正则校验正在与Boss沟通的岗位是否满足期望校验通过后再提醒 <el-checkbox v-if="!expectJobTypeRegExpStr?.trim()" :model-value="false" disabled>
</el-checkbox>
<template v-else>
<el-checkbox v-model="formContent.autoReminder.onlyRemindBossWithExpectJobType">
发送提醒消息前先按照Boss炸弹-职位类型正则校验正在与Boss沟通的岗位是否满足期望校验通过后再提醒 发送提醒消息前先按照Boss炸弹-职位类型正则校验正在与Boss沟通的岗位是否满足期望校验通过后再提醒
</el-checkbox> </el-checkbox>
<div ml1.5em color-gray> <template v-else>
<div>当前职位类型正则{{ expectJobTypeRegExpStr?.trim() }}</div> <el-checkbox v-model="formContent.autoReminder.onlyRemindBossWithExpectJobType">
<template 发送提醒消息前先按照Boss炸弹-职位类型正则校验正在与Boss沟通的岗位是否满足期望校验通过后再提醒
v-if=" </el-checkbox>
formContent.autoReminder.rechatContentSource === <div ml1.5em color-gray>
RECHAT_CONTENT_SOURCE.GEMINI_WITH_CHAT_CONTEXT <div>当前职位类型正则{{ expectJobTypeRegExpStr?.trim() }}</div>
" <template
> v-if="
<div>当前简历中填写的期望职位:{{ resumeContent?.expectJob ?? '-' }}</div> formContent.autoReminder.rechatContentSource ===
<div color-orange>请确保上方二者信息匹配</div> RECHAT_CONTENT_SOURCE.GEMINI_WITH_CHAT_CONTEXT
</template>
</div>
</template>
</div>
</el-form-item>
<el-form-item class="mb0" label="跟进话术 - 当发现已读不回的Boss时,将要向Boss发出:">
<el-radio-group v-model="formContent.autoReminder.rechatContentSource">
<div>
<el-tooltip
effect="light"
placement="right"
:enterable="false"
@show="gtagRenderer('tooltip_show_about_lfr_emotion_figure')"
>
<template #content>
<img block h-100px src="./resources/look-forward-reply-emotion.gif" />
</template>
<el-radio :label="RECHAT_CONTENT_SOURCE.LOOK_FORWARD_EMOTION">
“[盼回复]” 表情
</el-radio>
</el-tooltip>
<br />
<el-radio :label="RECHAT_CONTENT_SOURCE.GEMINI_WITH_CHAT_CONTEXT">
由大语言模型(根据简历及当前聊天上下文)生成的内容
</el-radio>
</div>
</el-radio-group>
</el-form-item>
<div class="ml-30px">
<template
v-if="
formContent.autoReminder.rechatContentSource ===
RECHAT_CONTENT_SOURCE.GEMINI_WITH_CHAT_CONTEXT
"
>
<el-form-item class="mb4px">
<div>
<el-button size="small" type="primary" @click="handleClickConfigLlm">
配置大语言模型
</el-button>
<div class="font-size-12px color-#666">
支持
<span
class="pl6px pr6px pt4px pb2px color-white border-rd-full font-size-0.8em"
style="background-color: #3c4efd"
>DeepSeek-V3</span
>
<span
class="ml4px pl6px pr6px pt4px pb2px color-white border-rd-full font-size-0.8em"
style="background-color: #000000"
>GPT-4o mini</span
>
<span
class="ml4px pl6px pr6px pt4px pb2px color-white border-rd-full font-size-0.8em"
style="background-color: #462ac4"
>Qwen2.5</span
>
模型;支持多个“服务商-模型”组合按权重搭配使用
</div>
</div>
</el-form-item>
<el-form-item class="mb4px">
<div>
<el-button size="small" type="primary" @click="handleClickEditResume">
编辑简历
</el-button>
<div class="font-size-12px color-#666">
简历内容将提交给大语言模型,以用于生成已读不回提醒消息;提交内容及生成消息中不会包含期望薪资
</div>
</div>
</el-form-item>
<el-form-item class="mb4px">
<div>
<div>
<el-button size="small" type="primary" @click="handleClickEditPrompt">
使用外部编辑器编辑提示词模板 (Markdown)
</el-button>
<el-button
size="small"
type="primary"
@click="
() => {
gtagRenderer('reset_template_clicked_in_main_form')
restoreDefaultTemplate()
}
" "
> >
还原默认提示词模板 <div>当前简历中填写的期望职位:{{ resumeContent?.expectJob ?? '-' }}</div>
</el-button> <div color-orange>请确保上方二者信息匹配</div>
</template>
</div> </div>
<div class="font-size-12px color-#666"> </template>
对生成效果不够满意?可在此查看、编辑提示词模板。请在模板中需要插入简历的位置插入 </div>
__REPLACE_REAL_RESUME_HERE__ </el-form-item>
</div> <el-form-item class="mb0" label="跟进话术 - 当发现已读不回的Boss时,将要向Boss发出:">
</div> <el-radio-group v-model="formContent.autoReminder.rechatContentSource">
</el-form-item>
<el-form-item prop="recentMessageQuantityForLlm">
<div> <div>
携带最近 <el-tooltip
<el-input-number effect="light"
v-model="formContent.autoReminder.recentMessageQuantityForLlm" placement="right"
class="w-120px" :enterable="false"
:min="8" @show="gtagRenderer('tooltip_show_about_lfr_emotion_figure')"
:max="20"
:precision="0"
:step="1"
></el-input-number>
次聊天内容作为上下文生成新消息
</div>
</el-form-item>
<el-form-item>
<el-button size="small" type="primary" @click="handleTestEffectClicked"
>使用当前配置模拟已读不回复聊过程</el-button
>
</el-form-item>
<el-form-item prop="recentMessageQuantityForLlm">
<div class="flex flex-items-center">
<span class="whitespace-nowrap">当所有模型均不可使用时&nbsp;</span>
<el-select
v-model="formContent.autoReminder.rechatLlmFallback"
class="w200px"
label="name"
> >
<el-option <template #content>
v-for="option in rechatLlmFallbackOptions" <img block h-100px src="./resources/look-forward-reply-emotion.gif" />
:key="option.value" </template>
:value="option.value" <el-radio :label="RECHAT_CONTENT_SOURCE.LOOK_FORWARD_EMOTION">
:label="option.name" “[盼回复]” 表情
/> </el-radio>
</el-select> </el-tooltip>
<br />
<el-radio :label="RECHAT_CONTENT_SOURCE.GEMINI_WITH_CHAT_CONTEXT">
由大语言模型(根据简历及当前聊天上下文)生成的内容
</el-radio>
</div> </div>
</el-form-item> </el-radio-group>
</template> </el-form-item>
</div> <div class="ml-30px">
<el-form-item label="跟进间隔(分钟)" prop="throttleIntervalMinutes"> <template
<el-input-number v-if="
v-model="formContent.autoReminder.throttleIntervalMinutes" formContent.autoReminder.rechatContentSource ===
class="w-150px" RECHAT_CONTENT_SOURCE.GEMINI_WITH_CHAT_CONTEXT
:min="3" "
:precision="1" >
:step="0.5" <el-form-item class="mb4px">
@blur="handleThrottleIntervalMinutesBlur" <div>
/>&nbsp;分钟内不多次跟进同一Boss <el-button size="small" type="primary" @click="handleClickConfigLlm">
</el-form-item> 配置大语言模型
<el-form-item label="跟进时限(天)" prop="rechatLimitDay" mb-0> </el-button>
<div> <div class="font-size-12px color-#666">
<div><el-checkbox v-model="enableRechatLimit" />&nbsp;启用</div> 支持
<span
class="pl6px pr6px pt4px pb2px color-white border-rd-full font-size-0.8em"
style="background-color: #3c4efd"
>DeepSeek-V3</span
>
<span
class="ml4px pl6px pr6px pt4px pb2px color-white border-rd-full font-size-0.8em"
style="background-color: #000000"
>GPT-4o mini</span
>
<span
class="ml4px pl6px pr6px pt4px pb2px color-white border-rd-full font-size-0.8em"
style="background-color: #462ac4"
>Qwen2.5</span
>
模型;支持多个“服务商-模型”组合按权重搭配使用
</div>
</div>
</el-form-item>
<el-form-item class="mb4px">
<div>
<el-button size="small" type="primary" @click="handleClickEditResume">
编辑简历
</el-button>
<div class="font-size-12px color-#666">
简历内容将提交给大语言模型,以用于生成已读不回提醒消息;提交内容及生成消息中不会包含期望薪资
</div>
</div>
</el-form-item>
<el-form-item class="mb4px">
<div>
<div>
<el-button size="small" type="primary" @click="handleClickEditPrompt">
使用外部编辑器编辑提示词模板 (Markdown)
</el-button>
<el-button
size="small"
type="primary"
@click="
() => {
gtagRenderer('reset_template_clicked_in_main_form')
restoreDefaultTemplate()
}
"
>
还原默认提示词模板
</el-button>
</div>
<div class="font-size-12px color-#666">
对生成效果不够满意?可在此查看、编辑提示词模板。请在模板中需要插入简历的位置插入
__REPLACE_REAL_RESUME_HERE__
</div>
</div>
</el-form-item>
<el-form-item prop="recentMessageQuantityForLlm">
<div>
携带最近
<el-input-number
v-model="formContent.autoReminder.recentMessageQuantityForLlm"
class="w-120px"
:min="8"
:max="20"
:precision="0"
:step="1"
></el-input-number>
次聊天内容作为上下文生成新消息
</div>
</el-form-item>
<el-form-item>
<el-button size="small" type="primary" @click="handleTestEffectClicked"
>使用当前配置模拟已读不回复聊过程</el-button
>
</el-form-item>
<el-form-item prop="recentMessageQuantityForLlm">
<div class="flex flex-items-center">
<span class="whitespace-nowrap">当所有模型均不可使用时&nbsp;</span>
<el-select
v-model="formContent.autoReminder.rechatLlmFallback"
class="w200px"
label="name"
>
<el-option
v-for="option in rechatLlmFallbackOptions"
:key="option.value"
:value="option.value"
:label="option.name"
/>
</el-select>
</div>
</el-form-item>
</template>
</div>
<el-form-item label="跟进间隔(分钟)" prop="throttleIntervalMinutes">
<el-input-number <el-input-number
v-model="formContent.autoReminder.rechatLimitDay" v-model="formContent.autoReminder.throttleIntervalMinutes"
class="w-150px" class="w-150px"
:min="0" :min="3"
:precision="1" :precision="1"
:step="0.5" :step="0.5"
:disabled="!enableRechatLimit" @blur="handleThrottleIntervalMinutesBlur"
/>&nbsp;天<br /> />&nbsp;分钟内不多次跟进同一Boss
<div v-if="enableRechatLimit"> </el-form-item>
不再跟进&nbsp;<span class="text-orange">{{ rechatLimitDateString }}</span <el-form-item label="跟进时限(天)" prop="rechatLimitDay" mb-0>
>)之前列表中没有进展的聊天 <div>
<div><el-checkbox v-model="enableRechatLimit" />&nbsp;启用</div>
<el-input-number
v-model="formContent.autoReminder.rechatLimitDay"
class="w-150px"
:min="0"
:precision="1"
:step="0.5"
:disabled="!enableRechatLimit"
/>&nbsp;天<br />
<div v-if="enableRechatLimit">
不再跟进&nbsp;<span class="text-orange">{{ rechatLimitDateString }}</span
>)之前列表中没有进展的聊天
</div>
<div v-else>这将会跟进列表中所有聊天(<span class="text-orange">不建议</span></div>
</div> </div>
<div v-else>这将会跟进列表中所有聊天(<span class="text-orange">不建议</span></div> </el-form-item>
</div> <el-form-item>
</el-form-item> <el-tooltip
<el-form-item> effect="light"
<el-tooltip placement="bottom-start"
effect="light" @show="gtagRenderer('tooltip_show_about_stop_trace_one_boss')"
placement="bottom-start"
@show="gtagRenderer('tooltip_show_about_stop_trace_one_boss')"
>
<template #content>
<ul m0 line-height-1.5em w-300px pl2em>
<li>
请向你不想继续提醒的Boss发送任意消息,发送后立即撤回的这条消息即可。
<br />
<br />
对于PC端Boss直聘,鼠标移动到要撤回的消息,点按鼠标右键调出菜单,再鼠标左键点击菜单中的“撤回”。如图所示:
<br />
<img block w-full src="./resources/withdraw-message-guide.png" />
</li>
</ul>
</template>
<el-button type="text" font-size-12px
><span><QuestionFilled w-1em h-1em mr2px /></span
>我不想持续提醒某个Boss了,如何处理?</el-button
> >
</el-tooltip> <template #content>
</el-form-item> <ul m0 line-height-1.5em w-300px pl2em>
<el-form-item class="last-form-item"> <li>
<el-button type="primary" @click="handleSubmit">开始提醒</el-button> 请向你不想继续提醒的Boss发送任意消息,发送后立即撤回的这条消息即可。
</el-form-item> <br />
<div> <br />
<el-button @click="handleStopButtonClick">结束任务</el-button> 对于PC端Boss直聘,鼠标移动到要撤回的消息,点按鼠标右键调出菜单,再鼠标左键点击菜单中的“撤回”。如图所示:
</div> <br />
</el-form> <img block w-full src="./resources/withdraw-message-guide.png" />
</li>
</ul>
</template>
<el-button type="text" font-size-12px
><span><QuestionFilled w-1em h-1em mr2px /></span
>我不想持续提醒某个Boss了,如何处理?</el-button
>
</el-tooltip>
</el-form-item>
<el-form-item class="last-form-item" flex>
<el-button type="primary" @click="handleSubmit">开始提醒</el-button>
</el-form-item>
</el-form>
</div>
<div
class="runing-overlay__wrap"
:style="{
pointerEvents: 'none'
}"
>
<RuningOverlay worker-id="readNoReplyAutoReminderMain">
<template #op-buttons>
<el-button @click="handleStopButtonClick">结束任务</el-button>
</template>
</RuningOverlay>
</div>
</div> </div>
</template> </template>
@@ -237,6 +248,7 @@ import {
import { gtagRenderer as baseGtagRenderer } from '@renderer/utils/gtag' import { gtagRenderer as baseGtagRenderer } from '@renderer/utils/gtag'
import mittBus from '../../utils/mitt' import mittBus from '../../utils/mitt'
import { QuestionFilled } from '@element-plus/icons-vue' import { QuestionFilled } from '@element-plus/icons-vue'
import RuningOverlay from '@renderer/features/RunningOverlay/index.vue'
const gtagRenderer = (name, params?: object) => { const gtagRenderer = (name, params?: object) => {
return baseGtagRenderer(name, { return baseGtagRenderer(name, {
scene: 'rnrr-config', scene: 'rnrr-config',
@@ -595,22 +607,29 @@ const handleStopButtonClick = async () => {
} }
</script> </script>
<style scoped lang="scss"> <style lang="scss">
.form-wrap { .read-no-reply-reminder__wrap {
max-height: 100vh; position: relative;
overflow: auto; .form-wrap {
padding-left: 20px; max-height: 100vh;
padding-right: 20px; overflow: auto;
:deep(.el-form) { padding-left: 20px;
margin: 0 auto; padding-right: 20px;
max-width: 1000px; .el-form {
padding-top: 8px; margin: 0 auto;
} max-width: 1000px;
.last-form-item { padding-top: 8px;
:deep(.el-form-item__content) {
margin-top: 0px;
justify-content: flex-end;
} }
.last-form-item {
.el-form-item__content {
margin-top: 0px;
justify-content: flex-end;
}
}
}
.runing-overlay__wrap {
position: absolute;
inset: 0;
} }
} }
</style> </style>
+1 -1
View File
@@ -25,7 +25,7 @@ export const useTaskManagerStore = defineStore('taskManager', () => {
function getRunningTasks() { function getRunningTasks() {
const { ipcRenderer } = electron const { ipcRenderer } = electron
ipcRenderer.invoke('get-task-manager-list').then(res => { ipcRenderer.invoke('get-task-manager-list').then(res => {
runningTasks.value = res runningTasks.value = res.workers ?? []
}) })
} }
const throttledGetRunningTasks = throttle(getRunningTasks, 2000) const throttledGetRunningTasks = throttle(getRunningTasks, 2000)