新版交互调整
This commit is contained in:
+417
-909
File diff suppressed because it is too large
Load Diff
@@ -449,7 +449,7 @@ function fillJobData(data: JobDetailData) {
|
||||
job.title = data.jobTitle || ''
|
||||
job.location = data.regionName || ''
|
||||
job.experience = formatExperience(data.minExperience)
|
||||
job.type = formatEmploymentType(data.employmentType)
|
||||
job.type = formatEmploymentType(data.recruitCategory)
|
||||
job.education = formatEducation(data.education)
|
||||
job.salary = data.salary || ''
|
||||
job.matchScore = data.matchScore ?? 0
|
||||
|
||||
+71
-19
@@ -10,7 +10,7 @@
|
||||
@save="handleSaveEdit"
|
||||
/>
|
||||
|
||||
<!-- 欢迎上传简历弹窗(无个人资料时自动弹出) -->
|
||||
<!-- 欢迎上传简历弹窗(无个人资料主表记录时自动弹出) -->
|
||||
<ResumeUploadDialog v-model="showWelcomeDialog" @confirm="handleWelcomeUpload" />
|
||||
|
||||
<!-- 页面标题 -->
|
||||
@@ -27,27 +27,12 @@
|
||||
<ProfilePageContent
|
||||
:profile="profile"
|
||||
@edit="handleEdit"
|
||||
@save="handleInlineSave"
|
||||
@exp-update="handleExpUpdate"
|
||||
@exp-add="handleExpAdd"
|
||||
/>
|
||||
|
||||
<!-- 右侧入口 -->
|
||||
<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>
|
||||
@@ -658,4 +643,71 @@ function goToJobs() {
|
||||
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('添加失败')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
+73
-79
@@ -25,7 +25,6 @@
|
||||
<th class="resume-page__th">简历</th>
|
||||
<th class="resume-page__th">目标岗位</th>
|
||||
<th class="resume-page__th">最近修改</th>
|
||||
<th class="resume-page__th">创建时间</th>
|
||||
<th class="resume-page__th resume-page__th--action"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -38,38 +37,39 @@
|
||||
>
|
||||
<td class="resume-page__td">
|
||||
<div class="resume-page__name-cell">
|
||||
<span class="resume-page__avatar" :style="{ background: item.avatarColor }">
|
||||
{{ item.avatarLetter }}
|
||||
</span>
|
||||
<!-- <span class="resume-page__avatar" :style="{ background: item.avatarColor }">-->
|
||||
<!-- {{ item.avatarLetter }}-->
|
||||
<!-- </span>-->
|
||||
<span class="resume-page__name">{{ item.name }}</span>
|
||||
<span v-if="item.isDefault" class="resume-page__default-tag">默认</span>
|
||||
<!-- 编辑名称岗位图标 -->
|
||||
<button
|
||||
class="resume-page__edit-btn"
|
||||
aria-label="编辑名称岗位"
|
||||
@click.stop="handleEditName(item)"
|
||||
>
|
||||
<el-icon class="resume-page__edit-icon"><EditPen /></el-icon>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="resume-page__td">{{ item.targetJob }}</td>
|
||||
<td class="resume-page__td">{{ item.updatedAt }}</td>
|
||||
<td class="resume-page__td">{{ item.createdAt }}</td>
|
||||
<!-- 操作按钮列 -->
|
||||
<td class="resume-page__td resume-page__td--action">
|
||||
<button
|
||||
class="resume-page__more-btn"
|
||||
aria-label="更多操作"
|
||||
@click.stop="toggleMenu(item.id)"
|
||||
>
|
||||
<svg viewBox="0 0 16 16" fill="currentColor" class="resume-page__more-svg">
|
||||
<circle cx="3" cy="8" r="1.5"/>
|
||||
<circle cx="8" cy="8" r="1.5"/>
|
||||
<circle cx="13" cy="8" r="1.5"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- 弹出菜单 -->
|
||||
<div v-if="activeMenuId === item.id" class="resume-page__popup" @click.stop>
|
||||
<div
|
||||
v-for="action in popupActions"
|
||||
:key="action"
|
||||
class="resume-page__popup-item"
|
||||
@click="handleAction(action, item.id)"
|
||||
>
|
||||
{{ action }}
|
||||
</div>
|
||||
<div class="resume-page__actions">
|
||||
<button
|
||||
v-if="!item.isDefault"
|
||||
class="resume-page__action-btn"
|
||||
@click.stop="handleSetDefault(item.id)"
|
||||
>设为默认</button>
|
||||
<button
|
||||
class="resume-page__action-btn"
|
||||
@click.stop="handleExport(item)"
|
||||
>导出</button>
|
||||
<button
|
||||
class="resume-page__action-btn resume-page__action-btn--delete"
|
||||
@click.stop="handleDelete(item.id)"
|
||||
>删除</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -104,13 +104,14 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { EditPen } from '@element-plus/icons-vue'
|
||||
import SideNav from '@/components/SideNav.vue'
|
||||
import ResumeEditNameDialog from '@/components/ResumeEditNameDialog.vue'
|
||||
import ResumeExportDialog from '@/components/ResumeExportDialog.vue'
|
||||
import ResumeUploadDialog from '@/components/ResumeUploadDialog.vue'
|
||||
import { uploadResume } from '@/utils/aiRequest'
|
||||
import {
|
||||
fetchResumeList, deleteResume, type ResumeListItem,
|
||||
fetchResumeList, deleteResume, setDefaultResume, type ResumeListItem,
|
||||
} from '@/api/resume'
|
||||
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
|
||||
// 命令式调用的组件,按需引入插件不会自动加载其样式,需手动引入
|
||||
@@ -203,9 +204,6 @@ onMounted(() => {
|
||||
|
||||
// ==================== 页面状态 ====================
|
||||
|
||||
/** 当前打开弹出菜单的简历 ID */
|
||||
const activeMenuId = ref<string | null>(null)
|
||||
|
||||
// ==================== 编辑简历名称弹窗状态 ====================
|
||||
|
||||
/** 编辑弹窗是否可见 */
|
||||
@@ -231,61 +229,57 @@ const exportResumeName = ref('')
|
||||
/** 上传弹窗是否可见 */
|
||||
const uploadDialogVisible = ref(false)
|
||||
|
||||
/** 弹出菜单操作项 */
|
||||
const popupActions = ['设为默认简历', '编辑名称岗位', '导出简历', '删除']
|
||||
|
||||
// ==================== 事件处理 ====================
|
||||
|
||||
/** 切换弹出菜单的显示/隐藏 */
|
||||
function toggleMenu(id: string) {
|
||||
activeMenuId.value = activeMenuId.value === id ? null : id
|
||||
/** 点击编辑图标 — 打开编辑名称岗位弹窗 */
|
||||
function handleEditName(item: ResumeItem) {
|
||||
editResumeId.value = item.id
|
||||
editResumeName.value = item.name
|
||||
editTargetPosition.value = item.targetJob
|
||||
editNameVisible.value = true
|
||||
}
|
||||
|
||||
/** 弹出菜单操作点击 */
|
||||
async function handleAction(action: string, id: string) {
|
||||
activeMenuId.value = null
|
||||
|
||||
if (action === '删除') {
|
||||
// 二次确认删除
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除这份简历吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
|
||||
// 调用删除接口
|
||||
const res = await deleteResume(id)
|
||||
if (res.code === '0') {
|
||||
ElMessage.success('删除成功')
|
||||
// 刷新列表
|
||||
loadResumeList()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
// 用户取消删除或接口报错
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败,请稍后重试')
|
||||
}
|
||||
/** 设为默认简历 */
|
||||
async function handleSetDefault(id: string) {
|
||||
try {
|
||||
const res = await setDefaultResume(id)
|
||||
if (res.code === '0') {
|
||||
ElMessage.success('已设为默认简历')
|
||||
loadResumeList()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '设置失败')
|
||||
}
|
||||
} else if (action === '编辑名称岗位') {
|
||||
// 找到当前简历数据,打开编辑弹窗
|
||||
const target = resumeList.value.find(r => r.id === id)
|
||||
if (target) {
|
||||
editResumeId.value = id
|
||||
editResumeName.value = target.name
|
||||
editTargetPosition.value = target.targetJob
|
||||
editNameVisible.value = true
|
||||
} catch {
|
||||
ElMessage.error('设置失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
/** 导出简历 */
|
||||
function handleExport(item: ResumeItem) {
|
||||
exportResumeId.value = item.id
|
||||
exportResumeName.value = item.name || '简历'
|
||||
exportDialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 删除简历 */
|
||||
async function handleDelete(id: string) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除这份简历吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
const res = await deleteResume(id)
|
||||
if (res.code === '0') {
|
||||
ElMessage.success('删除成功')
|
||||
loadResumeList()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败,请稍后重试')
|
||||
}
|
||||
} else if (action === '导出简历') {
|
||||
// 打开导出格式选择弹窗
|
||||
exportResumeId.value = id
|
||||
const target = resumeList.value.find(r => r.id === id)
|
||||
exportResumeName.value = target?.name || '简历'
|
||||
exportDialogVisible.value = true
|
||||
} else {
|
||||
console.log(action, id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+644
-285
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user