登陆页左侧新广告特效
This commit is contained in:
+131
-39
@@ -135,10 +135,17 @@
|
||||
<div class="resume-detail__card" :class="{ 'resume-detail__card-hover': editModule !== 'info' || !showEditDrawer }">
|
||||
<!-- 展示模式 -->
|
||||
<template v-if="editModule !== 'info' || !showEditDrawer">
|
||||
<div class="resume-detail__card-header">
|
||||
<div>
|
||||
<div class="resume-detail__card-header color-6">
|
||||
<div class="dflex-start aliite-c">
|
||||
<h3 class="resume-detail__user-name">{{ resumeMain.name || '未填写姓名' }}</h3>
|
||||
<p class="resume-detail__user-title">{{ resumeMain.targetPosition || '' }}</p>
|
||||
<span v-if="resumeMain.city" class="ml10 dflex-start aliite-c fs13">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="resume-detail__contact-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>
|
||||
{{ resumeMain.city }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 编辑按钮 — hover时才显示,品牌色图标+文字 -->
|
||||
<button class="resume-detail__edit-btn-inline" @click="openEditDrawer('info')" aria-label="编辑个人信息">
|
||||
@@ -162,20 +169,10 @@
|
||||
</svg>
|
||||
{{ resumeMain.mobileNumber }}
|
||||
</span>
|
||||
<!-- 所在城市 -->
|
||||
<span v-if="resumeMain.city" class="resume-detail__contact-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="resume-detail__contact-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>
|
||||
{{ resumeMain.city }}
|
||||
</span>
|
||||
|
||||
<!-- 微信号 -->
|
||||
<span v-if="resumeMain.wechatNumber" class="resume-detail__contact-item">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="resume-detail__contact-icon">
|
||||
<path d="M2 8a6 6 0 1112 0 6 6 0 01-12 0z" stroke="currentColor" stroke-width="1.2"/>
|
||||
<path d="M5.5 7.5c.5-1 1.5-1.5 2.5-1.5s2 .5 2.5 1.5M6 10s.8 1 2 1 2-1 2-1" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<el-icon class="fs14 color-9"><ChatLineRound /></el-icon>
|
||||
{{ resumeMain.wechatNumber }}
|
||||
</span>
|
||||
<!-- 作品集链接 -->
|
||||
@@ -250,7 +247,7 @@
|
||||
@save="handleExpAdd('education', $event)"
|
||||
@cancel="expAddingModule = ''"
|
||||
/>
|
||||
<div v-for="edu in educationList" :key="edu.id" class="resume-detail__exp-item">
|
||||
<div v-for="edu in educationList" :key="edu.id" class="resume-detail__exp-item" @click.stop="startEditExp('education', edu)">
|
||||
<!-- 展示模式 -->
|
||||
<template v-if="expEditingId !== edu.id">
|
||||
<div class="resume-detail__exp-row">
|
||||
@@ -262,11 +259,18 @@
|
||||
建议使用AI润色修复 >>
|
||||
<span class="resume-detail__fix-tooltip">{{ getIssueByRecord('education', edu.id!)!.finding }}</span>
|
||||
</span>
|
||||
<!-- 编辑按钮 — hover时显示 -->
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('education', edu)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
<span>编辑</span>
|
||||
</button>
|
||||
<div class="mlauto dflex-end">
|
||||
<!-- 编辑按钮 — hover时显示 -->
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('education', edu)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon>
|
||||
<span>编辑</span>
|
||||
</button>
|
||||
<!-- 删除按钮 -->
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click.stop="handleExpDelete('education', edu.id!)" aria-label="删除">
|
||||
<el-icon><DeleteFilled /></el-icon>
|
||||
<span>删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="edu.description?.length" class="resume-detail__desc-list">
|
||||
<p v-for="p in edu.description" :key="p.id" class="resume-detail__desc-item">{{ p.text }}</p>
|
||||
@@ -293,7 +297,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<ResumeExpInlineEdit v-if="expAddingModule === 'work'" :module-type="'work'" @save="handleExpAdd('work', $event)" @cancel="expAddingModule = ''" />
|
||||
<div v-for="exp in workList" :key="exp.id" class="resume-detail__exp-item">
|
||||
<div v-for="exp in workList" :key="exp.id" class="resume-detail__exp-item" @click.stop="startEditExp('work', exp)">
|
||||
<template v-if="expEditingId !== exp.id">
|
||||
<div class="resume-detail__exp-row">
|
||||
<span class="resume-detail__exp-name">{{ exp.companyName }}</span>
|
||||
@@ -304,9 +308,14 @@
|
||||
建议使用AI润色修复 >>
|
||||
<span class="resume-detail__fix-tooltip">{{ getIssueByRecord('work', exp.id!)!.finding }}</span>
|
||||
</span>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('work', exp)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<div class="mlauto dflex-end">
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('work', exp)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click.stop="handleExpDelete('work', exp.id!)" aria-label="删除">
|
||||
<el-icon><DeleteFilled /></el-icon><span>删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-if="exp.description?.length" class="resume-detail__desc-list pl16">
|
||||
<li v-for="p in exp.description" :key="p.id" class="resume-detail__desc-item">{{ p.text }}</li>
|
||||
@@ -325,7 +334,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<ResumeExpInlineEdit v-if="expAddingModule === 'internship'" :module-type="'internship'" @save="handleExpAdd('internship', $event)" @cancel="expAddingModule = ''" />
|
||||
<div v-for="intern in internshipList" :key="intern.id" class="resume-detail__exp-item">
|
||||
<div v-for="intern in internshipList" :key="intern.id" class="resume-detail__exp-item" @click.stop="startEditExp('internship', intern)">
|
||||
<template v-if="expEditingId !== intern.id">
|
||||
<div class="resume-detail__exp-row">
|
||||
<span class="resume-detail__exp-name">{{ intern.companyName }}</span>
|
||||
@@ -336,9 +345,14 @@
|
||||
建议使用AI润色修复 >>
|
||||
<span class="resume-detail__fix-tooltip">{{ getIssueByRecord('internship', intern.id!)!.finding }}</span>
|
||||
</span>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('internship', intern)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<div class="mlauto dflex-end">
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('internship', intern)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click.stop="handleExpDelete('internship', intern.id!)" aria-label="删除">
|
||||
<el-icon><DeleteFilled /></el-icon><span>删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="intern.description?.length" class="resume-detail__desc-list">
|
||||
<p v-for="p in intern.description" :key="p.id" class="resume-detail__desc-item">{{ p.text }}</p>
|
||||
@@ -357,7 +371,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<ResumeExpInlineEdit v-if="expAddingModule === 'project'" :module-type="'project'" @save="handleExpAdd('project', $event)" @cancel="expAddingModule = ''" />
|
||||
<div v-for="proj in projectList" :key="proj.id" class="resume-detail__exp-item">
|
||||
<div v-for="proj in projectList" :key="proj.id" class="resume-detail__exp-item" @click.stop="startEditExp('project', proj)">
|
||||
<template v-if="expEditingId !== proj.id">
|
||||
<div class="resume-detail__exp-row">
|
||||
<span class="resume-detail__exp-name">{{ proj.projectName }}</span>
|
||||
@@ -368,9 +382,14 @@
|
||||
建议使用AI润色修复 >>
|
||||
<span class="resume-detail__fix-tooltip">{{ getIssueByRecord('project', proj.id!)!.finding }}</span>
|
||||
</span>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('project', proj)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<div class="mlauto dflex-end">
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('project', proj)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click.stop="handleExpDelete('project', proj.id!)" aria-label="删除">
|
||||
<el-icon><DeleteFilled /></el-icon><span>删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="proj.description?.length" class="resume-detail__desc-list">
|
||||
<p v-for="p in proj.description" :key="p.id" class="resume-detail__desc-item">{{ p.text }}</p>
|
||||
@@ -389,7 +408,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<ResumeExpInlineEdit v-if="expAddingModule === 'competition'" :module-type="'competition'" @save="handleExpAdd('competition', $event)" @cancel="expAddingModule = ''" />
|
||||
<div v-for="comp in competitionList" :key="comp.id" class="resume-detail__exp-item">
|
||||
<div v-for="comp in competitionList" :key="comp.id" class="resume-detail__exp-item" @click.stop="startEditExp('competition', comp)">
|
||||
<template v-if="expEditingId !== comp.id">
|
||||
<div class="resume-detail__exp-row">
|
||||
<span class="resume-detail__exp-name">{{ comp.competitionName }}</span>
|
||||
@@ -400,9 +419,14 @@
|
||||
建议使用AI润色修复 >>
|
||||
<span class="resume-detail__fix-tooltip">{{ getIssueByRecord('competition', comp.id!)!.finding }}</span>
|
||||
</span>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('competition', comp)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<div class="mlauto dflex-end">
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click="startEditExp('competition', comp)" aria-label="编辑">
|
||||
<el-icon><EditPen /></el-icon><span>编辑</span>
|
||||
</button>
|
||||
<button class="resume-detail__edit-btn-inline resume-detail__exp-edit-btn" @click.stop="handleExpDelete('competition', comp.id!)" aria-label="删除">
|
||||
<el-icon><DeleteFilled /></el-icon><span>删除</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="comp.description?.length" class="resume-detail__desc-list">
|
||||
<p v-for="p in comp.description" :key="p.id" class="resume-detail__desc-item">{{ p.text }}</p>
|
||||
@@ -480,8 +504,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
import SideNav from '@/components/SideNav.vue'
|
||||
import ProfileEditDrawer from '@/components/ProfileEditDrawer.vue'
|
||||
import ResumeExpInlineEdit from '@/components/ResumeExpInlineEdit.vue'
|
||||
@@ -531,7 +556,11 @@ import {
|
||||
type DiagnosisIssue,
|
||||
type DescriptionParagraph,
|
||||
} from '@/api/resume'
|
||||
import {ArrowLeft, EditPen, Plus} from "@element-plus/icons-vue";
|
||||
import {ArrowLeft, EditPen, Plus, DeleteFilled, ChatLineRound} from "@element-plus/icons-vue";
|
||||
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
|
||||
|
||||
// ==================== Store 实例 ====================
|
||||
const store = useStore()
|
||||
|
||||
// ==================== 诊断数据相关 ====================
|
||||
|
||||
@@ -748,6 +777,23 @@ const competitionList = ref<ResumeCompetition[]>([])
|
||||
|
||||
// ==================== 数据加载 ====================
|
||||
|
||||
/** 根据城市名称从地区树中反查城市编码(用于后端未返回 regionCode 时的 fallback) */
|
||||
function resolveRegionCodeByName(cityName: string): string {
|
||||
if (!cityName) return ''
|
||||
const regions = store.state.regions || []
|
||||
for (const province of regions) {
|
||||
for (const city of province.children) {
|
||||
if (city.name === cityName) return city.code
|
||||
if (city.children) {
|
||||
for (const district of city.children) {
|
||||
if (district.name === cityName) return district.code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/** 加载所有简历详情数据 */
|
||||
async function loadResumeDetail() {
|
||||
const [mainRes, eduRes, workRes, internRes, projRes, compRes] = await Promise.all([
|
||||
@@ -761,6 +807,10 @@ async function loadResumeDetail() {
|
||||
|
||||
if (mainRes.code === '0' && mainRes.data) {
|
||||
resumeMain.value = mainRes.data
|
||||
// 如果后端未返回 regionCode 但有 city 名称,尝试从地区树反查编码
|
||||
if (!resumeMain.value.regionCode && resumeMain.value.city) {
|
||||
resumeMain.value.regionCode = resolveRegionCodeByName(resumeMain.value.city)
|
||||
}
|
||||
}
|
||||
if (eduRes.code === '0' && eduRes.data) {
|
||||
educationList.value = eduRes.data
|
||||
@@ -779,12 +829,26 @@ async function loadResumeDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 地区数据反查 ====================
|
||||
|
||||
/** 当 store 中地区树数据加载完毕后,如果 resumeMain 缺少 regionCode 则尝试反查 */
|
||||
watch(
|
||||
() => store.state.regions,
|
||||
(regions) => {
|
||||
if (regions?.length && resumeMain.value.city && !resumeMain.value.regionCode) {
|
||||
resumeMain.value.regionCode = resolveRegionCodeByName(resumeMain.value.city)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
|
||||
onMounted(() => {
|
||||
loadResumeDetail()
|
||||
// 加载诊断报告
|
||||
loadDiagnosis()
|
||||
// 确保地区分类数据可用(页面刷新后 store 可能为空)
|
||||
store.dispatch('loadCommonData')
|
||||
})
|
||||
|
||||
// ==================== 计算属性 ====================
|
||||
@@ -1286,6 +1350,32 @@ async function handleExpUpdate(moduleType: string, recordId: string, data: Recor
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除单条经历 */
|
||||
async function handleExpDelete(moduleType: string, recordId: string) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除这条经历吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
const deleteMap: Record<string, (id: string) => Promise<any>> = {
|
||||
education: deleteResumeEducation,
|
||||
work: deleteResumeWork,
|
||||
internship: deleteResumeInternship,
|
||||
project: deleteResumeProject,
|
||||
competition: deleteResumeCompetition,
|
||||
}
|
||||
const deleteFn = deleteMap[moduleType]
|
||||
if (deleteFn) {
|
||||
await deleteFn(recordId)
|
||||
await loadResumeDetail()
|
||||
ElMessage.success('删除成功')
|
||||
}
|
||||
} catch {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** 保存新增的经历 */
|
||||
async function handleExpAdd(moduleType: string, data: Record<string, any>) {
|
||||
try {
|
||||
@@ -1343,7 +1433,7 @@ function openEditDrawer(section: string) {
|
||||
name: resumeMain.value.name || '',
|
||||
email: resumeMain.value.email || '',
|
||||
phone: resumeMain.value.mobileNumber || '',
|
||||
location: '',
|
||||
location: resumeMain.value.regionCode || '',
|
||||
wechat: resumeMain.value.wechatNumber || '',
|
||||
portfolioUrl: resumeMain.value.portfolioUrl || '',
|
||||
}
|
||||
@@ -1446,6 +1536,7 @@ async function handleSaveEdit(data: Record<string, any>) {
|
||||
email: data.email,
|
||||
mobileNumber: data.phone,
|
||||
city: data.locationName || data.location || '',
|
||||
regionCode: data.location || '',
|
||||
wechatNumber: data.wechat,
|
||||
portfolioUrl: data.portfolioUrl,
|
||||
})
|
||||
@@ -1453,6 +1544,7 @@ async function handleSaveEdit(data: Record<string, any>) {
|
||||
resumeMain.value.email = data.email
|
||||
resumeMain.value.mobileNumber = data.phone
|
||||
resumeMain.value.city = data.locationName || data.location || ''
|
||||
resumeMain.value.regionCode = data.location || ''
|
||||
resumeMain.value.wechatNumber = data.wechat
|
||||
resumeMain.value.portfolioUrl = data.portfolioUrl
|
||||
} else if (editModule.value === 'summary') {
|
||||
|
||||
Reference in New Issue
Block a user