757 lines
25 KiB
Vue
757 lines
25 KiB
Vue
<template>
|
||
<div class="profile-page dflex">
|
||
<SideNav />
|
||
<div class="profile-page__content">
|
||
<!-- 个人资料编辑抽屉 -->
|
||
<ProfileEditDrawer
|
||
v-model="showEditDrawer"
|
||
:module="editModule"
|
||
:initial-data="editInitialData"
|
||
@save="handleSaveEdit"
|
||
/>
|
||
|
||
<!-- 欢迎上传简历弹窗(无个人资料主表记录时自动弹出) -->
|
||
<ResumeUploadDialog v-model="showWelcomeDialog" @confirm="handleWelcomeUpload" />
|
||
|
||
<!-- 页面标题 -->
|
||
<div class="profile-page__header">
|
||
<h2 class="profile-page__title">个人资料</h2>
|
||
</div>
|
||
|
||
<!-- 主体区域:左侧详情 + 右侧入口 -->
|
||
<div class="profile-page__body">
|
||
<!-- 个人资料内容组件 -->
|
||
<ProfilePageContent
|
||
:profile="profile"
|
||
@edit="handleEdit"
|
||
@save="handleInlineSave"
|
||
@exp-update="handleExpUpdate"
|
||
@exp-add="handleExpAdd"
|
||
@exp-delete="handleExpDelete"
|
||
/>
|
||
|
||
<!-- 右侧入口 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 全屏加载遮罩 -->
|
||
<FullscreenLoading :visible="fullLoading" :text="fullLoadingText" title="Nova 正在帮您努力处理~" />
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, onMounted, watch, computed } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { useStore } from 'vuex'
|
||
import SideNav from '@/components/SideNav.vue'
|
||
import ProfileEditDrawer from '@/components/ProfileEditDrawer.vue'
|
||
import ProfilePageContent from '@/components/ProfilePageContent.vue'
|
||
import ResumeUploadDialog from '@/components/ResumeUploadDialog.vue'
|
||
import { saveProfile, fetchProfile, fetchEducation, saveEducation, fetchWork, saveWork, fetchInternship, saveInternship, fetchProject, saveProject, fetchCompetition, saveCompetition, syncProfileFromResume } from '@/api/profile'
|
||
import { uploadResume } from '@/utils/aiRequest'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import FullscreenLoading from '@/components/FullscreenLoading.vue'
|
||
import type { SaveEducationItem, SaveWorkItem, SaveProjectItem, SaveCompetitionItem } from '@/api/profile'
|
||
|
||
const router = useRouter()
|
||
const store = useStore()
|
||
|
||
// ==================== 全屏加载状态 ====================
|
||
/** 全屏加载是否显示 */
|
||
const fullLoading = ref(false)
|
||
/** 全屏加载文案 */
|
||
const fullLoadingText = ref('')
|
||
|
||
/** 页面挂载时加载公共分类数据和个人资料 */
|
||
onMounted(async () => {
|
||
if (!store.state.regions.length) {
|
||
store.dispatch('loadCommonData')
|
||
}
|
||
// 请求个人资料主表数据,判断是否需要弹出欢迎弹窗
|
||
const profileRes = await fetchProfile()
|
||
if (profileRes.code === '0' && (!profileRes.data || profileRes.data === null)) {
|
||
// 无个人资料数据,弹出欢迎上传弹窗
|
||
showWelcomeDialog.value = true
|
||
return
|
||
}
|
||
// 有数据,正常填充
|
||
if (profileRes.code === '0' && profileRes.data) {
|
||
const d = profileRes.data
|
||
profile.value.name = d.name || ''
|
||
profile.value.phone = d.mobileNumber || ''
|
||
profile.value.email = d.email || ''
|
||
profile.value.idNumber = d.idCard || ''
|
||
profile.value.regionCode = d.regionCode || ''
|
||
profile.value.wechat = d.wechatNumber || ''
|
||
profile.value.skills = d.skills || []
|
||
profile.value.certificates = d.certificates || []
|
||
profile.value.portfolioUrl = d.portfolioUrl || ''
|
||
}
|
||
// 请求教育经历数据
|
||
await loadEducation()
|
||
// 请求工作经历数据
|
||
await loadWork()
|
||
// 请求实习经历数据
|
||
await loadInternship()
|
||
// 请求项目经历数据
|
||
await loadProject()
|
||
// 请求竞赛经历数据
|
||
await loadCompetition()
|
||
})
|
||
|
||
/** 加载教育经历数据 */
|
||
async function loadEducation() {
|
||
try {
|
||
const res = await fetchEducation()
|
||
if (res.code === '0' && res.data) {
|
||
profile.value.education = res.data.map(item => ({
|
||
school: item.school || '',
|
||
major: item.major || '',
|
||
studyType: item.studyType ?? 0,
|
||
degree: item.degree ?? 2,
|
||
startDate: item.startDate || '',
|
||
endDate: item.endDate || '',
|
||
description: (item.description || []).map(d => ({
|
||
id: d.id || '',
|
||
text: d.text || '',
|
||
})),
|
||
}))
|
||
}
|
||
} catch {
|
||
console.error('[Profile] 加载教育经历失败')
|
||
}
|
||
}
|
||
|
||
/** 加载工作经历数据 */
|
||
async function loadWork() {
|
||
try {
|
||
const res = await fetchWork()
|
||
if (res.code === '0' && res.data) {
|
||
profile.value.works = res.data.map(item => ({
|
||
companyName: item.companyName || '',
|
||
position: item.position || '',
|
||
startDate: item.startDate || '',
|
||
endDate: item.endDate || '',
|
||
description: (item.description || []).map(d => ({
|
||
id: d.id || '',
|
||
text: d.text || '',
|
||
})),
|
||
}))
|
||
}
|
||
} catch {
|
||
console.error('[Profile] 加载工作经历失败')
|
||
}
|
||
}
|
||
|
||
/** 加载实习经历数据 */
|
||
async function loadInternship() {
|
||
try {
|
||
const res = await fetchInternship()
|
||
if (res.code === '0' && res.data) {
|
||
profile.value.internships = res.data.map(item => ({
|
||
companyName: item.companyName || '',
|
||
position: item.position || '',
|
||
startDate: item.startDate || '',
|
||
endDate: item.endDate || '',
|
||
description: (item.description || []).map(d => ({
|
||
id: d.id || '',
|
||
text: d.text || '',
|
||
})),
|
||
}))
|
||
}
|
||
} catch {
|
||
console.error('[Profile] 加载实习经历失败')
|
||
}
|
||
}
|
||
|
||
/** 加载项目经历数据 */
|
||
async function loadProject() {
|
||
try {
|
||
const res = await fetchProject()
|
||
if (res.code === '0' && res.data) {
|
||
profile.value.projects = res.data.map(item => ({
|
||
projectName: item.projectName || '',
|
||
companyName: item.companyName || '',
|
||
role: item.role || '',
|
||
startDate: item.startDate || '',
|
||
endDate: item.endDate || '',
|
||
description: (item.description || []).map(d => ({
|
||
id: d.id || '',
|
||
text: d.text || '',
|
||
})),
|
||
}))
|
||
}
|
||
} catch {
|
||
console.error('[Profile] 加载项目经历失败')
|
||
}
|
||
}
|
||
|
||
/** 加载竞赛经历数据 */
|
||
async function loadCompetition() {
|
||
try {
|
||
const res = await fetchCompetition()
|
||
if (res.code === '0' && res.data) {
|
||
profile.value.competitions = res.data.map(item => ({
|
||
competitionName: item.competitionName || '',
|
||
award: item.award || '',
|
||
awardDate: item.awardDate || '',
|
||
description: (item.description || []).map(d => ({
|
||
id: d.id || '',
|
||
text: d.text || '',
|
||
})),
|
||
}))
|
||
}
|
||
} catch {
|
||
console.error('[Profile] 加载竞赛经历失败')
|
||
}
|
||
}
|
||
|
||
/** 编辑抽屉的显示状态 */
|
||
const showEditDrawer = ref(false)
|
||
|
||
/** 欢迎弹窗的显示状态 */
|
||
const showWelcomeDialog = ref(false)
|
||
|
||
/** 欢迎弹窗确认上传回调 — 上传简历并同步个人资料,完成后刷新页面 */
|
||
async function handleWelcomeUpload(file: File) {
|
||
fullLoadingText.value = '简历解析中,请耐心等待…'
|
||
fullLoading.value = true
|
||
|
||
try {
|
||
const res = await uploadResume(file)
|
||
if (res.code === 0 && res.data?.resumeId) {
|
||
// 继续同步个人资料
|
||
fullLoadingText.value = '正在同步个人资料…'
|
||
await syncProfileFromResume(String(res.data.resumeId))
|
||
fullLoading.value = false
|
||
ElMessage.success('简历上传并同步成功')
|
||
// 刷新页面数据
|
||
router.go(0)
|
||
} else {
|
||
fullLoading.value = false
|
||
ElMessage.error(res.msg || '上传失败')
|
||
}
|
||
} catch {
|
||
fullLoading.value = false
|
||
ElMessage.error('上传失败,请稍后重试')
|
||
}
|
||
}
|
||
|
||
/** 登录状态 */
|
||
const isAuthenticated = computed(() => store.state.isAuthenticated)
|
||
|
||
/** 监听登录状态变化 — 登录成功后检查个人资料是否存在 */
|
||
watch(isAuthenticated, async (newVal, oldVal) => {
|
||
if (newVal && !oldVal) {
|
||
try {
|
||
const profileRes = await fetchProfile()
|
||
if (profileRes.code === '0' && (!profileRes.data || profileRes.data === null)) {
|
||
showWelcomeDialog.value = true
|
||
}
|
||
} catch {
|
||
// 接口异常不阻塞
|
||
}
|
||
}
|
||
})
|
||
|
||
/** 当前编辑的模块名称 */
|
||
const editModule = ref('info')
|
||
|
||
/** 当前编辑模块的初始数据 */
|
||
const editInitialData = ref<Record<string, any>>({})
|
||
|
||
/** 保存中的加载状态 */
|
||
const saving = ref(false)
|
||
|
||
// ==================== 个人资料数据(非数组字段由接口填充,数组字段暂用模拟数据) ====================
|
||
const profile = ref({
|
||
/** 真实姓名 — 接口字段 name */
|
||
name: '',
|
||
/** 手机号码 — 接口字段 mobileNumber */
|
||
phone: '',
|
||
/** 邮箱 — 接口字段 email */
|
||
email: '',
|
||
/** 身份证号 — 接口字段 idCard */
|
||
idNumber: '',
|
||
/** 所在城市编码 — 接口字段 regionCode */
|
||
regionCode: '',
|
||
/** 微信号 — 接口字段 wechatNumber */
|
||
wechat: '',
|
||
/** 技能标签列表 — 接口字段 skills */
|
||
skills: [] as string[],
|
||
/** 证书标签列表 — 接口字段 certificates */
|
||
certificates: [] as string[],
|
||
/** 作品集链接 — 接口字段 portfolioUrl */
|
||
portfolioUrl: '',
|
||
/** 教育经历 — 对应数据库 bg_user_profile_education */
|
||
education: [] as Array<{
|
||
school: string
|
||
major: string
|
||
studyType: number
|
||
degree: number
|
||
startDate: string
|
||
endDate: string
|
||
description: Array<{ id: string; text: string }>
|
||
}>,
|
||
/** 工作经历 — 对应数据库 bg_user_profile_work */
|
||
works: [] as Array<{
|
||
companyName: string
|
||
position: string
|
||
startDate: string
|
||
endDate: string
|
||
description: Array<{ id: string; text: string }>
|
||
}>,
|
||
internships: [] as Array<{
|
||
companyName: string
|
||
position: string
|
||
startDate: string
|
||
endDate: string
|
||
description: Array<{ id: string; text: string }>
|
||
}>,
|
||
projects: [] as Array<{
|
||
projectName: string
|
||
companyName: string
|
||
role: string
|
||
startDate: string
|
||
endDate: string
|
||
description: Array<{ id: string; text: string }>
|
||
}>,
|
||
/** 竞赛经历 — 对应数据库 bg_user_profile_competition */
|
||
competitions: [] as Array<{
|
||
competitionName: string
|
||
award: string
|
||
awardDate: string
|
||
description: Array<{ id: string; text: string }>
|
||
}>,
|
||
})
|
||
|
||
// ==================== 事件处理 ====================
|
||
|
||
/** 打开编辑抽屉 — 根据模块名设置初始数据 */
|
||
function handleEdit(section: string) {
|
||
editModule.value = section
|
||
|
||
// 根据模块名提取对应的初始数据
|
||
if (section === 'info') {
|
||
editInitialData.value = {
|
||
name: profile.value.name,
|
||
email: profile.value.email,
|
||
phone: profile.value.phone,
|
||
/** 城市编码 — 传给编辑抽屉的 RegionSelector */
|
||
location: profile.value.regionCode,
|
||
wechat: profile.value.wechat,
|
||
}
|
||
} else if (section === 'education') {
|
||
editInitialData.value = {
|
||
education: profile.value.education.map(edu => ({
|
||
school: edu.school,
|
||
major: edu.major,
|
||
studyType: edu.studyType,
|
||
degree: edu.degree,
|
||
startDate: edu.startDate,
|
||
endDate: edu.endDate,
|
||
description: edu.description.map(d => ({ ...d })),
|
||
})),
|
||
}
|
||
} else if (section === 'work') {
|
||
editInitialData.value = {
|
||
works: profile.value.works.map(exp => ({
|
||
companyName: exp.companyName,
|
||
position: exp.position,
|
||
startDate: exp.startDate,
|
||
endDate: exp.endDate,
|
||
description: exp.description.map(d => ({ ...d })),
|
||
})),
|
||
}
|
||
} else if (section === 'internship') {
|
||
editInitialData.value = {
|
||
internships: profile.value.internships.map(exp => ({
|
||
companyName: exp.companyName,
|
||
position: exp.position,
|
||
startDate: exp.startDate,
|
||
endDate: exp.endDate,
|
||
description: exp.description.map(d => ({ ...d })),
|
||
})),
|
||
}
|
||
} else if (section === 'project') {
|
||
editInitialData.value = {
|
||
projects: profile.value.projects.map(proj => ({
|
||
projectName: proj.projectName,
|
||
companyName: proj.companyName,
|
||
role: proj.role,
|
||
startDate: proj.startDate,
|
||
endDate: proj.endDate,
|
||
description: proj.description.map(d => ({ ...d })),
|
||
})),
|
||
}
|
||
} else if (section === 'competition') {
|
||
editInitialData.value = {
|
||
competitions: profile.value.competitions.map(comp => ({
|
||
competitionName: comp.competitionName,
|
||
award: comp.award,
|
||
awardDate: comp.awardDate,
|
||
description: comp.description.map(d => ({ ...d })),
|
||
})),
|
||
}
|
||
} else if (section === 'portfolio') {
|
||
editInitialData.value = {
|
||
portfolioUrl: profile.value.portfolioUrl,
|
||
}
|
||
} else if (section === 'skills') {
|
||
editInitialData.value = {
|
||
skills: [...profile.value.skills],
|
||
}
|
||
} else if (section === 'certificate') {
|
||
editInitialData.value = {
|
||
certificates: [...profile.value.certificates],
|
||
}
|
||
} else {
|
||
editInitialData.value = {}
|
||
}
|
||
|
||
showEditDrawer.value = true
|
||
}
|
||
|
||
/** 保存编辑数据 — 将抽屉返回的数据合并到 profile,并调用对应接口持久化 */
|
||
async function handleSaveEdit(data: Record<string, any>) {
|
||
if (editModule.value === 'info') {
|
||
// ---- 基本信息:调用主表接口保存 ----
|
||
try {
|
||
saving.value = true
|
||
await saveProfile({
|
||
name: data.name,
|
||
email: data.email,
|
||
mobileNumber: data.phone,
|
||
regionCode: data.location,
|
||
wechatNumber: data.wechat,
|
||
portfolioUrl: data.portfolioUrl,
|
||
})
|
||
// 接口成功后更新本地数据
|
||
profile.value.name = data.name
|
||
profile.value.email = data.email
|
||
profile.value.phone = data.phone
|
||
profile.value.wechat = data.wechat
|
||
profile.value.portfolioUrl = data.portfolioUrl || ''
|
||
/** 将城市编码存入 regionCode,先直接显示编码,后续联调获取接口再做名称转换 */
|
||
profile.value.regionCode = data.location || ''
|
||
ElMessage.success('个人信息保存成功')
|
||
} catch {
|
||
ElMessage.error('个人信息保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'education') {
|
||
// ---- 教育经历:调用教育经历接口保存 ----
|
||
try {
|
||
saving.value = true
|
||
const payload: SaveEducationItem[] = data.education.map((edu: any) => ({
|
||
school: edu.school,
|
||
major: edu.major,
|
||
degree: edu.degree,
|
||
studyType: edu.studyType,
|
||
startDate: edu.startDate,
|
||
endDate: edu.endDate,
|
||
description: edu.description.map((d: any) => ({ id: d.id, text: d.text })),
|
||
}))
|
||
await saveEducation(payload)
|
||
// 接口成功后更新本地数据
|
||
profile.value.education = data.education.map((edu: any) => ({
|
||
school: edu.school,
|
||
major: edu.major,
|
||
studyType: edu.studyType,
|
||
degree: edu.degree,
|
||
startDate: edu.startDate,
|
||
endDate: edu.endDate,
|
||
description: edu.description.map((d: any) => ({ ...d })),
|
||
}))
|
||
ElMessage.success('教育经历保存成功')
|
||
} catch {
|
||
ElMessage.error('教育经历保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'work') {
|
||
// ---- 工作经历:调用工作经历接口保存 ----
|
||
try {
|
||
saving.value = true
|
||
const payload: SaveWorkItem[] = data.works.map((work: any) => ({
|
||
companyName: work.companyName,
|
||
position: work.position,
|
||
startDate: work.startDate,
|
||
endDate: work.endDate || '',
|
||
description: work.description.map((d: any) => ({ id: d.id, text: d.text })),
|
||
}))
|
||
await saveWork(payload)
|
||
// 接口成功后更新本地数据
|
||
profile.value.works = data.works.map((work: any) => ({
|
||
companyName: work.companyName,
|
||
position: work.position,
|
||
startDate: work.startDate,
|
||
endDate: work.endDate,
|
||
description: work.description.map((d: any) => ({ ...d })),
|
||
}))
|
||
ElMessage.success('工作经历保存成功')
|
||
} catch {
|
||
ElMessage.error('工作经历保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'internship') {
|
||
// ---- 实习经历:调用实习经历接口保存 ----
|
||
try {
|
||
saving.value = true
|
||
const payload: SaveWorkItem[] = data.internships.map((intern: any) => ({
|
||
companyName: intern.companyName,
|
||
position: intern.position,
|
||
startDate: intern.startDate,
|
||
endDate: intern.endDate || '',
|
||
description: intern.description.map((d: any) => ({ id: d.id, text: d.text })),
|
||
}))
|
||
await saveInternship(payload)
|
||
// 接口成功后更新本地数据
|
||
profile.value.internships = data.internships.map((intern: any) => ({
|
||
companyName: intern.companyName,
|
||
position: intern.position,
|
||
startDate: intern.startDate,
|
||
endDate: intern.endDate,
|
||
description: intern.description.map((d: any) => ({ ...d })),
|
||
}))
|
||
ElMessage.success('实习经历保存成功')
|
||
} catch {
|
||
ElMessage.error('实习经历保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'project') {
|
||
// ---- 项目经历:调用项目经历接口保存 ----
|
||
try {
|
||
saving.value = true
|
||
const payload: SaveProjectItem[] = data.projects.map((proj: any) => ({
|
||
projectName: proj.projectName,
|
||
companyName: proj.companyName || '',
|
||
role: proj.role || '',
|
||
startDate: proj.startDate,
|
||
endDate: proj.endDate || '',
|
||
description: proj.description.map((d: any) => ({ id: d.id, text: d.text })),
|
||
}))
|
||
await saveProject(payload)
|
||
// 接口成功后更新本地数据
|
||
profile.value.projects = data.projects.map((proj: any) => ({
|
||
projectName: proj.projectName,
|
||
companyName: proj.companyName,
|
||
role: proj.role,
|
||
startDate: proj.startDate,
|
||
endDate: proj.endDate,
|
||
description: proj.description.map((d: any) => ({ ...d })),
|
||
}))
|
||
ElMessage.success('项目经历保存成功')
|
||
} catch {
|
||
ElMessage.error('项目经历保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'competition') {
|
||
// ---- 竞赛经历:调用竞赛经历接口保存 ----
|
||
try {
|
||
saving.value = true
|
||
const payload: SaveCompetitionItem[] = data.competitions.map((comp: any) => ({
|
||
competitionName: comp.competitionName,
|
||
award: comp.award || '',
|
||
awardDate: comp.awardDate || '',
|
||
description: comp.description.map((d: any) => ({ id: d.id, text: d.text })),
|
||
}))
|
||
await saveCompetition(payload)
|
||
// 接口成功后更新本地数据
|
||
profile.value.competitions = data.competitions.map((comp: any) => ({
|
||
competitionName: comp.competitionName,
|
||
award: comp.award,
|
||
awardDate: comp.awardDate,
|
||
description: comp.description.map((d: any) => ({ ...d })),
|
||
}))
|
||
ElMessage.success('竞赛经历保存成功')
|
||
} catch {
|
||
ElMessage.error('竞赛经历保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'portfolio') {
|
||
// ---- 作品集:调用主表接口保存,需要传递完整的个人信息数据 ----
|
||
try {
|
||
saving.value = true
|
||
await saveProfile({
|
||
name: profile.value.name,
|
||
email: profile.value.email,
|
||
mobileNumber: profile.value.phone,
|
||
idCard: profile.value.idNumber,
|
||
regionCode: profile.value.regionCode,
|
||
wechatNumber: profile.value.wechat,
|
||
skills: profile.value.skills,
|
||
certificates: profile.value.certificates,
|
||
portfolioUrl: data.portfolioUrl,
|
||
})
|
||
profile.value.portfolioUrl = data.portfolioUrl
|
||
ElMessage.success('作品集保存成功')
|
||
} catch {
|
||
ElMessage.error('作品集保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'skills') {
|
||
// ---- 技能:调用主表接口保存,需要传递完整的个人信息数据 ----
|
||
try {
|
||
saving.value = true
|
||
await saveProfile({
|
||
name: profile.value.name,
|
||
email: profile.value.email,
|
||
mobileNumber: profile.value.phone,
|
||
idCard: profile.value.idNumber,
|
||
regionCode: profile.value.regionCode,
|
||
wechatNumber: profile.value.wechat,
|
||
skills: [...data.skills],
|
||
certificates: profile.value.certificates,
|
||
})
|
||
profile.value.skills = [...data.skills]
|
||
ElMessage.success('技能保存成功')
|
||
} catch {
|
||
ElMessage.error('技能保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
} else if (editModule.value === 'certificate') {
|
||
// ---- 证书:调用主表接口保存,需要传递完整的个人信息数据 ----
|
||
try {
|
||
saving.value = true
|
||
await saveProfile({
|
||
name: profile.value.name,
|
||
email: profile.value.email,
|
||
mobileNumber: profile.value.phone,
|
||
idCard: profile.value.idNumber,
|
||
regionCode: profile.value.regionCode,
|
||
wechatNumber: profile.value.wechat,
|
||
skills: profile.value.skills,
|
||
certificates: [...data.certificates],
|
||
})
|
||
profile.value.certificates = [...data.certificates]
|
||
ElMessage.success('证书保存成功')
|
||
} catch {
|
||
ElMessage.error('证书保存失败,请重试')
|
||
} finally {
|
||
saving.value = false
|
||
}
|
||
}
|
||
}
|
||
|
||
function goToJobs() {
|
||
router.push('/jobs')
|
||
}
|
||
|
||
function goToResume() {
|
||
router.push('/resume')
|
||
}
|
||
|
||
/** 内联保存处理(个人信息/技能/证书模块从组件内直接保存) */
|
||
async function handleInlineSave(section: string, data: Record<string, any>) {
|
||
// 复用已有的 handleSaveEdit 逻辑
|
||
editModule.value = section
|
||
await handleSaveEdit(data)
|
||
}
|
||
|
||
/** 单条经历更新 — 将编辑后的数据替换到完整列表中再整体保存 */
|
||
async function handleExpUpdate(moduleType: string, index: number, data: Record<string, any>) {
|
||
try {
|
||
if (moduleType === 'education') {
|
||
const list = profile.value.education.map((item, i) => i === index ? data : item) as any[]
|
||
await saveEducation(list)
|
||
await loadEducation()
|
||
} else if (moduleType === 'work') {
|
||
const list = profile.value.works.map((item, i) => i === index ? data : item) as any[]
|
||
await saveWork(list)
|
||
await loadWork()
|
||
} else if (moduleType === 'internship') {
|
||
const list = profile.value.internships.map((item, i) => i === index ? data : item) as any[]
|
||
await saveInternship(list)
|
||
await loadInternship()
|
||
} else if (moduleType === 'project') {
|
||
const list = profile.value.projects.map((item, i) => i === index ? data : item) as any[]
|
||
await saveProject(list)
|
||
await loadProject()
|
||
} else if (moduleType === 'competition') {
|
||
const list = profile.value.competitions.map((item, i) => i === index ? data : item) as any[]
|
||
await saveCompetition(list)
|
||
await loadCompetition()
|
||
}
|
||
ElMessage.success('保存成功')
|
||
} catch {
|
||
ElMessage.error('保存失败')
|
||
}
|
||
}
|
||
|
||
/** 新增经历 */
|
||
async function handleExpAdd(moduleType: string, data: Record<string, any>) {
|
||
try {
|
||
if (moduleType === 'education') {
|
||
const list = [...profile.value.education, data] as any[]
|
||
await saveEducation(list)
|
||
await loadEducation()
|
||
} else if (moduleType === 'work') {
|
||
const list = [...profile.value.works, data] as any[]
|
||
await saveWork(list)
|
||
await loadWork()
|
||
} else if (moduleType === 'internship') {
|
||
const list = [...profile.value.internships, data] as any[]
|
||
await saveInternship(list)
|
||
await loadInternship()
|
||
} else if (moduleType === 'project') {
|
||
const list = [...profile.value.projects, data] as any[]
|
||
await saveProject(list)
|
||
await loadProject()
|
||
} else if (moduleType === 'competition') {
|
||
const list = [...profile.value.competitions, data] as any[]
|
||
await saveCompetition(list)
|
||
await loadCompetition()
|
||
}
|
||
ElMessage.success('添加成功')
|
||
} catch {
|
||
ElMessage.error('添加失败')
|
||
}
|
||
}
|
||
|
||
/** 删除单条经历 — 从列表中移除对应索引后全量保存 */
|
||
async function handleExpDelete(moduleType: string, index: number) {
|
||
try {
|
||
await ElMessageBox.confirm('确定要删除这条经历吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
})
|
||
} catch {
|
||
return // 用户取消
|
||
}
|
||
try {
|
||
if (moduleType === 'education') {
|
||
const list = profile.value.education.filter((_, i) => i !== index) as any[]
|
||
await saveEducation(list)
|
||
await loadEducation()
|
||
} else if (moduleType === 'work') {
|
||
const list = profile.value.works.filter((_, i) => i !== index) as any[]
|
||
await saveWork(list)
|
||
await loadWork()
|
||
} else if (moduleType === 'internship') {
|
||
const list = profile.value.internships.filter((_, i) => i !== index) as any[]
|
||
await saveInternship(list)
|
||
await loadInternship()
|
||
} else if (moduleType === 'project') {
|
||
const list = profile.value.projects.filter((_, i) => i !== index) as any[]
|
||
await saveProject(list)
|
||
await loadProject()
|
||
} else if (moduleType === 'competition') {
|
||
const list = profile.value.competitions.filter((_, i) => i !== index) as any[]
|
||
await saveCompetition(list)
|
||
await loadCompetition()
|
||
}
|
||
ElMessage.success('删除成功')
|
||
} catch {
|
||
ElMessage.error('删除失败')
|
||
}
|
||
}
|
||
</script>
|