AI助手和Nova助手
This commit is contained in:
@@ -286,9 +286,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- AI正在回复的加载指示器 -->
|
||||
<div v-if="aiLoading" class="job-resume-custom-dialog__ai-msg job-resume-custom-dialog__ai-msg--ai">
|
||||
<div class="job-resume-custom-dialog__ai-msg-bubble job-resume-custom-dialog__ai-msg-bubble--loading">AI正在思考中...</div>
|
||||
</div>
|
||||
<AiThinkingIndicator v-if="aiLoading" text="AI正在思考中" />
|
||||
</div>
|
||||
<!-- AI输入框 -->
|
||||
<div class="job-resume-custom-dialog__ai-input-area">
|
||||
@@ -307,7 +305,7 @@
|
||||
</div>
|
||||
<!-- 编辑内容 — 折叠手风琴式编辑面板 -->
|
||||
<div v-if="previewTab === 'edit'" class="job-resume-custom-dialog__preview-edit">
|
||||
<JobResumeCustomEditPanel :resumeData="customResumeRawData" @update="onEditPanelUpdate" />
|
||||
<JobResumeCustomEditPanel :resumeData="customResumeRawData" :jobId="jobId" @update="onEditPanelUpdate" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -318,7 +316,7 @@
|
||||
<button class="job-resume-custom-dialog__primary-btn" @click="handleDrawerNext">立即定制简历</button>
|
||||
</div>
|
||||
<!-- 步骤四专属底部:下载简历 + 立即去投递 -->
|
||||
<div v-if="currentStep === 4" class="job-resume-custom-dialog__preview-footer">
|
||||
<div v-if="currentStep === 4" class="job-resume-custom-dialog__preview-footer mt10 pt30">
|
||||
<!-- 左侧:下载简历按钮(带下拉) -->
|
||||
<div class="job-resume-custom-dialog__download-wrap">
|
||||
<button class="job-resume-custom-dialog__download-btn" @click="toggleDownloadMenu">下载简历</button>
|
||||
@@ -347,14 +345,15 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, nextTick, watch } from 'vue'
|
||||
import html2pdf from 'html2pdf.js'
|
||||
import JobResumeTemplate from '@/components/JobResumeTemplate.vue'
|
||||
import JobResumeCustomEditPanel from '@/components/JobResumeCustomEditPanel.vue'
|
||||
import type { ResumeTemplateData } from '@/components/JobResumeTemplate.vue'
|
||||
import { exportResumePdf, exportResumeWord } from '@/utils/resumeExport'
|
||||
import { fetchResumeList } from '@/api/resume'
|
||||
import type { ResumeListItem } from '@/api/resume'
|
||||
import { fetchCustomizeResume, generateCustomizeResume, aiEditResume, rollbackCustomizeResume } from '@/api/jobs'
|
||||
import type { CustomizeResumeData, AiEditChatMessage } from '@/api/jobs'
|
||||
import AiThinkingIndicator from '@/components/tools/AiThinkingIndicator.vue'
|
||||
|
||||
// ==================== 类型定义 ====================
|
||||
|
||||
@@ -458,7 +457,7 @@ async function fetchAndLoadCustomResume() {
|
||||
})
|
||||
try {
|
||||
// 第一步:查询是否已有定制简历
|
||||
let queryRes = await fetchCustomizeResume()
|
||||
let queryRes = await fetchCustomizeResume(props.jobId)
|
||||
// if (queryRes.code === 0 && queryRes.data) {
|
||||
// // 已有定制简历,直接填充数据并跳转预览
|
||||
// fillCustomResumeData(queryRes.data)
|
||||
@@ -480,7 +479,7 @@ async function fetchAndLoadCustomResume() {
|
||||
}
|
||||
|
||||
// 第三步:生成成功后再次查询获取简历数据
|
||||
queryRes = await fetchCustomizeResume()
|
||||
queryRes = await fetchCustomizeResume(props.jobId)
|
||||
if (queryRes.code === 0 && queryRes.data) {
|
||||
fillCustomResumeData(queryRes.data)
|
||||
currentStep.value = 4
|
||||
@@ -845,7 +844,7 @@ async function sendAiMessage(text: string) {
|
||||
oldResumeTemplateData.value = JSON.parse(JSON.stringify(resumeTemplateData.value))
|
||||
|
||||
// 重新查询定制简历数据来刷新简历预览
|
||||
const queryRes = await fetchCustomizeResume()
|
||||
const queryRes = await fetchCustomizeResume(props.jobId)
|
||||
if (queryRes.code === 0 && queryRes.data) {
|
||||
fillCustomResumeData(queryRes.data)
|
||||
// 开启差异对比模式
|
||||
@@ -894,14 +893,14 @@ async function confirmRollback() {
|
||||
if (idx < 0) return
|
||||
|
||||
try {
|
||||
const res = await rollbackCustomizeResume()
|
||||
const res = await rollbackCustomizeResume(props.jobId)
|
||||
if (res.code === 0) {
|
||||
// 标记该消息为已撤销
|
||||
aiMessages.value[idx].rollbackStatus = 'done'
|
||||
// 关闭差异对比模式
|
||||
isShowDiff.value = false
|
||||
// 重新查询简历数据刷新预览
|
||||
const queryRes = await fetchCustomizeResume()
|
||||
const queryRes = await fetchCustomizeResume(props.jobId)
|
||||
if (queryRes.code === 0 && queryRes.data) {
|
||||
fillCustomResumeData(queryRes.data)
|
||||
}
|
||||
@@ -929,78 +928,22 @@ function toggleDownloadMenu() {
|
||||
async function handleDownload(type: 'pdf' | 'word') {
|
||||
showDownloadMenu.value = false
|
||||
|
||||
if (type === 'pdf') {
|
||||
// 通过 JobResumeTemplate 组件暴露的 resumeRef 获取简历DOM
|
||||
const element = resumeTemplateRef.value?.resumeRef
|
||||
if (!element) {
|
||||
console.error('[下载简历] 无法获取简历模板DOM')
|
||||
return
|
||||
}
|
||||
const element = resumeTemplateRef.value?.resumeRef
|
||||
if (!element) {
|
||||
console.error('[下载简历] 无法获取简历模板DOM')
|
||||
return
|
||||
}
|
||||
|
||||
// html2pdf 配置选项
|
||||
const options = {
|
||||
margin: [10, 10, 10, 10] as [number, number, number, number],
|
||||
filename: `${resumeTemplateData.value.name || '简历'}_定制简历.pdf`,
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: { scale: 2, useCORS: true, logging: false },
|
||||
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' as const },
|
||||
}
|
||||
const fileName = (resumeTemplateData.value.name || '简历') + '_定制简历'
|
||||
|
||||
try {
|
||||
await html2pdf().set(options).from(element).save()
|
||||
} catch (err) {
|
||||
console.error('[下载简历] PDF生成失败', err)
|
||||
}
|
||||
} else {
|
||||
// 将简历HTML转为Word文档并下载(使用HTML格式的.doc文件,Word可正常打开)
|
||||
const element = resumeTemplateRef.value?.resumeRef
|
||||
if (!element) {
|
||||
console.error('[下载简历] 无法获取简历模板DOM')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取页面样式表内容
|
||||
const styleSheets = Array.from(document.styleSheets)
|
||||
let cssText = ''
|
||||
styleSheets.forEach((sheet) => {
|
||||
try {
|
||||
Array.from(sheet.cssRules).forEach((rule) => {
|
||||
cssText += rule.cssText + '\n'
|
||||
})
|
||||
} catch {
|
||||
// 跨域样式表无法读取,跳过
|
||||
}
|
||||
})
|
||||
|
||||
// 组装完整HTML文档(Word可识别的HTML格式)
|
||||
const fullHtml = `
|
||||
<html xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||
xmlns:w="urn:schemas-microsoft-com:office:word"
|
||||
xmlns="http://www.w3.org/TR/REC-html40">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="ProgId" content="Word.Document">
|
||||
<meta name="Generator" content="Microsoft Word 15">
|
||||
<style>${cssText}</style>
|
||||
</head>
|
||||
<body>${element.outerHTML}</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// 生成Blob并触发下载
|
||||
const blob = new Blob([fullHtml], { type: 'application/msword' })
|
||||
const fileName = `${resumeTemplateData.value.name || '简历'}_定制简历.doc`
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = fileName
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
URL.revokeObjectURL(link.href)
|
||||
} catch (err) {
|
||||
console.error('[下载简历] Word生成失败', err)
|
||||
try {
|
||||
if (type === 'pdf') {
|
||||
await exportResumePdf(element, fileName)
|
||||
} else {
|
||||
exportResumeWord(element, fileName)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[下载简历] 导出失败', err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user