仓库初始化+岗位相关页面
This commit is contained in:
@@ -0,0 +1,579 @@
|
||||
<template>
|
||||
<div class="profile-page dflex">
|
||||
<SideNav />
|
||||
<div class="profile-page__content">
|
||||
<!-- 个人资料编辑抽屉 -->
|
||||
<ProfileEditDrawer
|
||||
v-model="showEditDrawer"
|
||||
:module="editModule"
|
||||
:initial-data="editInitialData"
|
||||
@save="handleSaveEdit"
|
||||
/>
|
||||
|
||||
<!-- 页面标题 -->
|
||||
<div class="profile-page__header">
|
||||
<h2 class="profile-page__title">个人资料 <span class="profile-page__title-tip">ⓘ</span></h2>
|
||||
<p class="profile-page__subtitle">
|
||||
设定个人资料以匹配岗位需求,包括教育背景、实习经历等,大部分信息可以从简历中自动获取,也可以手动修改。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 主体区域:左侧详情 + 右侧入口 -->
|
||||
<div class="profile-page__body">
|
||||
<!-- 个人资料内容组件 -->
|
||||
<ProfilePageContent
|
||||
:profile="profile"
|
||||
@edit="handleEdit"
|
||||
/>
|
||||
|
||||
<!-- 右侧入口 -->
|
||||
<div class="profile-page__sidebar">
|
||||
<!-- 提示卡片 -->
|
||||
<div class="profile-page__tip-card">
|
||||
<p class="profile-page__tip-text">
|
||||
非常棒!你的个人资料已经被完善了,自动填写信息也已变换,现在可以轻松开始投递简历啦!
|
||||
</p>
|
||||
<button class="profile-page__tip-btn" @click="goToJobs">去投递</button>
|
||||
</div>
|
||||
|
||||
<!-- 管理简历入口 -->
|
||||
<div class="profile-page__nav-entry" @click="goToResume">
|
||||
<span class="profile-page__nav-entry-icon">📄</span>
|
||||
<span class="profile-page__nav-entry-text">管理我的简历</span>
|
||||
<svg viewBox="0 0 16 16" fill="none" class="profile-page__nav-arrow">
|
||||
<path d="M6 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } 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 { saveProfile, fetchProfile, fetchEducation, saveEducation, fetchWork, saveWork, fetchInternship, saveInternship, fetchProject, saveProject, fetchCompetition, saveCompetition } from '@/api/profile'
|
||||
import type { SaveEducationItem, SaveWorkItem, SaveProjectItem, SaveCompetitionItem } from '@/api/profile'
|
||||
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
|
||||
/** 页面挂载时加载公共分类数据和个人资料 */
|
||||
onMounted(async () => {
|
||||
if (!store.state.regions.length) {
|
||||
store.dispatch('loadCommonData')
|
||||
}
|
||||
// 请求个人资料主表数据,填充非数组字段
|
||||
await loadProfile()
|
||||
// 请求教育经历数据
|
||||
await loadEducation()
|
||||
// 请求工作经历数据
|
||||
await loadWork()
|
||||
// 请求实习经历数据
|
||||
await loadInternship()
|
||||
// 请求项目经历数据
|
||||
await loadProject()
|
||||
// 请求竞赛经历数据
|
||||
await loadCompetition()
|
||||
})
|
||||
|
||||
/** 加载个人资料主表数据 */
|
||||
async function loadProfile() {
|
||||
try {
|
||||
const res = await fetchProfile()
|
||||
if (res.code === '0' && res.data) {
|
||||
const d = res.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 || []
|
||||
}
|
||||
} catch {
|
||||
console.error('[Profile] 加载个人资料失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载教育经历数据 */
|
||||
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 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[],
|
||||
/** 教育经历 — 对应数据库 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 === '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,
|
||||
})
|
||||
// 接口成功后更新本地数据
|
||||
profile.value.name = data.name
|
||||
profile.value.email = data.email
|
||||
profile.value.phone = data.phone
|
||||
profile.value.wechat = data.wechat
|
||||
/** 将城市编码存入 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 === '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')
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user