仓库初始化+岗位相关页面
This commit is contained in:
@@ -0,0 +1,546 @@
|
||||
<template>
|
||||
<div class="job-detail dflex">
|
||||
<SideNav />
|
||||
<div class="job-detail__content">
|
||||
<!-- 页面标题 + Tab 切换 -->
|
||||
<JobPageHeader :activeTab="''" />
|
||||
|
||||
<!-- 顶部操作栏 -->
|
||||
<div class="job-detail__toolbar">
|
||||
<button class="job-detail__close-btn" @click="goBack" aria-label="关闭">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__close-icon">
|
||||
<path d="M12 4L4 12M4 4l8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="job-detail__toolbar-right">
|
||||
<button class="job-detail__tool-btn" aria-label="编辑" @click="openDislikeDialog">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__tool-icon">
|
||||
<path d="M11.5 2.5l2 2L5 13H3v-2l8.5-8.5z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="jobs-page__action-icon-btn" :class="{ 'job-detail__tool-btn--liked': job.isFavorite }" aria-label="收藏">
|
||||
<svg viewBox="0 0 16 16" :fill="job.isFavorite ? 'currentColor' : 'none'" class="job-detail__tool-icon">
|
||||
<path d="M8 13.7l-1.1-1C3.6 9.8 1.5 7.9 1.5 5.7 1.5 3.9 2.9 2.5 4.7 2.5c1 0 2 .5 2.6 1.2h1.4c.6-.7 1.6-1.2 2.6-1.2 1.8 0 3.2 1.4 3.2 3.2 0 2.2-2.1 4.1-5.4 6.9L8 13.7z" stroke="currentColor" stroke-width="1"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="job-detail__apply-btn" @click="handleApply">去投递</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域(可滚动) -->
|
||||
<div class="job-detail__body">
|
||||
<!-- 导航 Tab:岗位详情 / 公司概况 -->
|
||||
<div class="job-detail__nav-tabs">
|
||||
<div
|
||||
class="job-detail__nav-tab"
|
||||
:class="{ 'job-detail__nav-tab--active': activeSection === 'job' }"
|
||||
@click="activeSection = 'job'"
|
||||
>岗位详情</div>
|
||||
<div
|
||||
class="job-detail__nav-tab"
|
||||
:class="{ 'job-detail__nav-tab--active': activeSection === 'company' }"
|
||||
@click="scrollToCompany"
|
||||
>公司概况</div>
|
||||
<div class="job-detail__nav-tab-right">
|
||||
<span class="job-detail__link-btn" @click="handleFeedback">问题反馈</span>
|
||||
<span class="job-detail__link-btn" @click="handleReport">原链接</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 岗位详情内容 -->
|
||||
<template v-if="activeSection === 'job'">
|
||||
<!-- 公司 & 职位头部 -->
|
||||
<div class="job-detail__card">
|
||||
<div class="job-detail__card-top">
|
||||
<div class="job-detail__card-left">
|
||||
<div class="job-detail__company-row">
|
||||
<div class="job-detail__company-icon">
|
||||
<img v-if="job.companyLogoUrl" :src="job.companyLogoUrl" :alt="job.company" class="job-detail__company-logo-img" />
|
||||
<svg v-else viewBox="0 0 24 24" fill="none" class="job-detail__company-svg">
|
||||
<rect x="3" y="7" width="18" height="14" rx="2" stroke="currentColor" stroke-width="1.5"/>
|
||||
<path d="M7 7V5a2 2 0 012-2h6a2 2 0 012 2v2" stroke="currentColor" stroke-width="1.5"/>
|
||||
<path d="M3 13h18" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="job-detail__company-name">{{ job.company }}</span>
|
||||
</div>
|
||||
<h3 class="job-detail__job-title">{{ job.title }}</h3>
|
||||
<div class="job-detail__job-meta">
|
||||
<span class="job-detail__meta-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__meta-icon">
|
||||
<circle cx="8" cy="6.5" r="2.5" stroke="currentColor" stroke-width="1.2"/>
|
||||
<path d="M8 14s-5-4-5-7.5a5 5 0 0110 0C13 10 8 14 8 14z" stroke="currentColor" stroke-width="1.2"/>
|
||||
</svg>
|
||||
{{ job.location }}
|
||||
</span>
|
||||
<span class="job-detail__meta-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__meta-icon">
|
||||
<rect x="2" y="3" width="12" height="11" rx="1.5" stroke="currentColor" stroke-width="1.2"/>
|
||||
<path d="M2 6.5h12" stroke="currentColor" stroke-width="1.2"/>
|
||||
</svg>
|
||||
{{ job.experience }}
|
||||
</span>
|
||||
<span class="job-detail__meta-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__meta-icon">
|
||||
<rect x="2" y="2" width="12" height="12" rx="2" stroke="currentColor" stroke-width="1.2"/>
|
||||
<path d="M5 8h6M8 5v6" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
{{ job.type }}
|
||||
</span>
|
||||
<span v-if="job.education" class="job-detail__meta-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__meta-icon">
|
||||
<path d="M8 2L1 6l7 4 7-4-7-4z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>
|
||||
<path d="M3 7.5v4l5 3 5-3v-4" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
{{ job.education }}
|
||||
</span>
|
||||
<span v-if="job.salary" class="job-detail__meta-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="job-detail__meta-icon">
|
||||
<path d="M8 1v14M4 4h8M3 8h10M5 12h6" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
{{ job.salary }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 匹配度环 -->
|
||||
<div class="job-detail__match-area">
|
||||
<div class="job-detail__match-ring">
|
||||
<svg viewBox="0 0 80 80" class="job-detail__ring-svg">
|
||||
<circle cx="40" cy="40" r="34" stroke-width="5" stroke="#E8E8E8" fill="none" opacity="0.3"/>
|
||||
<circle cx="40" cy="40" r="34" stroke-width="5" fill="none"
|
||||
stroke="#4FC2C9"
|
||||
stroke-linecap="round"
|
||||
:stroke-dasharray="2 * Math.PI * 34"
|
||||
:stroke-dashoffset="2 * Math.PI * 34 * (1 - job.matchScore / 100)"
|
||||
transform="rotate(-90 40 40)"
|
||||
/>
|
||||
</svg>
|
||||
<div class="job-detail__match-score">{{ job.matchScore }}%</div>
|
||||
</div>
|
||||
<div class="job-detail__match-label">岗位匹配值</div>
|
||||
<div class="job-detail__match-details">
|
||||
<div class="job-detail__match-item" v-for="m in matchItems" :key="m.label">
|
||||
<div class="job-detail__match-mini-ring">
|
||||
<svg viewBox="0 0 40 40" class="job-detail__mini-ring-svg">
|
||||
<circle cx="20" cy="20" r="16" stroke-width="3" stroke="#E8E8E8" fill="none" opacity="0.3"/>
|
||||
<circle cx="20" cy="20" r="16" stroke-width="3" fill="none"
|
||||
stroke="#BFBFBF"
|
||||
stroke-linecap="round"
|
||||
:stroke-dasharray="2 * Math.PI * 16"
|
||||
:stroke-dashoffset="2 * Math.PI * 16 * (1 - m.score / 100)"
|
||||
transform="rotate(-90 20 20)"
|
||||
/>
|
||||
</svg>
|
||||
<span class="job-detail__mini-score">{{ m.score }}%</span>
|
||||
</div>
|
||||
<span class="job-detail__match-item-label">{{ m.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 优化简历提示 -->
|
||||
<div class="job-detail__optimize-bar">
|
||||
<span>优化简历大幅提升面试成功率!</span>
|
||||
<button class="job-detail__optimize-btn" @click="handleGenerateResume">生成岗位专属简历</button>
|
||||
</div>
|
||||
|
||||
<!-- 岗位描述 -->
|
||||
<div class="job-detail__card">
|
||||
<p class="job-detail__desc-text">{{ job.companyInfo.summary }}</p>
|
||||
<div class="job-detail__tag-list">
|
||||
<span v-for="tag in job.tags" :key="tag" class="job-detail__tag">{{ tag }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 岗位职责 -->
|
||||
<div class="job-detail__card">
|
||||
<h3 class="job-detail__section-title">岗位职责</h3>
|
||||
<ol class="job-detail__list">
|
||||
<li v-for="(item, i) in job.responsibilities" :key="i">{{ item }}</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<!-- 任职要求 -->
|
||||
<div class="job-detail__card">
|
||||
<div class="job-detail__section-header">
|
||||
<h3 class="job-detail__section-title">任职要求</h3>
|
||||
<span class="job-detail__skill-hint">
|
||||
<svg viewBox="0 0 14 14" fill="none" class="job-detail__hint-icon">
|
||||
<circle cx="7" cy="7" r="6" stroke="currentColor" stroke-width="1"/>
|
||||
<path d="M7 6.5V10" stroke="currentColor" stroke-width="1" stroke-linecap="round"/>
|
||||
<circle cx="7" cy="4.5" r="0.5" fill="currentColor"/>
|
||||
</svg>
|
||||
查看您的技能与岗位要求的匹配情况
|
||||
</span>
|
||||
</div>
|
||||
<div class="job-detail__skill-tags">
|
||||
<span
|
||||
v-for="skill in job.requiredSkills"
|
||||
:key="skill.name"
|
||||
class="job-detail__skill-tag cursor-po"
|
||||
:class="{ 'job-detail__skill-tag--matched': skill.matched }"
|
||||
@click="skill.matched = !skill.matched"
|
||||
>
|
||||
{{ skill.name }}
|
||||
<svg v-if="skill.matched" viewBox="0 0 12 12" fill="none" class="job-detail__skill-close">
|
||||
<path d="M9 3L3 9M3 3l6 6" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<ol class="job-detail__list">
|
||||
<li v-for="(item, i) in job.requirements" :key="i">{{ item }}</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<!-- 加分项 -->
|
||||
<div class="job-detail__card">
|
||||
<h3 class="job-detail__section-title">加分项</h3>
|
||||
<p class="job-detail__desc-text">{{ job.bonus }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 公司概况 -->
|
||||
<div ref="companySectionRef" class="job-detail__card">
|
||||
<h3 class="job-detail__section-title">公司概况</h3>
|
||||
<div class="job-detail__company-info">
|
||||
<div class="job-detail__company-info-left">
|
||||
<div class="job-detail__company-header">
|
||||
<div class="job-detail__company-logo">
|
||||
<img v-if="job.companyLogoUrl" :src="job.companyLogoUrl" :alt="job.company" class="job-detail__company-logo-img" />
|
||||
<svg v-else viewBox="0 0 24 24" fill="none" class="job-detail__company-svg">
|
||||
<rect x="3" y="7" width="18" height="14" rx="2" stroke="currentColor" stroke-width="1.5"/>
|
||||
<path d="M7 7V5a2 2 0 012-2h6a2 2 0 012 2v2" stroke="currentColor" stroke-width="1.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="job-detail__company-info-name">{{ job.company }}</span>
|
||||
</div>
|
||||
<p class="job-detail__company-desc">{{ job.companyInfo.description }}</p>
|
||||
</div>
|
||||
<div class="job-detail__company-info-right">
|
||||
<div class="job-detail__company-meta-item">
|
||||
<span class="job-detail__meta-label">成立时间:</span>
|
||||
<span>{{ job.companyInfo.founded }}</span>
|
||||
</div>
|
||||
<div class="job-detail__company-meta-item">
|
||||
<span class="job-detail__meta-label">公司地址:</span>
|
||||
<span>{{ job.companyInfo.address }}</span>
|
||||
</div>
|
||||
<div class="job-detail__company-meta-item">
|
||||
<span class="job-detail__meta-label">企业规模:</span>
|
||||
<span>{{ job.companyInfo.size }}</span>
|
||||
</div>
|
||||
<div class="job-detail__company-meta-item">
|
||||
<span class="job-detail__meta-label">官网:</span>
|
||||
<a :href="job.companyInfo.website" target="_blank" class="job-detail__company-link">{{ job.companyInfo.website }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 融资 -->
|
||||
<div class="job-detail__card">
|
||||
<h3 class="job-detail__section-title">融资</h3>
|
||||
<p class="job-detail__desc-text">
|
||||
<span class="job-detail__funding-label">当前融资阶段:</span>{{ job.companyInfo.fundingStage }}
|
||||
<span class="job-detail__funding-label" style="margin-left: 0.3rem;">最新估值:</span>{{ job.companyInfo.valuation }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 最新动态 -->
|
||||
<div class="job-detail__card" v-if="job.companyInfo.news.length">
|
||||
<h3 class="job-detail__section-title">最新动态</h3>
|
||||
<div class="job-detail__news-list">
|
||||
<div v-for="(news, i) in job.companyInfo.news" :key="i" class="job-detail__news-item">
|
||||
<p class="job-detail__news-desc">{{ news }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 公司概况 Tab 已移除,点击直接滚动到岗位详情中的公司概况部分 -->
|
||||
</div>
|
||||
</div>
|
||||
<AiChat />
|
||||
|
||||
<!-- 职位不感兴趣反馈弹窗 -->
|
||||
<JobDislikeDialog ref="dislikeDialogRef" v-model="showDislikeDialog" :job-id="jobId" />
|
||||
|
||||
<!-- 职位问题反馈弹窗 -->
|
||||
<JobFeedbackDialog ref="feedbackDialogRef" v-model="showFeedbackDialog" :job-id="jobId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, nextTick, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import SideNav from '@/components/SideNav.vue'
|
||||
import AiChat from '@/components/AiChat.vue'
|
||||
import JobPageHeader from '@/components/JobPageHeader.vue'
|
||||
import JobDislikeDialog from '@/components/JobDislikeDialog.vue'
|
||||
import JobFeedbackDialog from '@/components/JobFeedbackDialog.vue'
|
||||
import { fetchJobDetail } from '@/api/jobs'
|
||||
import type { JobDetailData } from '@/api/jobs'
|
||||
|
||||
// ==================== 路由相关 ====================
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
/** 当前岗位 ID,从路由参数中获取 */
|
||||
const jobId = route.params.id as string
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
/** 工作类型映射:数字 → 中文 */
|
||||
function formatEmploymentType(type: number | undefined): string {
|
||||
const map: Record<number, string> = { 0: '全职', 1: '兼职' }
|
||||
return map[type ?? -1] ?? '未知'
|
||||
}
|
||||
|
||||
/** 学历要求映射:数字 → 中文 */
|
||||
function formatEducation(edu: number | undefined): string {
|
||||
const map: Record<number, string> = { 0: '不限', 1: '大专', 2: '本科', 3: '硕士', 4: '博士' }
|
||||
return map[edu ?? -1] ?? '未知'
|
||||
}
|
||||
|
||||
/** 最低工作年限格式化 */
|
||||
function formatExperience(min: number | undefined): string {
|
||||
if (min === undefined || min === null) return '经验不限'
|
||||
if (min === 0) return '经验不限'
|
||||
return `${min}年以上`
|
||||
}
|
||||
|
||||
/**
|
||||
* 将带序号的文本拆分为列表项
|
||||
* 例如 "1.xxx;2.yyy;3.zzz" → ['xxx', 'yyy', 'zzz']
|
||||
*/
|
||||
function splitNumberedText(text: string | undefined): string[] {
|
||||
if (!text) return []
|
||||
// 按 "数字." 或 "数字、" 分割,过滤空项
|
||||
const items = text.split(/\d+[.、]/).filter((s) => s.trim())
|
||||
return items.map((s) => s.trim().replace(/[;;]$/, ''))
|
||||
}
|
||||
|
||||
// ==================== 页面状态 ====================
|
||||
|
||||
/** 当前激活的内容区 Tab:job-岗位详情 / company-公司概况 */
|
||||
const activeSection = ref<'job' | 'company'>('job')
|
||||
|
||||
/** 公司概况卡片 ref,用于滚动定位 */
|
||||
const companySectionRef = ref<HTMLElement | null>(null)
|
||||
|
||||
/** 是否正在加载 */
|
||||
const loading = ref(false)
|
||||
|
||||
/** 点击公司概况 tab 时,确保显示岗位详情内容并滚动到公司概况卡片 */
|
||||
function scrollToCompany() {
|
||||
activeSection.value = 'job'
|
||||
nextTick(() => {
|
||||
companySectionRef.value?.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 岗位详情数据 ====================
|
||||
|
||||
/** 匹配度维度列表(岗位匹配环下方的子维度) */
|
||||
const matchItems = ref([
|
||||
{ label: '行业经验', score: 0 },
|
||||
{ label: '核心技能', score: 0 },
|
||||
{ label: '工作经历', score: 0 },
|
||||
])
|
||||
|
||||
/** 技能标签项(matched 表示用户是否具备该技能,可点击切换) */
|
||||
interface SkillTag {
|
||||
/** 技能名称 */
|
||||
name: string
|
||||
/** 是否匹配 */
|
||||
matched: boolean
|
||||
}
|
||||
|
||||
/** 岗位详情响应式数据 */
|
||||
const job = reactive({
|
||||
/** 岗位 ID */
|
||||
id: jobId,
|
||||
/** 公司名称(优先简称) */
|
||||
company: '',
|
||||
/** 公司 Logo URL */
|
||||
companyLogoUrl: '',
|
||||
/** 岗位标题 */
|
||||
title: '',
|
||||
/** 地区名称 */
|
||||
location: '',
|
||||
/** 工作经验要求(格式化后的文案) */
|
||||
experience: '',
|
||||
/** 工作类型(格式化后的文案) */
|
||||
type: '',
|
||||
/** 学历要求(格式化后的文案) */
|
||||
education: '',
|
||||
/** 薪资描述 */
|
||||
salary: '',
|
||||
/** 匹配总分 */
|
||||
matchScore: 0,
|
||||
/** 岗位描述(原始文本) */
|
||||
description: '',
|
||||
/** 岗位标签 */
|
||||
tags: [] as string[],
|
||||
/** 岗位职责列表(从 description 拆分) */
|
||||
responsibilities: [] as string[],
|
||||
/** 技能标签 */
|
||||
requiredSkills: [] as SkillTag[],
|
||||
/** 任职要求列表(从 requirement 拆分) */
|
||||
requirements: [] as string[],
|
||||
/** 加分项 */
|
||||
bonus: '',
|
||||
/** 来源链接 */
|
||||
sourceUrl: '',
|
||||
/** 是否已收藏 */
|
||||
isFavorite: false,
|
||||
/** 公司信息 */
|
||||
companyInfo: {
|
||||
/** 公司类型 */
|
||||
type: '',
|
||||
/** 公司所属行业 */
|
||||
industryName: '',
|
||||
/** 公司简介 */
|
||||
summary: '',
|
||||
/** 公司描述 */
|
||||
description: '',
|
||||
/** 成立时间 */
|
||||
founded: '',
|
||||
/** 公司地址 */
|
||||
address: '',
|
||||
/** 公司规模 */
|
||||
size: '',
|
||||
/** 公司官网 */
|
||||
website: '',
|
||||
/** 融资状态 */
|
||||
fundingStage: '',
|
||||
/** 最新估值 */
|
||||
valuation: '',
|
||||
/** 公司标签 */
|
||||
tags: [] as string[],
|
||||
/** 公司新闻列表 */
|
||||
news: [] as string[],
|
||||
},
|
||||
})
|
||||
|
||||
/** 将接口返回数据填充到页面响应式对象 */
|
||||
function fillJobData(data: JobDetailData) {
|
||||
job.id = data.jobId
|
||||
job.company = data.companyShortName || data.companyName || ''
|
||||
job.companyLogoUrl = data.companyLogoUrl || ''
|
||||
job.title = data.jobTitle || ''
|
||||
job.location = data.regionName || ''
|
||||
job.experience = formatExperience(data.minExperience)
|
||||
job.type = formatEmploymentType(data.employmentType)
|
||||
job.education = formatEducation(data.education)
|
||||
job.salary = data.salary || ''
|
||||
job.matchScore = data.matchScore ?? 0
|
||||
job.description = data.description || ''
|
||||
job.tags = data.tags || []
|
||||
job.sourceUrl = data.sourceUrl || ''
|
||||
job.isFavorite = data.isFavorite ?? false
|
||||
job.bonus = data.bonus || ''
|
||||
|
||||
// 岗位职责:从 description 中按序号拆分
|
||||
job.responsibilities = splitNumberedText(data.description)
|
||||
|
||||
// 任职要求:从 requirement 中按序号拆分
|
||||
job.requirements = splitNumberedText(data.requirement)
|
||||
|
||||
// 技能标签:默认 matched 为 false
|
||||
job.requiredSkills = (data.skillTags || []).map((name) => ({ name, matched: false }))
|
||||
|
||||
// 匹配度详情
|
||||
if (data.matchDetail) {
|
||||
matchItems.value = [
|
||||
{ label: '行业经验', score: data.matchDetail.industryScore ?? 0 },
|
||||
{ label: '核心技能', score: data.matchDetail.skillScore ?? 0 },
|
||||
{ label: '工作经历', score: data.matchDetail.experienceScore ?? 0 },
|
||||
]
|
||||
}
|
||||
|
||||
// 公司信息
|
||||
job.companyInfo.type = data.companyType || ''
|
||||
job.companyInfo.industryName = data.companyIndustryName || ''
|
||||
job.companyInfo.summary = data.companySummary || ''
|
||||
job.companyInfo.description = data.companyDescription || ''
|
||||
job.companyInfo.founded = data.companyFoundedYear ? `${data.companyFoundedYear}年` : ''
|
||||
job.companyInfo.address = data.companyAddress || ''
|
||||
job.companyInfo.size = data.companyScale || ''
|
||||
job.companyInfo.website = data.companyWebsite || ''
|
||||
job.companyInfo.fundingStage = data.companyFinancingStage || ''
|
||||
job.companyInfo.valuation = data.companyLatestValuation || ''
|
||||
job.companyInfo.tags = data.companyTags || []
|
||||
job.companyInfo.news = data.companyNews || []
|
||||
}
|
||||
|
||||
// ==================== 加载岗位详情 ====================
|
||||
|
||||
/** 调用接口获取岗位详情 */
|
||||
async function loadJobDetail() {
|
||||
if (!jobId) return
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await fetchJobDetail(jobId)
|
||||
if (res.code === '0' && res.data) {
|
||||
fillJobData(res.data)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载岗位详情失败', e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadJobDetail()
|
||||
})
|
||||
|
||||
// ==================== 事件处理 ====================
|
||||
|
||||
/** 不感兴趣弹窗状态 */
|
||||
const showDislikeDialog = ref(false)
|
||||
const dislikeDialogRef = ref<InstanceType<typeof JobDislikeDialog> | null>(null)
|
||||
|
||||
/** 问题反馈弹窗状态 */
|
||||
const showFeedbackDialog = ref(false)
|
||||
const feedbackDialogRef = ref<InstanceType<typeof JobFeedbackDialog> | null>(null)
|
||||
|
||||
/** 打开不感兴趣弹窗 */
|
||||
function openDislikeDialog() {
|
||||
dislikeDialogRef.value?.resetForm()
|
||||
showDislikeDialog.value = true
|
||||
}
|
||||
|
||||
/** 返回职位列表页 */
|
||||
function goBack() {
|
||||
router.push('/jobs')
|
||||
}
|
||||
|
||||
/** 问题反馈 */
|
||||
function handleFeedback() {
|
||||
feedbackDialogRef.value?.resetForm()
|
||||
showFeedbackDialog.value = true
|
||||
}
|
||||
|
||||
/** 跳转到原链接 */
|
||||
function handleReport() {
|
||||
if (job.sourceUrl) {
|
||||
window.open(job.sourceUrl, '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
/** 生成岗位专属简历 */
|
||||
function handleGenerateResume() {
|
||||
console.log('生成岗位专属简历')
|
||||
}
|
||||
|
||||
/** 去投递 — 跳转到来源链接 */
|
||||
function handleApply() {
|
||||
if (job.sourceUrl) {
|
||||
window.open(job.sourceUrl, '_blank')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user