From 27fcea613c00f89c93372e416773283631344f08 Mon Sep 17 00:00:00 2001
From: zlwu <704541015@qq.com>
Date: Fri, 18 Jul 2025 10:31:52 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=B0=83=E6=9F=A5=E9=97=AE?=
=?UTF-8?q?=E5=8D=B7=E7=9A=84=E6=9F=A5=E7=9C=8B=E9=A2=98=E7=9B=AE=E7=9A=84?=
=?UTF-8?q?=E6=8C=89=E9=92=AE=E7=9A=84=E5=9B=9E=E6=98=BE=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/views/hq/answerSurvey/index.vue | 169 ++++++++++++++++++------
1 file changed, 126 insertions(+), 43 deletions(-)
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字段获取文本答案