diff --git a/web/src/views/hq/answerSurvey/index.vue b/web/src/views/hq/answerSurvey/index.vue index 3801a9ad..7beb13b2 100644 --- a/web/src/views/hq/answerSurvey/index.vue +++ b/web/src/views/hq/answerSurvey/index.vue @@ -256,6 +256,7 @@ :key="option.id || index" :label="String.fromCharCode(65 + index)" class="answer-option-horizontal" + :class="{ 'is-checked': question.userAnswer === String.fromCharCode(65 + index) }" > {{ String.fromCharCode(65 + index) }}. {{ option.optionContent || option.optionText || option.text || option.content || `选项${index + 1}` }} @@ -274,6 +275,7 @@ :key="option.id || index" :label="String.fromCharCode(65 + index)" class="answer-option-horizontal" + :class="{ 'is-checked': Array.isArray(question.userAnswer) && question.userAnswer.includes(String.fromCharCode(65 + index)) }" > {{ String.fromCharCode(65 + index) }}. {{ option.optionContent || option.optionText || option.text || option.content || `选项${index + 1}` }} @@ -289,7 +291,11 @@ placeholder="请输入答案..." disabled class="answer-textarea" - /> + > + + @@ -1016,14 +1022,35 @@ const loadPreviousAnswers = async (surveyId: string | number, formData: Record match.split(':')[1]) : []; + + console.log('从JSON字符串中提取的原始questionId列表:', originalIds); + // 使用 JSON.parse 时配合 reviver 函数处理大整数 - answersData = JSON.parse(jsonStr, (key, value) => { - // 如果是 questionId 字段,确保作为字符串处理 - if (key === 'questionId' && typeof value === 'number') { - return String(value); - } - return value; - }); + answersData = JSON.parse(jsonStr); + + // 解析后直接使用提取的原始ID进行修复 + if (originalIds.length === answersData.length) { + console.log('使用提取的原始ID进行修复,数量匹配'); + answersData.forEach((answer, index) => { + if (index < originalIds.length) { + // 始终将ID作为字符串处理,避免精度丢失 + answer.questionId = String(originalIds[index]); + console.log(`修复第 ${index + 1} 条数据的 questionId: ${answer.questionId}`); + } + }); + } else { + console.warn('ID数量不匹配,尝试其他修复方式'); + + // 备选修复方法:确保所有questionId都是字符串类型 + answersData.forEach((answer) => { + if (answer.questionId) { + answer.questionId = String(answer.questionId); + } + }); + } console.log('成功解析历史答题数据:', answersData); @@ -1031,30 +1058,6 @@ const loadPreviousAnswers = async (surveyId: string | number, formData: Record a.questionId)); console.log('解析后唯一的 questionId 数量:', uniqueIds.size); console.log('唯一的 questionId 列表:', Array.from(uniqueIds)); - - // 如果所有 questionId 都变成相同的,尝试手动修复 - if (uniqueIds.size === 1 && answersData.length > 1) { - console.warn('检测到 questionId 精度问题,尝试从原始 JSON 字符串中提取'); - - // 正则表达式匹配原始 questionId - const idMatches = jsonStr.match(/"questionId":(\d+)/g); - if (idMatches && idMatches.length === answersData.length) { - console.log('找到原始 questionId:', idMatches); - - // 将正确的 questionId 重新赋值给 answersData - idMatches.forEach((match, index) => { - if (index < answersData.length) { - const originalId = match.split(':')[1]; - answersData[index].questionId = originalId; - console.log(`修复第 ${index + 1} 条数据的 questionId: ${originalId}`); - } - }); - - // 再次检查唯一 ID - const fixedUniqueIds = new Set(answersData.map((a) => a.questionId)); - console.log('修复后唯一的 questionId 数量:', fixedUniqueIds.size); - } - } } catch (error) { console.error('解析ANSWERS_DATA失败:', error); return false; @@ -1310,7 +1313,7 @@ const submitAnswer = async () => { // 遍历所有答题数据,构造答案列表 for (const question of answerQuestions.value) { - const questionId = question.questionId || question.id; + const questionId = String(question.questionId || question.id); // 确保questionId是字符串类型 const questionType = String(question.questionType); const userAnswer = answerForm.value[questionId]; @@ -1358,7 +1361,7 @@ const submitAnswer = async () => { const optionLetter = String.fromCharCode(65 + optionIndex); // A, B, C, D... const answerItem: SubmitAnswerItem = { - questionId: questionId, + questionId: String(questionId), // 确保questionId是字符串类型 questionType: questionType, answerValue: '', // 不再使用answerValue字段 optionId: selectedOption.id || selectedOption.optionId, // 确保有选项ID @@ -1409,7 +1412,7 @@ const submitAnswer = async () => { // 创建单独的答案记录 const answerItem: SubmitAnswerItem = { - questionId: questionId, + questionId: String(questionId), // 确保questionId是字符串类型 questionType: questionType, answerValue: '', // 不再使用answerValue字段 optionId: selectedOption.id || selectedOption.optionId, // 确保有选项ID @@ -1436,7 +1439,7 @@ const submitAnswer = async () => { const answerText = userAnswer != null ? String(userAnswer) : ''; const answerItem: SubmitAnswerItem = { - questionId: questionId, + questionId: String(questionId), // 确保questionId是字符串类型 questionType: questionType, answerValue: '', // 不再使用answerValue字段 optionId: null, // 问答题没有选项ID @@ -1506,13 +1509,30 @@ const loadQuestionData = async () => { if (readonly.value) { console.log('只读模式:尝试加载用户答题记录...'); try { + // 与答题按钮功能保持一致,使用同一个API获取历史答题记录 userAnswerRes = await getUserSurveyAnswer(currentSurvey.value!.id); - console.log('✅ 成功加载用户答题记录'); + console.log('✅ 成功加载用户答题记录:', userAnswerRes); + + // 检查API返回数据,判断是否包含历史答题记录 + if (userAnswerRes && userAnswerRes.code === 200 && userAnswerRes.data) { + console.log('✅ 获取到历史答题数据成功'); + } else { + console.log('⚠️ API返回成功但无历史答题数据'); + } } catch (error) { + // 处理API请求失败的情况 if ((error as any)?.response?.status === 404) { console.log('ℹ️ 用户尚未回答此问卷,将显示空白题目'); } else { console.warn('⚠️ 加载用户答题记录失败,将显示空白题目:', error); + + // 调试输出完整错误信息 + if (error && typeof error === 'object') { + const err = error as any; + console.error('错误详情:', err.response?.data || err.message || String(error)); + } else { + console.error('错误详情:', String(error)); + } } userAnswerRes = null; // 确保为null,后续逻辑会处理 } @@ -1537,8 +1557,56 @@ const loadQuestionData = async () => { console.log('查看模式-答题明细样例:', userAnswers.details[0]); } else { console.log('查看模式-未找到有效的答题明细数据'); - // 确保details属性存在 - userAnswers.details = []; + + // 检查是否存在remark字段并尝试从中提取答题数据(与loadPreviousAnswers一致) + if (userAnswers.remark && userAnswers.remark.includes('ANSWERS_DATA:')) { + try { + // 从remark字段中提取JSON字符串并解析 + const jsonStr = userAnswers.remark.split('ANSWERS_DATA:')[1]; + console.log('查看模式-找到ANSWERS_DATA,尝试解析:', jsonStr); + + // 修复方式1:先用正则表达式提取所有questionId,以便后续修复 + const idMatches = jsonStr.match(/"questionId":(\d+)/g); + const originalIds = idMatches ? idMatches.map((match) => match.split(':')[1]) : []; + + console.log('从JSON字符串中提取的原始questionId列表:', originalIds); + + // 使用 JSON.parse 时配合 reviver 函数处理大整数 + const answersData = JSON.parse(jsonStr); + + // 解析后直接使用提取的原始ID进行修复 + if (originalIds.length === answersData.length) { + console.log('使用提取的原始ID进行修复,数量匹配'); + answersData.forEach((answer, index) => { + if (index < originalIds.length) { + // 始终将ID作为字符串处理,避免精度丢失 + answer.questionId = String(originalIds[index]); + console.log(`修复第 ${index + 1} 条数据的 questionId: ${answer.questionId}`); + } + }); + } else { + console.warn('ID数量不匹配,尝试其他修复方式'); + + // 备选修复方法:确保所有questionId都是字符串类型 + answersData.forEach((answer) => { + if (answer.questionId) { + answer.questionId = String(answer.questionId); + } + }); + } + + console.log('成功解析历史答题数据:', answersData); + + // 将答题数据转换为details格式,方便后续处理 + userAnswers.details = answersData; + console.log('查看模式-转换后的答题明细数据:', userAnswers.details.length, '条记录'); + } catch (error) { + console.error('解析ANSWERS_DATA失败:', error); + userAnswers.details = []; + } + } else { + userAnswers.details = []; + } } } else { console.log('ℹ️ 查看模式-用户尚未回答此问卷,显示空白题目'); @@ -1603,13 +1671,28 @@ const loadQuestionData = async () => { if (question.questionType === '1' || question.questionType === 1) { // 单选题:设置选中的选项值 const detail = questionAnswers[0]; - question.userAnswer = String(detail.answerScore || detail.answer_score || ''); + // 使用answerScore作为答案标识,确保类型匹配 + const answerScore = detail.answerScore || detail.answer_score || 0; + question.userAnswer = String.fromCharCode( + 65 + + question.options.findIndex( + (opt) => + Number(opt.optionScore) === Number(answerScore) || (opt.score !== undefined && Number(opt.score) === Number(answerScore)) + ) + ); console.log(`✅ 查看模式-单选题${questionId}用户答案:`, question.userAnswer); } else if (question.questionType === '2' || question.questionType === 2) { - // 多选题:从多条记录中收集选项值 + // 多选题:从多条记录中收集选项值并转换为字母标识 question.userAnswer = questionAnswers - .map((detail) => String(detail.answerScore || detail.answer_score || '')) - .filter((val) => val !== null && val !== undefined && val !== ''); + .map((detail) => { + const answerScore = detail.answerScore || detail.answer_score || 0; + const optionIndex = question.options.findIndex( + (opt) => + Number(opt.optionScore) === Number(answerScore) || (opt.score !== undefined && Number(opt.score) === Number(answerScore)) + ); + return optionIndex >= 0 ? String.fromCharCode(65 + optionIndex) : ''; + }) + .filter((val) => val !== ''); console.log(`✅ 查看模式-多选题${questionId}用户答案:`, question.userAnswer); } else if (question.questionType === '3' || question.questionType === 3) { // 问答题:从remark字段获取文本答案