Files
prop-ai-hr/mobile-uni/src/services/candidate.ts
T

120 lines
3.5 KiB
TypeScript

import type {
CandidateMaterial,
CandidateSelectedFile,
InterviewFinishResponse,
InterviewRecord,
InterviewStartResponse
} from '@/types/api';
import { apiRequest, apiUrl, authHeaders, readTextPayload } from './api';
import { getAuth } from './auth';
const materialExtensions = ['.pdf', '.doc', '.docx', '.jpg', '.jpeg', '.png', '.webp'];
export const getCandidateId = () => {
const phone = getAuth().phone.trim();
if (!phone) {
throw new Error('请先登录后再查看候选人进度');
}
return phone;
};
export const getCandidateName = () => {
const phone = getAuth().phone.trim();
return phone ? `候选人${phone.slice(-4)}` : '候选人';
};
export const getCandidateMaterials = () =>
apiRequest<CandidateMaterial[]>({
url: `/api/aihr/mobile/candidate/materials?candidateId=${encodeURIComponent(getCandidateId())}`,
method: 'GET',
timeout: 15000
});
export const getCandidateInterviewRecords = () =>
apiRequest<InterviewRecord[]>({
url: `/api/recruit/interview/records?limit=5&candidateId=${encodeURIComponent(getCandidateId())}`,
method: 'GET',
timeout: 15000
});
export const chooseCandidateFile = () =>
new Promise<CandidateSelectedFile>((resolve, reject) => {
uni.chooseFile({
count: 1,
type: 'all',
extension: materialExtensions,
success: (result) => {
const tempFiles = Array.isArray(result.tempFiles) ? result.tempFiles : [];
const file = (tempFiles[0] || {}) as Partial<CandidateSelectedFile>;
const path = file.path || result.tempFilePaths?.[0] || '';
if (!path) {
reject(new Error('未获取到文件路径'));
return;
}
resolve({
path,
name: file.name || path.split('/').pop() || 'candidate-material',
size: Number(file.size || 0)
});
},
fail: () => reject(new Error('未选择文件'))
});
});
export const uploadCandidateMaterial = (file: CandidateSelectedFile, materialType = '补充资料') =>
new Promise<CandidateMaterial>((resolve, reject) => {
uni.uploadFile({
url: apiUrl('/api/aihr/mobile/candidate/materials'),
filePath: file.path,
name: 'file',
header: authHeaders(false),
formData: {
candidateId: getCandidateId(),
candidateName: getCandidateName(),
materialType
},
success: (response) => {
try {
resolve(readTextPayload<CandidateMaterial>(response.statusCode, response.data));
} catch (error) {
reject(error);
}
},
fail: () => reject(new Error('资料上传失败'))
});
});
export const startCandidateInterview = () =>
apiRequest<InterviewStartResponse>({
url: '/api/recruit/interview/start',
method: 'POST',
data: {
candidateId: getCandidateId(),
candidateName: getCandidateName(),
positionCode: 'customer-service',
mode: 'mobile'
},
timeout: 30000
});
export const saveInterviewAnswer = (
sessionId: string,
questionId: string,
answerText: string,
answerAudioOssId?: number
) =>
apiRequest<void>({
url: '/api/recruit/interview/answer',
method: 'POST',
data: { sessionId, questionId, answerText, answerAudioOssId },
timeout: 30000
});
export const finishCandidateInterview = (sessionId: string, answers: Record<string, string>) =>
apiRequest<InterviewFinishResponse>({
url: '/api/recruit/interview/finish',
method: 'POST',
data: { sessionId, answers },
timeout: 45000
});