Files
offerpai_web/src/api/resume.ts
T
2026-05-06 15:07:44 +08:00

705 lines
18 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import request from '@/utils/request'
import aiService from '@/utils/aiRequest'
import type { ApiResult } from '@/api/auth'
import type { AiResult } from '@/utils/aiRequest'
// ==================== 简历列表相关 ====================
/** 时间戳结构(Instant */
export interface InstantTime {
/** 秒级时间戳 */
seconds?: number
/** 纳秒部分 */
nanos?: number
}
/** 简历列表项 */
export interface ResumeListItem {
/** 简历 ID(字符串,避免大整数精度丢失) */
id?: string
/** 简历名称 */
resumeName?: string
/** 目标岗位 */
targetPosition?: string
/** 是否默认简历 0=否 1=是 */
isDefault?: number
/** 简历修改时间(毫秒时间戳) */
updateTime?: number
/** 简历创建时间(毫秒时间戳) */
createTime?: number
}
/**
* 获取简历列表
* GET /resume/list
*/
export function fetchResumeList() {
return request.get<any, ApiResult<ResumeListItem[]>>('/resume/list')
}
// ==================== 描述段落(通用) ====================
/** 描述段落 */
export interface DescriptionParagraph {
/** 段落标识,前端生成的短ID */
id?: string
/** 段落文本内容 */
text?: string
}
// ==================== 简历主表 ====================
/** 简历主表数据 */
export interface ResumeMainData {
/** 简历 ID(字符串,避免大整数精度丢失) */
id?: string
/** 简历名称 */
resumeName?: string
/** 目标岗位 */
targetPosition?: string
/** 是否默认简历 0=否 1=是 */
isDefault?: number
/** 头像URL */
avatarUrl?: string
/** 真实姓名 */
name?: string
/** 邮箱 */
email?: string
/** 手机号码 */
mobileNumber?: string
/** 所在城市 */
city?: string
/** 微信号 */
wechatNumber?: string
/** 作品集链接 */
portfolioUrl?: string
/** 技能标签列表 */
skills?: string[]
/** 证书标签列表 */
certificates?: string[]
/** 个人概述 */
summary?: string
}
/**
* 查询简历主表
* GET /resume?resumeId=xxx
*/
export function fetchResumeMain(resumeId: string) {
return request.get<any, ApiResult<ResumeMainData>>('/resume', {
params: { resumeId },
})
}
// ==================== 教育经历 ====================
/** 教育经历项 */
export interface ResumeEducation {
/** ID(字符串,避免大整数精度丢失) */
id?: string
/** 学校名称 */
school?: string
/** 专业 */
major?: string
/** 学历:大专/本科/硕士/博士 */
degree?: string
/** 学习形式:全日制/非全日制 */
studyType?: string
/** 开始时间,格式:2023.09 */
startDate?: string
/** 结束时间,格式:2024.06 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 查询简历的教育经历列表
* GET /resume/education?resumeId=xxx
*/
export function fetchResumeEducation(resumeId: string) {
return request.get<any, ApiResult<ResumeEducation[]>>('/resume/education', {
params: { resumeId },
})
}
// ==================== 工作经历 ====================
/** 工作经历项 */
export interface ResumeWork {
/** ID(字符串,避免大整数精度丢失) */
id?: string
/** 公司名称 */
companyName?: string
/** 职位 */
position?: string
/** 开始时间 */
startDate?: string
/** 结束时间 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 查询简历的工作经历列表
* GET /resume/work?resumeId=xxx
*/
export function fetchResumeWork(resumeId: string) {
return request.get<any, ApiResult<ResumeWork[]>>('/resume/work', {
params: { resumeId },
})
}
// ==================== 实习经历 ====================
/** 实习经历项 */
export interface ResumeInternship {
/** ID(字符串,避免大整数精度丢失) */
id?: string
/** 公司名称 */
companyName?: string
/** 职位 */
position?: string
/** 开始时间 */
startDate?: string
/** 结束时间 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 查询简历的实习经历列表
* GET /resume/internship?resumeId=xxx
*/
export function fetchResumeInternship(resumeId: string) {
return request.get<any, ApiResult<ResumeInternship[]>>('/resume/internship', {
params: { resumeId },
})
}
// ==================== 项目经历 ====================
/** 项目经历项 */
export interface ResumeProject {
/** ID(字符串,避免大整数精度丢失) */
id?: string
/** 所属公司 */
companyName?: string
/** 项目名称 */
projectName?: string
/** 担任角色 */
role?: string
/** 开始时间 */
startDate?: string
/** 结束时间 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 查询简历的项目经历列表
* GET /resume/project?resumeId=xxx
*/
export function fetchResumeProject(resumeId: string) {
return request.get<any, ApiResult<ResumeProject[]>>('/resume/project', {
params: { resumeId },
})
}
// ==================== 竞赛经历 ====================
/** 竞赛经历项 */
export interface ResumeCompetition {
/** ID(字符串,避免大整数精度丢失) */
id?: string
/** 竞赛名称 */
competitionName?: string
/** 获奖情况 */
award?: string
/** 获奖时间,格式:2023.07 */
awardDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 查询简历的竞赛经历列表
* GET /resume/competition?resumeId=xxx
*/
export function fetchResumeCompetition(resumeId: string) {
return request.get<any, ApiResult<ResumeCompetition[]>>('/resume/competition', {
params: { resumeId },
})
}
// ==================== 简历保存相关 ====================
/** 保存简历主表参数 */
export interface SaveResumeMainParams {
/** 简历 ID */
resumeId: string
/** 简历名称 */
resumeName?: string
/** 目标岗位 */
targetPosition?: string
/** 真实姓名 */
name?: string
/** 邮箱 */
email?: string
/** 手机号码 */
mobileNumber?: string
/** 所在城市 */
city?: string
/** 微信号 */
wechatNumber?: string
/** 作品集链接 */
portfolioUrl?: string
/** 技能标签列表 */
skills?: string[]
/** 证书标签列表 */
certificates?: string[]
/** 个人概述 */
summary?: string
}
/**
* 保存/更新简历主表信息
* POST /resume
*/
export function saveResumeMain(data: SaveResumeMainParams) {
return request.post<any, ApiResult>('/resume', data)
}
/** 保存简历教育经历参数(单条) */
export interface SaveResumeEducationItem {
/** 记录ID(编辑时必传) */
id?: string | number
/** 学校名称 */
school?: string
/** 专业 */
major?: string
/** 学历 */
degree?: string
/** 学习形式 */
studyType?: string
/** 开始时间 */
startDate?: string
/** 结束时间 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 保存简历教育经历(全量覆盖)— 旧接口,保留兼容
* POST /resume/education
*/
export function saveResumeEducation(resumeId: string, data: SaveResumeEducationItem[]) {
return request.post<any, ApiResult>('/resume/education', { resumeId, items: data })
}
/**
* 添加单条教育经历,返回新记录ID
* POST /resume/education/add
*/
export function addResumeEducation(resumeId: string, data: SaveResumeEducationItem) {
return request.post<any, ApiResult<string>>('/resume/education/add', data, {
params: { resumeId },
})
}
/**
* 根据ID编辑单条教育经历
* POST /resume/education/update
*/
export function updateResumeEducation(data: SaveResumeEducationItem) {
return request.post<any, ApiResult>('/resume/education/update', data)
}
/**
* 根据ID删除单条教育经历
* POST /resume/education/delete
*/
export function deleteResumeEducation(id: string) {
return request.post<any, ApiResult>('/resume/education/delete', null, {
params: { id },
})
}
/** 保存简历工作经历参数(单条) */
export interface SaveResumeWorkItem {
/** 记录ID(编辑时必传) */
id?: string | number
/** 公司名称 */
companyName?: string
/** 职位 */
position?: string
/** 开始时间 */
startDate?: string
/** 结束时间 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 保存简历工作经历(全量覆盖)— 旧接口,保留兼容
* POST /resume/work
*/
export function saveResumeWork(resumeId: string, data: SaveResumeWorkItem[]) {
return request.post<any, ApiResult>('/resume/work', { resumeId, items: data })
}
/**
* 添加单条工作经历,返回新记录ID
* POST /resume/work/add
*/
export function addResumeWork(resumeId: string, data: SaveResumeWorkItem) {
return request.post<any, ApiResult<string>>('/resume/work/add', data, {
params: { resumeId },
})
}
/**
* 根据ID编辑单条工作经历
* POST /resume/work/update
*/
export function updateResumeWork(data: SaveResumeWorkItem) {
return request.post<any, ApiResult>('/resume/work/update', data)
}
/**
* 根据ID删除单条工作经历
* POST /resume/work/delete
*/
export function deleteResumeWork(id: string) {
return request.post<any, ApiResult>('/resume/work/delete', null, {
params: { id },
})
}
/**
* 保存简历实习经历(全量覆盖)— 旧接口,保留兼容
* POST /resume/internship
*/
export function saveResumeInternship(resumeId: string, data: SaveResumeWorkItem[]) {
return request.post<any, ApiResult>('/resume/internship', { resumeId, items: data })
}
/**
* 添加单条实习经历,返回新记录ID
* POST /resume/internship/add
*/
export function addResumeInternship(resumeId: string, data: SaveResumeWorkItem) {
return request.post<any, ApiResult<string>>('/resume/internship/add', data, {
params: { resumeId },
})
}
/**
* 根据ID编辑单条实习经历
* POST /resume/internship/update
*/
export function updateResumeInternship(data: SaveResumeWorkItem) {
return request.post<any, ApiResult>('/resume/internship/update', data)
}
/**
* 根据ID删除单条实习经历
* POST /resume/internship/delete
*/
export function deleteResumeInternship(id: string) {
return request.post<any, ApiResult>('/resume/internship/delete', null, {
params: { id },
})
}
/** 保存简历项目经历参数(单条) */
export interface SaveResumeProjectItem {
/** 记录ID(编辑时必传) */
id?: string | number
/** 项目名称 */
projectName?: string
/** 所属公司 */
companyName?: string
/** 担任角色 */
role?: string
/** 开始时间 */
startDate?: string
/** 结束时间 */
endDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 保存简历项目经历(全量覆盖)— 旧接口,保留兼容
* POST /resume/project
*/
export function saveResumeProject(resumeId: string, data: SaveResumeProjectItem[]) {
return request.post<any, ApiResult>('/resume/project', { resumeId, items: data })
}
/**
* 添加单条项目经历,返回新记录ID
* POST /resume/project/add
*/
export function addResumeProject(resumeId: string, data: SaveResumeProjectItem) {
return request.post<any, ApiResult<string>>('/resume/project/add', data, {
params: { resumeId },
})
}
/**
* 根据ID编辑单条项目经历
* POST /resume/project/update
*/
export function updateResumeProject(data: SaveResumeProjectItem) {
return request.post<any, ApiResult>('/resume/project/update', data)
}
/**
* 根据ID删除单条项目经历
* POST /resume/project/delete
*/
export function deleteResumeProject(id: string) {
return request.post<any, ApiResult>('/resume/project/delete', null, {
params: { id },
})
}
/** 保存简历竞赛经历参数(单条) */
export interface SaveResumeCompetitionItem {
/** 记录ID(编辑时必传) */
id?: string | number
/** 竞赛名称 */
competitionName?: string
/** 获奖情况 */
award?: string
/** 获奖时间 */
awardDate?: string
/** 描述段落 */
description?: DescriptionParagraph[]
}
/**
* 保存简历竞赛经历(全量覆盖)— 旧接口,保留兼容
* POST /resume/competition
*/
export function saveResumeCompetition(resumeId: string, data: SaveResumeCompetitionItem[]) {
return request.post<any, ApiResult>('/resume/competition', { resumeId, items: data })
}
/**
* 添加单条竞赛经历,返回新记录ID
* POST /resume/competition/add
*/
export function addResumeCompetition(resumeId: string, data: SaveResumeCompetitionItem) {
return request.post<any, ApiResult<string>>('/resume/competition/add', data, {
params: { resumeId },
})
}
/**
* 根据ID编辑单条竞赛经历
* POST /resume/competition/update
*/
export function updateResumeCompetition(data: SaveResumeCompetitionItem) {
return request.post<any, ApiResult>('/resume/competition/update', data)
}
/**
* 根据ID删除单条竞赛经历
* POST /resume/competition/delete
*/
export function deleteResumeCompetition(id: string) {
return request.post<any, ApiResult>('/resume/competition/delete', null, {
params: { id },
})
}
/**
* 删除简历
* POST /resume/delete
*/
export function deleteResume(resumeId: string) {
return request.post<any, ApiResult>('/resume/delete', null, {
params: { resumeId },
})
}
// ==================== 简历诊断相关 ====================
/** 诊断报告数据 */
export interface DiagnosisReport {
/** 报告 ID */
id?: string
/** 简历 ID */
resumeId?: string
/** 评级 A/B/C/D */
grade?: string
/** AI 整体评价 */
summary?: string
/** 紧急修复总数 */
urgentTotal?: number
/** 重点优化总数 */
importantTotal?: number
/** 表达提升总数 */
expressionTotal?: number
/** 创建时间 */
createTime?: string
}
/** 诊断问题子类型计数 */
export interface IssueSubCounts {
[key: string]: number
}
/** 诊断问题项 */
export interface DiagnosisIssue {
/** 问题 ID */
id?: string
/** 模块类型: summary/education/work/internship/project/competition */
moduleType?: string
/** 模块记录 IDsummary 时为 resume_id */
moduleRecordId?: string
/** 诊断发现 */
finding?: string
/** 为什么重要 */
importance?: string
/** 改进建议 */
suggestion?: string
/** 紧急修复子类型计数 */
urgentIssues?: IssueSubCounts
/** 重点优化子类型计数 */
importantIssues?: IssueSubCounts
/** 表达提升子类型计数 */
expressionIssues?: IssueSubCounts
/** AI 改写后的内容 */
optimizedContent?: any
/** 0=待处理 1=已处理 */
status?: number
/** 0=未评价 1=符合 2=不符合 */
userFeedback?: number
}
/** 诊断接口返回的 data 结构 */
export interface DiagnosisData {
/** 诊断报告 */
report: DiagnosisReport
/** 诊断问题列表 */
issues: DiagnosisIssue[]
}
/**
* 查询简历诊断报告(AI 接口)
* GET /resume/diagnose/{resume_id}
*/
export function fetchResumeDiagnosis(resumeId: string) {
return aiService.get<AiResult<DiagnosisData | null>>(`/resume/diagnose/${resumeId}`, {
transformResponse: [(data: string) => {
try {
// 大整数安全解析
const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"')
return JSON.parse(processed)
} catch {
return data
}
}],
}).then(res => res.data)
}
/** 触发诊断返回的 data 结构 */
export interface TriggerDiagnosisData {
/** 诊断报告 ID */
reportId?: string
}
/**
* 触发简历诊断(AI 接口)
* POST /resume/diagnose
*/
export function triggerResumeDiagnosis(resumeId: string) {
return aiService.post<AiResult<TriggerDiagnosisData>>('/resume/diagnose', { resumeId }, {
transformResponse: [(data: string) => {
try {
const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"')
return JSON.parse(processed)
} catch {
return data
}
}],
}).then(res => res.data)
}
// ==================== 问题润色(AI 优化用户改写内容) ====================
/** 润色接口返回的 data 结构 */
export interface PolishIssueData {
/** AI 润色后的文本段落数组 */
content: string[]
}
/**
* 对诊断问题进行 AI 润色(AI 接口)
* POST /resume/diagnose/issue/{issue_id}/polish
* @param issueId 问题 ID
* @param content 用户编辑后的文本段落数组
*/
export function polishDiagnosisIssue(issueId: string, content: string[]) {
return aiService.post<AiResult<PolishIssueData>>(`/resume/diagnose/issue/${issueId}/polish`, { content }, {
transformResponse: [(data: string) => {
try {
const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"')
return JSON.parse(processed)
} catch {
return data
}
}],
}).then(res => res.data)
}
// ==================== 问题用户评价 ====================
/**
* 提交诊断问题的用户评价(AI 接口)
* PUT /resume/diagnose/issue/{issue_id}/feedback
* @param issueId 问题 ID
* @param userFeedback 1=符合(有用) 2=不符合(无用)
*/
export function feedbackDiagnosisIssue(issueId: string, userFeedback: number) {
return aiService.put<AiResult<null>>(`/resume/diagnose/issue/${issueId}/feedback`, { userFeedback }, {
transformResponse: [(data: string) => {
try {
const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"')
return JSON.parse(processed)
} catch {
return data
}
}],
}).then(res => res.data)
}
// ==================== 标记问题已处理 ====================
/**
* 标记诊断问题为已处理(AI 接口)
* PUT /resume/diagnose/issue/{issue_id}/resolve
* @param issueId 问题 ID
*/
export function resolveDiagnosisIssue(issueId: string) {
return aiService.put<AiResult<null>>(`/resume/diagnose/issue/${issueId}/resolve`, null, {
transformResponse: [(data: string) => {
try {
const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"')
return JSON.parse(processed)
} catch {
return data
}
}],
}).then(res => res.data)
}