// @ts-nocheck export const EMP_RE = /emp_[a-z0-9]+/i; const CN_NUM_MAP = { '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10, }; const INDEX_RE = /(?:第\s*|选\s*|选第\s*)?([一二三四五六七八九十\d]+)\s*[号个]?\s*/; export function validateCandidateSelection(aiResponse, candidates) { if (!aiResponse || typeof aiResponse !== 'string') { return { valid: false, reason: 'NO_AI_RESPONSE' }; } if (!Array.isArray(candidates) || candidates.length === 0) { return { valid: false, reason: 'NO_CANDIDATES' }; } const validIds = candidates .map(c => (typeof c === 'string' ? c : c?.employeeId)) .filter(Boolean) .map(id => id.toLowerCase()); const empMatch = aiResponse.match(EMP_RE); if (empMatch) { const empId = empMatch[0].toLowerCase(); if (validIds.includes(empId)) { return { valid: true, employeeId: empId }; } return { valid: false, reason: 'EMP_NOT_IN_CANDIDATES', attempted: empId, validIds, }; } const numMatch = aiResponse.match(INDEX_RE); if (numMatch) { const raw = numMatch[1]; const idx = /^\d+$/.test(raw) ? parseInt(raw, 10) : CN_NUM_MAP[raw]; if (idx == null) { return { valid: false, reason: 'UNRECOGNIZED_FORMAT' }; } if (idx >= 1 && idx <= validIds.length) { return { valid: true, employeeId: validIds[idx - 1] }; } return { valid: false, reason: 'INDEX_OUT_OF_RANGE', index: idx, total: validIds.length, }; } return { valid: false, reason: 'UNRECOGNIZED_FORMAT' }; } export function formatValidationFailure(result) { if (!result || result.valid) return ''; switch (result.reason) { case 'INDEX_OUT_OF_RANGE': return `序号 ${result.index} 越界(共 ${result.total} 个候选)。请用户从 1-${result.total} 中选择,或在候选表里指出特征(如「乘务二组那个」)。`; case 'EMP_NOT_IN_CANDIDATES': return `引用的员工 ID「${result.attempted}」不在当前候选列表内。请用户从候选列表中重新选择(候选:${result.validIds?.join(', ')})。`; case 'UNRECOGNIZED_FORMAT': return `未识别用户的选择。请用户回复「序号」(如「1 号」),或直接说班组/岗位特征(如「乘务二组那个」)。`; case 'NO_CANDIDATES': return `当前没有候选列表,请用户先重新发起查询。`; case 'NO_AI_RESPONSE': return `AI 回复为空,无法识别选择。`; default: return `选择无效,请用户重新选择。`; } }