From c8aae6f408d593c7a734cafb62f19c7f6f97e0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=9D=A8?= <666> Date: Mon, 28 Oct 2024 17:12:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BD=9C=E4=B8=9A=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=97=AE=E9=A2=98=E4=BB=A5=E5=8F=8A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/utils/tool.js | 2 +- .../classTask/container/classOverview.vue | 38 ++- .../classOverview/distribution/echarts.vue | 14 +- .../classOverview/distribution/stuList.vue | 13 +- .../container/classOverview/knowledge.vue | 27 +- .../container/classOverview/timeAnalyse.vue | 233 ++++++++++-------- .../src/views/classTask/teachClassTask.vue | 2 +- 7 files changed, 205 insertions(+), 124 deletions(-) diff --git a/src/renderer/src/utils/tool.js b/src/renderer/src/utils/tool.js index 84fc77b..c5813f2 100644 --- a/src/renderer/src/utils/tool.js +++ b/src/renderer/src/utils/tool.js @@ -373,7 +373,7 @@ const eventHandles = (type, win) => { export const toLinkWeb = (path) => { const config = baseConfig() // console.log(config) - const fullPath = config.url + path + const fullPath = 'https://localhost:7860/' + path // 通知主进程 ipcRenderer.send('openWindow', { key: `win-${Date.now()}`, diff --git a/src/renderer/src/views/classTask/container/classOverview.vue b/src/renderer/src/views/classTask/container/classOverview.vue index e3d51b7..8ce866b 100644 --- a/src/renderer/src/views/classTask/container/classOverview.vue +++ b/src/renderer/src/views/classTask/container/classOverview.vue @@ -75,12 +75,12 @@ let studentList = ref([]) // 学生数据 // 初始-数据处理 const initData = () => { - console.log('xxx', props) // window.test = activeCourse studentList.value = props.activeData.studentList || [] const activeWorkFeedList = props.activeData.workFeedList || [] const quizlist = props.activeData.quizlist || [] - const timeArr = groupByField(props.activeData.workFeedList,'entpcourseworkid') + console.log(quizlist,'quizlist'); + // 习题特殊处理 let data = quizlist.map(o => { // 解析题选项 @@ -90,14 +90,9 @@ const initData = () => { let rightIds = [] // 正确学生 let hasAnswers= [] // 答过题的学生 let timeAnalyse = [] // 平均时长和编号 + // let subjectCourese = [] // 题目编号 const quizFeedList = activeWorkFeedList.filter(f => f.entpcourseworkid == o.id) // 做该题的列表 - // 获取所有的做题时间 - timeArr.forEach((item,index) => { - const arr = item.reduce((acc, cur) => { - return acc + (cur.timelength ? Number(cur.timelength) : 0); - },0) - timeAnalyse.push(arr) - }) + let children = [] const allStudents = []; if (o.worktype == '单选题') { // '单选题','多选题' @@ -108,6 +103,11 @@ const initData = () => { // 改选项的学生id const studentIds = quizFeedList.filter(f => f.feedcontent==v&&f.finishtimelength!='0').map(f => f.studentid)||[]; accSum += studentIds.length; + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) + if (isOk) { activeIds.push(...studentIds) } @@ -122,7 +122,7 @@ const initData = () => { const res = isSame((f.feedcontent||'').split(','), workanswer); return f.entpcourseworkid == o.id && f.finishtimelength!='0' && res; }); - + const list = workdesc.includes('#&') ? workdesc.split('#&') : isJson(workdesc)?JSON.parse(workdesc):[]; children = list.map((v,i) => { const isOne = o.worktype == '单选题' @@ -135,6 +135,10 @@ const initData = () => { if (studentIds.length>0) { allStudents.push(...studentIds); } + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) if(isOk) { activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重 } @@ -153,6 +157,10 @@ const initData = () => { activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重 hasAnswers=[...new Set(hasAnswers.concat(studentIds))] accSum = activeIds.length + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) return { def, code, txt, isOk:true, studentIds } }) } else if (o.worktype == '判断题') { // 判断题 @@ -194,6 +202,10 @@ const initData = () => { accSum += studentIds.length; if(isOk) activeIds.push(...studentIds) hasAnswers.push(...studentIds) + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) return { def: v, code: v, isOk, studentIds } }) } else { // 论述题 @@ -203,6 +215,10 @@ const initData = () => { activeIds=[...new Set(activeIds.concat(studentIds))] // 多选去重 hasAnswers=[...new Set(hasAnswers.concat(studentIds))] accSum = activeIds.length + // 该到题的用时时间 + timeAnalyse = quizFeedList.reduce((acc, cur) => { + return acc + (cur.timelength ? Number(cur.timelength) : 0); + },0) children = [{ def, code, isOk:true, studentIds }] } @@ -222,7 +238,7 @@ const initData = () => { } // def: 原始题数据 type 类型 active: 选中 points: 得分率, accSum 题解答人数 - return { def: o, id: o.id, type: o.worktype, active: [], points, accSum, rightSum, children,hasAnswers,timeAnalyse } + return { def: o, id: o.id, type: o.worktype, active: [], points, accSum, rightSum, children,hasAnswers,timeAnalyse,score:o.score } }) if (data.length === 0) return useOverview.getAllData([...data]) diff --git a/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue b/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue index ed70dfa..f19b912 100644 --- a/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue +++ b/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue @@ -24,6 +24,7 @@ const dataList = ref([ // 答过题的学生才进行统计 const hasStudents = ref([]) + // 根据数据生成不同的颜色 function getColor(name) { const colorMap = { @@ -104,7 +105,18 @@ const showEcharts = () => { } //执行 watch(() => useOverview.tableList, () => { - hasStudents.value = useOverview.tableList.filter(item => useOverview.allData[0].hasAnswers.includes(item.studentid)).map(item => item); + // 判断是不是客观题 + const subType = useOverview.allData.map(item => item.type) + const objectiveQuestion = ['单选题','多选题','判断题'] + if( !subType.every(item => objectiveQuestion.includes(item)) ){ + hasStudents.value = useOverview.tableList.filter(item => { + if(item.rating > 0 && useOverview.allData[0].hasAnswers.includes(item.studentid)){ + return item + } + }) + }else{ + hasStudents.value = useOverview.tableList.filter(item => useOverview.allData[0].hasAnswers.includes(item.studentid)).map(item => item); + } showEcharts(); nextTick(() => { initChart(); diff --git a/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue b/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue index 29d1425..9625c6d 100644 --- a/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue +++ b/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue @@ -81,7 +81,18 @@ const showStudents = (index) => { }) } watch(() => useOverview.tableList, () => { - hasStudents.value = useOverview.tableList.filter(item => useOverview.allData[0].hasAnswers.includes(item.studentid)).map(item => item); + // 判断是不是客观题 + const subType = useOverview.allData.map(item => item.type) + const objectiveQuestion = ['单选题','多选题','判断题'] + if( !subType.every(item => objectiveQuestion.includes(item)) ){ + hasStudents.value = useOverview.tableList.filter(item => { + if(item.rating > 0 && useOverview.allData[0].hasAnswers.includes(item.studentid)){ + return item + } + }) + }else{ + hasStudents.value = useOverview.tableList.filter(item => useOverview.allData[0].hasAnswers.includes(item.studentid)).map(item => item); + } showStudents(0) },{deep: true}) diff --git a/src/renderer/src/views/classTask/container/classOverview/knowledge.vue b/src/renderer/src/views/classTask/container/classOverview/knowledge.vue index c221cba..0ed7dd4 100644 --- a/src/renderer/src/views/classTask/container/classOverview/knowledge.vue +++ b/src/renderer/src/views/classTask/container/classOverview/knowledge.vue @@ -25,19 +25,23 @@ const useOverview = overviewStore() const tableData = ref([]) //用来获取所有知识点 const konwledge = ref([]) +const hasStudents = ref([]) +// 获取的所有得分 +const allScore = ref([]) //所有题目的知识点 const getKonwledge = () => { const getScoreRate = [] // 获取知识点的种数 const ledges = [] - useOverview.tableList.forEach(item => { + hasStudents.value.forEach((item,index) => { //判断是否存在知识点 if(item.knowledgePoint){ const title = JSON.parse(item.knowledgePoint) //判断知识点是否重复 if(!ledges.includes(title.id)){ ledges.push(title.id) - konwledge.value.push({title:title.title,allPoint:item.point,id:title.id}) + // 假如分数是0 或者 得分率为空 + konwledge.value.push({title:title.title,allPoint:allScore.value,id:title.id}) } // 判断学生是否答过题 if(useOverview.allData[0].hasAnswers.includes(item.studentid)) @@ -50,6 +54,7 @@ const getKonwledge = () => { let sunRate = 0 let num = 0 if(getScoreRate.length === 0) return + getScoreRate.forEach(item2 => { if(item.id === item2.id){ sunRate += extractedNumber(item2.rate) @@ -71,7 +76,23 @@ const extractedNumber = (score) => { } //组装tableList表格 -watch(() => useOverview.tableList,() => { +watch(() => useOverview.tableList,() => { + // 判断是不是客观题 + const subType = useOverview.allData.map(item => item.type) + const objectiveQuestion = ['单选题','多选题','判断题'] + if( !subType.every(item => objectiveQuestion.includes(item)) ){ + hasStudents.value = useOverview.tableList.filter(item => { + if(item.rating > 0 && useOverview.allData[0].hasAnswers.includes(item.studentid)){ + return item + } + }) + }else{ + hasStudents.value = useOverview.tableList.filter(item => useOverview.allData[0].hasAnswers.includes(item.studentid)).map(item => item); + } + // 这里获取所有知识点的总分 + allScore.value = useOverview.allData.reduce((acc, cur) => { + return acc + Number(cur.score) + },0) getKonwledge() }) diff --git a/src/renderer/src/views/classTask/container/classOverview/timeAnalyse.vue b/src/renderer/src/views/classTask/container/classOverview/timeAnalyse.vue index b79cb65..815ee6b 100644 --- a/src/renderer/src/views/classTask/container/classOverview/timeAnalyse.vue +++ b/src/renderer/src/views/classTask/container/classOverview/timeAnalyse.vue @@ -9,134 +9,155 @@ import * as echarts from 'echarts'; import {ref, nextTick, watch} from 'vue' import overviewStore from '@/store/modules/overview' -const useOverview = overviewStore() +const useOverview = overviewStore(); // 获取图表容器的引用 const chartRef = ref(null); +// 预计用时 +const expectedDuration = ref([]); // 初始化图表 function initChart() { const myChart = echarts.init(chartRef.value); - // 指定图表的配置项和数据 - let option = { - tooltip: { - trigger: "axis", - axisPointer: { - type: "shadow", // 默认为直线,可选为:'line' | 'shadow' - }, - formatter: function(parms) { - let str = - parms[0].axisValue + - "
" + - parms[0].marker + - "平均用时:" + - parms[0].value + 's' - return str; - }, - - }, - textStyle: { + + // 指定图表的配置项和数据 + let option = { + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", // 默认为直线,可选为:'line' | 'shadow' + }, + formatter: function (parms) { + let str = ""; + parms.forEach(param => { + if (param.seriesType === 'bar') { + str += param.axisValue + "
" + param.marker + "平均用时:" + param.value + 's' + "
"; + } else if (param.seriesType === 'line') { + str += param.marker + "预计用时:" + param.value + 's'; + } + }); + return str; + }, + }, + textStyle: { + color: "#333", + }, + color: ["#7BA9FA", "#4690FA"], + grid: { + containLabel: true, + left: "10%", + top: "20%", + bottom: "10%", + right: "10%", + }, + xAxis: { + type: "category", + data: getXValue(), + axisLine: { + lineStyle: { color: "#333", }, - color: ["#7BA9FA", "#4690FA"], - grid: { - containLabel: true, - left: "10%", - top: "20%", - bottom: "10%", - right: "10%", + }, + axisTick: { + show: false, + }, + axisLabel: { + margin: 20, //刻度标签与轴线之间的距离。 + textStyle: { + color: "#000", }, - xAxis: { - type: "category", - data: getXValue(), - axisLine: { - lineStyle: { - color: "#333", - }, - }, - axisTick: { - show: false, - }, - axisLabel: { - margin: 20, //刻度标签与轴线之间的距离。 - textStyle: { - color: "#000", - }, - }, - name:'题目编号' + }, + name: '题目编号' + }, + yAxis: { + type: "value", + axisLine: { + show: true, + lineStyle: { + color: "#B5B5B5", }, - yAxis: { - type: "value", - axisLine: { - show: true, - lineStyle: { - color: "#B5B5B5", - }, - }, - name:'平均时长', - splitLine: { - lineStyle: { - // 使用深浅的间隔色 - color: ["#B5B5B5"], - type: "dashed", - opacity: 0.5, - }, - }, - axisLabel: {}, + }, + name: '平均时长', + splitLine: { + lineStyle: { + // 使用深浅的间隔色 + color: ["#B5B5B5"], + type: "dashed", + opacity: 0.5, }, - series: [{ - data: getYValue(), - stack: "zs", - type: "bar", - barMaxWidth: "auto", - barWidth: 60, - itemStyle: { - color: { - x: 0, - y: 0, - x2: 0, - y2: 1, - type: "linear", - global: false, - colorStops: [{ - offset: 0, - color: "#5EA1FF", - }, - { - offset: 1, - color: "#90BEFF", - }, - ], - }, + }, + axisLabel: {}, + }, + series: [ + { + data: getYValue(), + stack: "zs", + type: "bar", + barMaxWidth: "auto", + barWidth: 60, + itemStyle: { + color: { + x: 0, + y: 0, + x2: 0, + y2: 1, + type: "linear", + global: false, + colorStops: [ + { offset: 0, color: "#5EA1FF" }, + { offset: 1, color: "#90BEFF" }, + ], }, }, - ], - }; + label: { + show: true, + position: 'top', + formatter: '{c}s', + color: '#333', + }, + }, + //折线的加入 + { + data: expectedDuration.value, + type: "line", + smooth: true, + symbol: 'circle', + symbolSize: 8, + lineStyle: { + color: '#FF7F50', + width: 2, + }, + itemStyle: { + color: '#FF7F50', + }, + }, + ], + }; + myChart.setOption(option); } - //获取平均时长纵坐标 + +// 获取平均时长纵坐标 const getYValue = () => { - const arr = [...useOverview.allData[0].timeAnalyse] - const num = useOverview.allData[0].hasAnswers.length - - return arr.map(item => { - return item ? (item / num).toFixed(2) : 0 - }) -} - // 获取横纵轴坐标数据 + const arr = useOverview.allData.map(item => item.timeAnalyse) + const num = useOverview.allData[0].hasAnswers.length; + if (arr.length === 0) return []; + return arr.map(item => (item ? (item / num).toFixed(2) : 0)); +}; + +// 获取横纵轴坐标数据 const getXValue = () => { - return useOverview.allData.map(item => item.id) -} + return useOverview.allData.map((item, index) => `第${index + 1}题`); +}; +watch(() => useOverview.tableList, () => { + expectedDuration.value = useOverview.tableList.map(item => (Number(item.timelength) * 60 / useOverview.allData.length).toFixed(2)); - -watch(() => useOverview.tableList,() => { - //获取横纵坐标 + // 获取横纵坐标 nextTick(() => { initChart(); - }) -}) - + }); +});