diff --git a/src/components/Course/courseExam.vue b/src/components/Course/courseExam.vue index 22c0d9a4..9683d139 100644 --- a/src/components/Course/courseExam.vue +++ b/src/components/Course/courseExam.vue @@ -167,7 +167,7 @@ import simplePaper from "@/components/Course/simpleTestPaper.vue"; import apiCourse from '../../api/modules/course.js'; import apiExamPaper from '../../api/modules/paper.js'; - import { deepClone } from "../../utils"; + import { deepClone, safeJsonParse } from "../../utils"; export default{ components:{simplePaper}, props:{ @@ -253,7 +253,7 @@ this.examInfo=res.result; if(res.result.paperType==1){ this.examInfo.paperContent=res.result.paperContent; - this.examPaper=JSON.parse(res.result.paperContent); + this.examPaper = safeJsonParse(res.result.paperContent, { items: [] }); }else{ apiExamPaper.detail(this.examInfo.paperId).then(rs=>{ if(rs.status==200){ diff --git a/src/components/Course/exam.vue b/src/components/Course/exam.vue index 6ccff889..2fac4104 100644 --- a/src/components/Course/exam.vue +++ b/src/components/Course/exam.vue @@ -132,6 +132,7 @@ import apiCourse from '@/api/modules/course.js'; import apiExamPaper from '@/api/modules/paper.js'; import {formatDate,formatSeconds} from '@/utils/datetime.js'; import {testType,correctJudgment,numberToLetter} from '@/utils/tools.js'; +import { safeJsonParse } from '@/utils/index.js'; export default { props:{ studyId: { @@ -216,8 +217,12 @@ export default { apiCourse.getExam(this.content.id).then(res=>{ if(res.status==200){ this.info=res.result; - if(this.showTest) { - let paper= JSON.parse(this.info.paperContent); + if(this.showTest) { + let paper = safeJsonParse(this.info.paperContent, { items: [] }); + if(!paper.items || paper.items.length === 0){ + this.viewTest = []; + return; + } paper.items.forEach(item=>{ //console.log(item); if(item.type==101){ diff --git a/src/components/Course/weikeContent.vue b/src/components/Course/weikeContent.vue index 168aa565..66e13012 100644 --- a/src/components/Course/weikeContent.vue +++ b/src/components/Course/weikeContent.vue @@ -575,7 +575,7 @@ import apiExamPaper from '../../api/modules/paper.js'; import audioPlayer from '@/components/AudioPlayer/index.vue'; import {getType} from '../../utils/tools.js'; - import { deepClone } from "../../utils"; + import { deepClone, safeJsonParse } from "../../utils"; export default{ components:{WxEditor,simplePaper,FileUpload,pdfPreview,audioPlayer,chooseCourseFile}, props: { @@ -921,7 +921,7 @@ if(res.status==200){ this.exam.info=res.result; if(res.result.paperType==1){ - this.exam.paperJson=JSON.parse(res.result.paperContent); + this.exam.paperJson = safeJsonParse(res.result.paperContent, { items: [] }); }else{ apiExamPaper.detail(this.exam.info.paperId).then(rs=>{ if(rs.status==200){ diff --git a/src/components/Exam/EditPaper.vue b/src/components/Exam/EditPaper.vue index f3ce3d07..5b0f73a8 100644 --- a/src/components/Exam/EditPaper.vue +++ b/src/components/Exam/EditPaper.vue @@ -109,6 +109,7 @@ import imgupload from '@/components/ImageUpload/single.vue'; import apiExamTask from '@/api/modules/examTask.js'; import examQuestionApi from "@/api/modules/question"; + import { safeJsonParse } from '../../utils'; import {numberToLetter, deepCopy} from '../../utils/tools.js'; export default { name: 'comEditPaper', @@ -163,7 +164,7 @@ if(res.status === 200) { this.paper=res.result; //转化试题 - this.qitems=JSON.parse(res.result.paperContent); + this.qitems = safeJsonParse(res.result.paperContent, []); //console.log(this.qitems,this.qitems) this.tempItems=this.qitems; this.paperCalculation(); diff --git a/src/utils/index.js b/src/utils/index.js index 0507bcac..0d7432f7 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -310,6 +310,42 @@ export function deepClone(source) { return targetObj } +import { Message } from 'element-ui'; + +/** + * 安全解析 JSON 字符串,统一处理错误日志和 UI 提示 + * @param {string|object} text 待解析的字符串(或对象) + * @param {*} fallback 解析失败或为空时的回退值,默认为空对象 {} + * @param {string} errorMessage UI 提示信息,默认为试卷格式错误提示 + * @returns {*} + */ +export function safeJsonParse(text, fallback = {}, errorMessage = '试卷内容格式有误,请联系管理员检查试卷数据') { + // 1. 如果已经是对象或数组,直接返回 + if (typeof text === 'object' && text !== null) { + return text; + } + + // 2. 处理空值情况 + if (text === null || text === undefined || text === '') { + return fallback; + } + + // 3. 尝试解析 + try { + return JSON.parse(text); + } catch (error) { + // 4. 统一日志和报错 + console.error('JSON 解析失败:', { + input: text, + error: error.message + }); + if (errorMessage) { + Message.error(errorMessage); + } + return fallback; + } +} + /** * @param {Array} arr * @returns {Array} diff --git a/src/views/exam/TestPaper.vue b/src/views/exam/TestPaper.vue index 5a1a497c..538a497c 100644 --- a/src/views/exam/TestPaper.vue +++ b/src/views/exam/TestPaper.vue @@ -296,7 +296,7 @@ import apiPaper from '@/api/modules/paper.js'; import apiExamTask from '@/api/modules/examTask.js'; import examQuestionApi from "@/api/modules/question"; -import { deepClone } from '../../utils'; +import { deepClone, safeJsonParse } from '../../utils'; import {numberToLetter, deepCopy} from '../../utils/tools.js'; import { mapGetters,mapActions} from 'vuex'; import editPaper from "@/components/Exam/EditPaper"; @@ -689,7 +689,7 @@ export default { this.viewVolumeShow=true; apiPaper.detail(row.id).then(res=>{ if(res.status === 200) { - this.viewShowData = JSON.parse(res.result.paperContent); + this.viewShowData = safeJsonParse(res.result.paperContent, { items: [] }); console.log(this.viewShowData,'lll') } else { this.$message.error(res.message); @@ -720,8 +720,9 @@ export default { apiPaper.detail(row.id).then(res=>{ if(res.status === 200) { this.paper = res.result; - this.paper.data = JSON.parse(res.result.paperContent); - this.paperData = JSON.parse(res.result.paperContent); + const parsedValue = safeJsonParse(res.result.paperContent, []); + this.paper.data = parsedValue; + this.paperData = parsedValue; this.paper.paperType = Number(res.result.paperType); if(res.result.resOwner3) { this.resOwner = [res.result.resOwner1,res.result.resOwner2,res.result.resOwner3]; diff --git a/src/views/portal/course/microPreview.vue b/src/views/portal/course/microPreview.vue index a8fa2ceb..1cd20bb8 100644 --- a/src/views/portal/course/microPreview.vue +++ b/src/views/portal/course/microPreview.vue @@ -357,16 +357,17 @@ import apiCourse from "@/api/modules/course.js"; import apiCourseFile from "@/api/modules/courseFile.js"; import apiCoursePortal from "@/api/modules/coursePortal.js"; import apiUser from '@/api/system/user.js'; -import { - formatDate, - resListMap, - toScore, - courseType, - getType, - numberToLetter, - correctJudgment -} from "@/utils/tools.js"; -import apicourseStudy from "@/api/modules/courseStudy.js"; + import { + formatDate, + resListMap, + toScore, + courseType, + getType, + numberToLetter, + correctJudgment + } from "@/utils/tools.js"; + import { safeJsonParse } from "@/utils"; + import apicourseStudy from "@/api/modules/courseStudy.js"; import apiCourseGrade from "@/api/modules/courseGrade.js"; import apiPraises from "@/api/modules/praises.js"; import apiTrample from "@/api/modules/trample.js"; @@ -716,7 +717,7 @@ export default { apiCourse.getExam(this.examInfo.content.id).then(res => { if (res.status == 200) { this.examInfo.info = res.result; - this.examInfo.paper = JSON.parse(res.result.paperContent); + this.examInfo.paper = safeJsonParse(res.result.paperContent, { items: [] }); } else if (res.status == 404) { //没有找到考试信息 } else {