Просмотр исходного кода

修改调查问卷的查看题目的按钮的回显问题

zlwu 1 год назад
Родитель
Сommit
27fcea613c
1 измененных файлов с 126 добавлено и 43 удалено
  1. 126 43
      web/src/views/hq/answerSurvey/index.vue

+ 126 - 43
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"
-                    />
+                    >
+                      <template #append v-if="question.userAnswer && question.userAnswer.trim()">
+                        <el-tag size="small" type="success">已作答</el-tag>
+                      </template>
+                    </el-input>
                   </div>
                 </div>
               </div>
@@ -1016,14 +1022,35 @@ const loadPreviousAnswers = async (surveyId: string | number, formData: Record<s
         // 从remark字段中提取JSON字符串并解析
         const jsonStr = userData.remark.split('ANSWERS_DATA:')[1];
 
+        // 修复方式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 函数处理大整数
-        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<s
         const uniqueIds = new Set(answersData.map((a) => 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字段获取文本答案