求职助手配置

This commit is contained in:
xuxin
2026-05-28 11:23:48 +08:00
parent f52a7c56f7
commit 3dbeddcb8f
2 changed files with 345 additions and 1 deletions
@@ -69,7 +69,7 @@
/* 区块标题 */
&__section-title {
font-size: 0.15rem;
font-size: 0.18rem;
font-weight: 600;
color: $text-dark;
}
@@ -199,4 +199,128 @@
object-fit: contain;
}
}
/* ========== 求职助手配置表单 ========== */
&__config-group {
margin-top: 0.16rem;
}
&__config-label {
font-size: 0.13rem;
font-weight: 600;
color: $text-dark;
margin-bottom: 0.08rem;
}
&__config-sub {
font-size: 0.12rem;
color: $text-middle;
margin-bottom: 0.06rem;
}
&__config-options {
display: flex;
flex-wrap: wrap;
gap: 0.08rem;
}
&__config-btn {
padding: 0.07rem 0.16rem;
background: $bg-white;
border: 1px solid $border-color;
border-radius: 0.2rem;
font-size: 0.12rem;
color: $text-dark;
cursor: pointer;
transition: border-color 0.2s, background 0.2s;
&:hover {
border-color: $accent;
}
&--active {
border-color: $accent;
background: $theme-color;
color: $accent;
}
}
&__config-selects {
display: flex;
gap: 0.1rem;
}
&__config-select {
min-width: 1.2rem;
&--full {
flex: 1;
}
}
/* 简历选择行 */
&__resume-row {
display: flex;
align-items: center;
gap: 0.08rem;
}
&__resume-icon {
width: 0.18rem;
height: 0.18rem;
color: $text-middle;
flex-shrink: 0;
}
/* 开关行 */
&__switch-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.1rem;
}
&__switch-text {
font-size: 0.12rem;
color: $text-dark;
line-height: 1.6;
}
&__switch-sub {
font-size: 0.11rem;
color: $text-light;
}
&__tip {
font-size: 0.12rem;
color: $text-light;
cursor: help;
margin-left: 0.04rem;
}
/* 提交按钮 */
&__submit-wrap {
margin-top: 0.24rem;
text-align: center;
}
&__submit-btn {
padding: 0.1rem 0.5rem;
background: $gradient-bg;
color: $bg-white;
border: none;
border-radius: 0.24rem;
font-size: 0.14rem;
cursor: pointer;
transition: opacity 0.2s;
&:hover {
opacity: 0.9;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}
+220
View File
@@ -95,6 +95,114 @@
<div class="agent-setting-panel__section-header">
<span class="agent-setting-panel__section-title">求职助手配置</span>
</div>
<!-- 网申常见问题 -->
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">是否愿意接受部门调剂</div>
<div class="agent-setting-panel__config-options">
<button class="agent-setting-panel__config-btn" :class="{ 'agent-setting-panel__config-btn--active': configForm.acceptDeptTransfer === '是,服从调剂' }" @click="configForm.acceptDeptTransfer = '是,服从调剂'">服从调剂</button>
<button class="agent-setting-panel__config-btn" :class="{ 'agent-setting-panel__config-btn--active': configForm.acceptDeptTransfer === '否,不调剂' }" @click="configForm.acceptDeptTransfer = '否,不调剂'">不调剂</button>
</div>
</div>
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">是否接受地点调剂</div>
<div class="agent-setting-panel__config-options">
<button class="agent-setting-panel__config-btn" :class="{ 'agent-setting-panel__config-btn--active': configForm.acceptLocationTransfer === '是' }" @click="configForm.acceptLocationTransfer = '是'"></button>
<button class="agent-setting-panel__config-btn" :class="{ 'agent-setting-panel__config-btn--active': configForm.acceptLocationTransfer === '否' }" @click="configForm.acceptLocationTransfer = '否'"></button>
</div>
</div>
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">可以参加面试的方式</div>
<div class="agent-setting-panel__config-options">
<button class="agent-setting-panel__config-btn" :class="{ 'agent-setting-panel__config-btn--active': configForm.interviewType.includes('线下面试') }" @click="toggleInterviewType('线下面试')">线下面试</button>
<button class="agent-setting-panel__config-btn" :class="{ 'agent-setting-panel__config-btn--active': configForm.interviewType.includes('线上远程') }" @click="toggleInterviewType('线上远程')">线上远程</button>
</div>
</div>
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">你的语言能力</div>
<div class="agent-setting-panel__config-selects">
<el-select v-model="configForm.languages[0].language" placeholder="语种" class="agent-setting-panel__config-select">
<el-option v-for="lang in languageOptions" :key="lang" :label="lang" :value="lang" />
</el-select>
<el-select v-model="configForm.languages[0].proficiency" placeholder="掌握程度" class="agent-setting-panel__config-select">
<el-option v-for="p in proficiencyOptions" :key="p" :label="p" :value="p" />
</el-select>
</div>
</div>
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">预计到岗时间</div>
<div class="agent-setting-panel__config-selects">
<el-select v-model="configForm.availableDate" placeholder="请选择" class="agent-setting-panel__config-select">
<el-option v-for="d in availableDateOptions" :key="d" :label="d" :value="d" />
</el-select>
</div>
</div>
<!-- 实习相关仅实习类型时显示 -->
<template v-if="isInternship">
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">每周可实习天数</div>
<div class="agent-setting-panel__config-selects">
<el-select v-model="configForm.internDaysPerWeek" placeholder="请选择" class="agent-setting-panel__config-select">
<el-option v-for="d in internDaysOptions" :key="d" :label="d" :value="d" />
</el-select>
</div>
</div>
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">预计实习时长</div>
<div class="agent-setting-panel__config-selects">
<el-select v-model="configForm.internDuration" placeholder="请选择" class="agent-setting-panel__config-select">
<el-option v-for="d in internDurationOptions" :key="d" :label="d" :value="d" />
</el-select>
</div>
</div>
</template>
<!-- 简历设置 -->
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__config-label">
简历设置
<el-tooltip content="选择投递时使用的默认简历" placement="top">
<span class="agent-setting-panel__tip"></span>
</el-tooltip>
</div>
<div class="agent-setting-panel__config-sub">设置默认简历</div>
<div class="agent-setting-panel__resume-row">
<svg viewBox="0 0 16 16" fill="none" class="agent-setting-panel__resume-icon">
<path d="M10 1H4a1.5 1.5 0 00-1.5 1.5v11A1.5 1.5 0 004 15h8a1.5 1.5 0 001.5-1.5V4.5L10 1z" stroke="currentColor" stroke-width="1"/>
<path d="M10 1v3.5h3.5" stroke="currentColor" stroke-width="1"/>
</svg>
<el-select v-model="selectedResumeId" placeholder="请选择简历" class="agent-setting-panel__config-select agent-setting-panel__config-select--full">
<el-option v-for="r in resumeList" :key="r.id" :label="r.resumeName" :value="r.id || ''" />
</el-select>
</div>
</div>
<!-- 自动优化简历开关 -->
<div class="agent-setting-panel__config-group">
<div class="agent-setting-panel__switch-row">
<div class="agent-setting-panel__switch-text">
<span>在投递时帮我针对岗位自动优化简历</span>
<el-tooltip content="MVP只补充缺少技能" placement="top">
<span class="agent-setting-panel__tip"></span>
</el-tooltip>
<br/>
<span class="agent-setting-panel__switch-sub">MVP只补充缺少技能</span>
</div>
<el-switch v-model="autoOptimizeSwitch" active-color="#4FC2C9" />
</div>
</div>
<!-- 提交设置按钮 -->
<div class="agent-setting-panel__submit-wrap">
<button class="agent-setting-panel__submit-btn" :disabled="configSaving" @click="handleSubmitConfig">
{{ configSaving ? '保存中...' : '保存设置' }}
</button>
</div>
</div>
</div>
@@ -137,6 +245,9 @@ import type { SaveEducationItem, SaveWorkItem, SaveProjectItem, SaveCompetitionI
import { resolveRegionName } from '@/utils/region'
import { resolveIndustryName } from '@/utils/industry'
import { resolveJobCategoryName } from '@/utils/jobCategory'
import { fetchResumeList } from '@/api/resume'
import type { ResumeListItem } from '@/api/resume'
import { fetchAgentConfig, saveAgentConfig } from '@/api/agent'
/** 事件 */
const emit = defineEmits<{
@@ -221,6 +332,113 @@ function downloadExtension() {
window.open(extensionDownloadUrl, '_blank')
}
// ==================== 求职助手配置 ====================
/** 是否为实习类型 */
const isInternship = computed(() => store.state.jobIntention?.employmentType === 1)
/** 配置表单数据 */
const configForm = ref({
acceptDeptTransfer: '',
acceptLocationTransfer: '',
interviewType: [] as string[],
languages: [{ language: '', proficiency: '' }] as Array<{ language: string; proficiency: string }>,
availableDate: '',
internDaysPerWeek: '',
internDuration: '',
})
/** 语种选项 */
const languageOptions = ['英语', '日语', '法语', '德语', '韩语', '西班牙语', '俄语']
/** 掌握程度选项 */
const proficiencyOptions = ['入门', '日常会话', '商务会话', '无障碍沟通', '母语']
/** 到岗时间选项 */
const availableDateOptions = ['一周以内', '两周以内', '一个月以内', '一个月以上']
/** 实习天数选项 */
const internDaysOptions = ['3天及以上', '4天及以上', '5天及以上']
/** 实习时长选项 */
const internDurationOptions = ['3个月', '4个月', '5个月', '6个月及以上']
/** 切换面试方式(多选) */
function toggleInterviewType(type: string) {
const idx = configForm.value.interviewType.indexOf(type)
idx >= 0 ? configForm.value.interviewType.splice(idx, 1) : configForm.value.interviewType.push(type)
}
/** 简历列表 */
const resumeList = ref<ResumeListItem[]>([])
/** 当前选中的简历 ID */
const selectedResumeId = ref('')
/** 自动优化简历开关 */
const autoOptimizeSwitch = ref(true)
/** 保存中状态 */
const configSaving = ref(false)
/** 加载简历列表 */
async function loadResumeList() {
try {
const res = await fetchResumeList()
if (res.code === '0' && res.data) {
resumeList.value = res.data
const defaultResume = res.data.find(r => r.isDefault === 1)
if (defaultResume && defaultResume.id) {
selectedResumeId.value = defaultResume.id
} else if (res.data.length > 0 && res.data[0].id) {
selectedResumeId.value = res.data[0].id
}
}
} catch { console.error('[AgentSettingPanel] 加载简历列表失败') }
}
/** 加载已有的求职助手配置 — 填充表单 */
async function loadAgentConfig() {
try {
const res = await fetchAgentConfig()
if (res.code === '0' && res.data) {
const cfg = res.data
configForm.value.acceptDeptTransfer = cfg.acceptDeptTransfer || ''
configForm.value.acceptLocationTransfer = cfg.acceptLocationTransfer || ''
configForm.value.interviewType = cfg.interviewType ? [...cfg.interviewType] : []
configForm.value.languages = cfg.languages?.length
? cfg.languages.map(l => ({ language: l.language || '', proficiency: l.proficiency || '' }))
: [{ language: '', proficiency: '' }]
configForm.value.availableDate = cfg.availableDate || ''
configForm.value.internDaysPerWeek = cfg.internDaysPerWeek || ''
configForm.value.internDuration = cfg.internDuration || ''
if (cfg.autoOptimizeResume !== undefined) autoOptimizeSwitch.value = cfg.autoOptimizeResume === 1
}
} catch { console.error('[AgentSettingPanel] 加载求职助手配置失败') }
}
/** 提交设置 — 调用 saveAgentConfig 接口 */
async function handleSubmitConfig() {
configSaving.value = true
try {
await saveAgentConfig({
acceptDeptTransfer: configForm.value.acceptDeptTransfer,
acceptLocationTransfer: configForm.value.acceptLocationTransfer,
interviewType: configForm.value.interviewType,
languages: configForm.value.languages.filter(l => l.language),
availableDate: configForm.value.availableDate,
internDaysPerWeek: configForm.value.internDaysPerWeek,
internDuration: configForm.value.internDuration,
autoOptimizeResume: autoOptimizeSwitch.value ? 1 : 0,
})
ElMessage.success('设置保存成功')
} catch {
ElMessage.error('设置保存失败,请重试')
} finally {
configSaving.value = false
}
}
// ==================== 个人资料数据 ====================
/** 个人档案响应式数据 */
@@ -245,6 +463,8 @@ onMounted(async () => {
await loadInternship()
await loadProject()
await loadCompetition()
await loadResumeList()
await loadAgentConfig()
})
/** 加载基本信息 */