个人资料,简历
This commit is contained in:
+103
-24
@@ -5,12 +5,21 @@
|
||||
<!-- 页面标题 + 上传按钮 -->
|
||||
<div class="resume-page__header">
|
||||
<h2 class="resume-page__title">我的简历</h2>
|
||||
<button class="resume-page__upload-btn" @click="handleUpload">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="resume-page__upload-icon">
|
||||
<path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
上传简历
|
||||
</button>
|
||||
<div class="dflex-end">
|
||||
<!-- 从个人资料创建按钮 -->
|
||||
<button class="resume-page__create-btn mr16" :disabled="creatingFromProfile" @click="handleCreateFromProfile">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="resume-page__upload-icon">
|
||||
<path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
从个人资料创建
|
||||
</button>
|
||||
<button class="resume-page__upload-btn" @click="handleUpload">
|
||||
<svg viewBox="0 0 16 16" fill="none" class="resume-page__upload-icon">
|
||||
<path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
上传简历
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 简历表格 -->
|
||||
@@ -39,14 +48,6 @@
|
||||
<div class="resume-page__name-cell">
|
||||
<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>
|
||||
@@ -54,6 +55,16 @@
|
||||
<!-- 操作按钮列 -->
|
||||
<td class="resume-page__td resume-page__td--action">
|
||||
<div class="resume-page__actions">
|
||||
<button
|
||||
class="resume-page__action-btn"
|
||||
@click.stop="handleEditName(item)"
|
||||
>
|
||||
<svg width="12" height="12" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0523 1.82016C11.7781 1.54295 11.4366 1.34358 11.062 1.24212C10.6875 1.14065 10.2931 1.14065 9.91851 1.24212C9.54396 1.34358 9.2024 1.54295 8.92822 1.82016L8.29348 2.46298C8.2617 2.4886 8.23269 2.51753 8.20693 2.54932L1.90565 8.92043C1.82508 9.00168 1.77008 9.10517 1.74754 9.21793L1.16589 12.1346C1.14691 12.2288 1.1513 12.3264 1.17863 12.4185C1.20598 12.5107 1.25544 12.5945 1.32261 12.6627C1.38979 12.7308 1.47258 12.7811 1.56364 12.809C1.65458 12.837 1.75127 12.8417 1.84449 12.8229L4.7343 12.2396C4.84585 12.2168 4.94823 12.1612 5.02859 12.0797L12.0523 4.97947C12.3265 4.70229 12.5237 4.35703 12.6241 3.97838C12.7245 3.59974 12.7245 3.20105 12.6241 2.8224C12.5237 2.44375 12.3265 2.09849 12.0523 1.82133" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.3353 11.1303L2.46814 11.5083L2.84319 9.62298L8.65699 3.74536L10.1491 5.25385L4.3353 11.1303ZM9.7439 2.64628C9.8742 2.51131 10.0376 2.41368 10.2174 2.36336C10.3972 2.31304 10.587 2.31183 10.7675 2.35985C10.9479 2.40787 11.1125 2.5034 11.2445 2.63669C11.3765 2.76999 11.4711 2.93629 11.5187 3.11863C11.5664 3.30096 11.5653 3.4928 11.5157 3.67459C11.466 3.85638 11.3696 4.0216 11.2362 4.15341L10.9661 4.42871L9.47384 2.91925L9.7439 2.64628Z" fill="white"/>
|
||||
</svg>
|
||||
<span class="fs12 color-middle ml3 color-dark-ho">修改简历信息</span>
|
||||
</button>
|
||||
<button
|
||||
v-if="!item.isDefault"
|
||||
class="resume-page__action-btn"
|
||||
@@ -97,6 +108,17 @@
|
||||
/>
|
||||
<!-- 全屏加载遮罩 -->
|
||||
<FullscreenLoading :visible="fullLoading" :text="fullLoadingText" title="Nova 正在帮您努力处理~" />
|
||||
<!-- 简历解析步骤进度遮罩 -->
|
||||
<StepProgressOverlay
|
||||
v-if="showUploadProgress"
|
||||
:title="uploadProgressTitle"
|
||||
:subtitle="uploadProgressSubtitle"
|
||||
:steps="uploadProgressSteps"
|
||||
:durations="uploadProgressDurations"
|
||||
:done="uploadProgressDone"
|
||||
@finished="handleUploadProgressFinished"
|
||||
@close="handleUploadProgressClose"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -110,12 +132,13 @@ import ResumeExportDialog from '@/components/ResumeExportDialog.vue'
|
||||
import ResumeUploadDialog from '@/components/ResumeUploadDialog.vue'
|
||||
import { uploadResume } from '@/utils/aiRequest'
|
||||
import {
|
||||
fetchResumeList, deleteResume, setDefaultResume, type ResumeListItem,
|
||||
fetchResumeList, deleteResume, setDefaultResume, createResumeFromProfile, type ResumeListItem,
|
||||
} from '@/api/resume'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
// 命令式调用的组件,按需引入插件不会自动加载其样式,需手动引入
|
||||
import 'element-plus/es/components/message-box/style/css'
|
||||
import FullscreenLoading from '@/components/FullscreenLoading.vue'
|
||||
import StepProgressOverlay from '@/components/StepProgressOverlay.vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -207,6 +230,30 @@ onMounted(() => {
|
||||
loadResumeList()
|
||||
})
|
||||
|
||||
// ==================== 从个人资料创建简历 ====================
|
||||
|
||||
/** 防抖锁:防止多次点击 */
|
||||
const creatingFromProfile = ref(false)
|
||||
|
||||
/**
|
||||
* 从个人资料创建简历(带防抖)
|
||||
*/
|
||||
async function handleCreateFromProfile() {
|
||||
if (creatingFromProfile.value) return
|
||||
creatingFromProfile.value = true
|
||||
try {
|
||||
const res = await createResumeFromProfile()
|
||||
if (res.code === '0') {
|
||||
ElMessage.success('创建成功')
|
||||
await loadResumeList()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('从个人资料创建简历失败', e)
|
||||
} finally {
|
||||
creatingFromProfile.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 页面状态 ====================
|
||||
|
||||
// ==================== 编辑简历名称弹窗状态 ====================
|
||||
@@ -301,29 +348,61 @@ function handleUpload() {
|
||||
|
||||
/** 上传弹窗确认回调 — 接收 File 对象,调用接口上传 */
|
||||
async function handleUploadConfirm(file: File) {
|
||||
// 全屏加载提示,AI 接口响应较慢
|
||||
fullLoadingText.value = '简历解析中,请耐心等待…'
|
||||
fullLoading.value = true
|
||||
// 显示步骤进度遮罩
|
||||
showUploadProgress.value = true
|
||||
uploadProgressDone.value = false
|
||||
pendingResumeId.value = ''
|
||||
|
||||
try {
|
||||
const res = await uploadResume(file)
|
||||
if (res.code === 0) {
|
||||
// 上传成功,刷新列表
|
||||
loadResumeList()
|
||||
// 等待让后端异步处理数据,再关闭加载动画并跳转详情页
|
||||
await new Promise(resolve => setTimeout(resolve, 2000))
|
||||
fullLoading.value = false
|
||||
goDetail(res.data.resumeId)
|
||||
// 缓存简历ID,等进度走完后跳转
|
||||
pendingResumeId.value = res.data.resumeId
|
||||
// 通知进度组件接口已完成
|
||||
uploadProgressDone.value = true
|
||||
} else {
|
||||
fullLoading.value = false
|
||||
showUploadProgress.value = false
|
||||
ElMessage.error(res.msg || '上传失败')
|
||||
}
|
||||
} catch {
|
||||
fullLoading.value = false
|
||||
showUploadProgress.value = false
|
||||
ElMessage.error('上传失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 简历解析步骤进度遮罩 ====================
|
||||
|
||||
/** 解析步骤进度遮罩是否显示 */
|
||||
const showUploadProgress = ref(false)
|
||||
/** 解析接口是否已完成 */
|
||||
const uploadProgressDone = ref(false)
|
||||
/** 大标题 */
|
||||
const uploadProgressTitle = '正在解析简历'
|
||||
/** 副标题 */
|
||||
const uploadProgressSubtitle = '正在识别教育背景、工作经历与技能关键词'
|
||||
/** 4个步骤名称 */
|
||||
const uploadProgressSteps = ['教育背景解析...', '工作经历解析...', '技能特长解析...', '个人资料最终确认']
|
||||
/** 每步时长4600毫秒 */
|
||||
const uploadProgressDurations = [4200, 4200, 4200, 4200]
|
||||
/** 缓存的简历ID(等进度走完后跳转) */
|
||||
const pendingResumeId = ref('')
|
||||
|
||||
/** 解析进度走完后跳转详情页 */
|
||||
function handleUploadProgressFinished() {
|
||||
showUploadProgress.value = false
|
||||
if (pendingResumeId.value) {
|
||||
goDetail(pendingResumeId.value)
|
||||
pendingResumeId.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
/** 关闭解析进度遮罩 */
|
||||
function handleUploadProgressClose() {
|
||||
showUploadProgress.value = false
|
||||
}
|
||||
|
||||
/** 跳转到简历详情页 */
|
||||
function goDetail(id: string) {
|
||||
router.push(`/resume/${id}`)
|
||||
|
||||
Reference in New Issue
Block a user