baigl #180

Merged
baigl merged 13 commits from baigl into main 2024-09-10 13:51:04 +08:00
5 changed files with 301 additions and 8 deletions
Showing only changes of commit 5bda6cfad2 - Show all commits

View File

@ -245,6 +245,8 @@ const getStudentVisible = async () => {
} else { } else {
classWorkList.value[t].averagetime = 0 classWorkList.value[t].averagetime = 0
} }
//
classWorkList.value[t].teacherrationgcount = curWork.teacherrationgcount
} else { } else {
classWorkList.value[t].finishpercent = 0 classWorkList.value[t].finishpercent = 0
} }
@ -256,8 +258,6 @@ const getStudentVisible = async () => {
// //
const getStudentClassWorkData = () => { const getStudentClassWorkData = () => {
// //
console.log('======????????""""""""""')
//TODO id
listClassworkdata({ listClassworkdata({
classids: classListIds.value.join(','), classids: classListIds.value.join(','),
//entpcourseid: '', // id //entpcourseid: '', // id
@ -268,8 +268,8 @@ const getStudentClassWorkData = () => {
}).then((res) => { }).then((res) => {
for (var t = 0; t < classWorkList.value.length; t++) { for (var t = 0; t < classWorkList.value.length; t++) {
for (var i = 0; i < res.rows.length; i++) { for (var i = 0; i < res.rows.length; i++) {
if (res.rows[i].uniquekey == classWorkList.value[t].uniquekey) { //if (res.rows[i].uniquekey == classWorkList.value[t].uniquekey) {
// if (res.rows[i].classworkid == classWorkList.value[t].id && res.rows[i].resultcount > 0) { if (res.rows[i].classworkid == classWorkList.value[t].id && res.rows[i].resultcount > 0) {
console.log('==================') console.log('==================')
// / // /
// resultcount0 // resultcount0

View File

@ -98,7 +98,8 @@
<!-- <span>学生答案{{ stuItem.feedcontent }}</span> --> <!-- <span>学生答案{{ stuItem.feedcontent }}</span> -->
<span <span
>学生答案 >学生答案
<span v-if="quItem.workdesc == ''"> <span v-if="quItem.workdesc == ''|| quItem.workdesc == '[]' ">
<!-- quItem.workdesc 没值说明是非选择题 -->
<span <span
v-if="stuItem.feedcontent != ''" v-if="stuItem.feedcontent != ''"
style=" style="
@ -112,6 +113,7 @@
</span> </span>
</span> </span>
<span v-else> <span v-else>
<!-- 选择题类型学生答题转换为 ABCD格式 -->
<span <span
v-if="stuItem.feedcontent != ''" v-if="stuItem.feedcontent != ''"
style=" style="

View File

@ -137,7 +137,7 @@
<!-- 作业概况 --> <!-- 作业概况 -->
<div v-else-if="classWorkAnalysis.view == 'quizStats'"> <div v-else-if="classWorkAnalysis.view == 'quizStats'">
<!-- <quiz-stats :active-data="classWorkActiveData" /> --> <quiz-stats :active-data="classWorkActiveData" />
</div> </div>
<!-- 作业报告--> <!-- 作业报告-->

View File

@ -0,0 +1,278 @@
<template>
<el-row class="c-warp" :gutter="10">
<el-col class="left" :span="16">
<el-collapse class="c-item" v-model="activeTopic" accordion>
<template v-for="(item, index) in dataList">
<el-collapse-item class="collapse-item" :name="index+1" :id="'collapse-'+(index+1)">
<template #title>
<el-popover :width="500" placement="right">
<p>{{item.def?.titletext}}</p>
<template #reference>
<el-button type="primary" size="small" round>{{index+1}}</el-button>
</template>
</el-popover>
<span class="item-title-o">{{item.type}} {{getRatioTxt(item)}} </span>
<el-tag type="success" size="small">{{item.points}}%</el-tag>
</template>
<div class="respond">
<div class="c-label">
<b t1>作答情况</b>
<span>(已经完成 <el-text type="danger">{{item.accSum}}</el-text> )</span>
</div>
<div class="c-childen">
<template v-for="(it, ind) in item.children">
<el-collapse v-model="item.active">
<el-collapse-item class="collapse-item" :name="ind+1">
<template #title>
<div class="t-left">
<el-tooltip placement="right" :content="it.def">
<el-tag size="small" style="vertical-align: 2px;" v-html="it.code"></el-tag>
</el-tooltip>
<el-text t1>{{it.studentIds.length}} / {{ratio_1(it, item.accSum)}}%</el-text>
</div>
<div style="flex: 1;">
<el-progress :status="getStatus(it)" :stroke-width="10" :percentage="ratio_1(it, item.accSum)" />
</div>
</template>
<div class="c-respond">
<template v-for="(sid, indStu) in it.studentIds">
<el-tag>{{getStudentName(sid)}}</el-tag>
</template>
</div>
</el-collapse-item>
</el-collapse>
</template>
</div>
</div>
</el-collapse-item>
</template>
</el-collapse>
</el-col>
<el-col class="right" :span="8">
<div class="c-item">
<div class="title">答题情况</div>
<div class="respond">
<el-space wrap>
<!-- <template v-for="it in 11"> -->
<template v-for="(item, index) in dataList">
<el-card shadow="hover" class="card-warp">
<div class="card-body">
<el-progress type="dashboard" :color="colorArr" :width="80" :percentage="ratio_2(item)" />
<el-button type="primary" :plain="getActive(index+1)" size="small" round
@click="clickInfo(index+1)">{{index+1}}</el-button>
</div>
</el-card>
</template>
</el-space>
</div>
</div>
</el-col>
</el-row>
</template>
<script setup>
// -|(使-|-)
// === ===
// import { nextTick } from 'vue'
// import * as elementPlus from 'element-plus' // ElMessage ElMessageBox
let colorArr = [] // --
const attrs = useAttrs() // props
const activeTopic = ref(0) //
let dataList = ref([]) //
let studentList = ref([]) //
const props = defineProps({ // defineProps
activeData: { //
type: Object,
// required: true, //
default: () => ({
quizlist: [], //
studentList: [], // -
workFeedList: [] // -
})
},
})
//
// dataList.value = [
// { id: 1, type: '', points: '47.5', accSum: 18, active: [], children: [
// { code: 'A', isOk: false, studentIds: [55056, 55057, 55058]},
// ]
// },
// ]
//
colorArr = [
{ color: '#f56c6c', percentage: 20 },
{ color: '#e6a23c', percentage: 50 },
{ color: '#1989fa', percentage: 80 },
{ color: '#5cb87a', percentage: 100 },
]
// === ===
onMounted(() => {})
// === (methods) ===
// -
const initData = () => {
// console.log('xxx', props)
// window.test = activeCourse
studentList.value = props.activeData.studentList || []
const activeWorkFeedList = props.activeData.workFeedList || []
const quizlist = props.activeData.quizlist || []
//
let data = quizlist.map(o => {
//
const workdesc = o.workdesc || ''
let accSum = 0 //
let activeIds = [] //
const quizFeedList = activeWorkFeedList.filter(f => f.entpcourseworkid == o.id) //
let children = []
if (['单选题','多选题'].includes(o.worktype)) { // '',''
const list = workdesc.includes('#&') ? workdesc.split('#&') : isJson(workdesc)?JSON.parse(workdesc):[]
children = list.map((v,i) => {
const isOne = o.worktype == '单选题'
const code = toCode(i) // A-Z
// const isOk = isOne ? i == o.workanswer : o.workanswer.includes(i) // ()
const isOk = (isJson(workdesc)?JSON.parse(o.workanswer):o.workanswer||'').includes(i+'') // ()
// id
const studentIds = quizFeedList.filter(f => isOne ? f.feedcontent==v : f.feedcontent.includes(i)).map(f => f.studentid)||[]
accSum += studentIds.length
if(isOk) isOne ? activeIds.push(...studentIds) : activeIds=[...new Set(activeIds.concat(studentIds))] //
return { def: v, code, isOk, studentIds }
})
} else if (o.worktype == '填空题') { //
const regex = /<!--BA-->(.*?)<!--EA-->/g // <!--BA-->xxx<!--EA-->
children = (o.title||'').match(regex).map((v,i) => {
const def = `填空项 ${i+1}`
const code = '(&emsp;)', txt=v
// id
const studentIds = quizFeedList.filter(f => !!(f.feedcontent||'').replace(/#$/,'').split('#')[i]).map(f => f.studentid)||[]
activeIds=[...new Set(activeIds.concat(studentIds))] //
accSum = activeIds.length
return { def, code, txt, isOk:true, studentIds }
})
} else if (o.worktype == '论述题') { //
const code = '(&emsp;)', def = '论述内容'
const studentIds = quizFeedList.filter(f => !!(f.feedcontent||'').replace(/#$/,'')).map(f => f.studentid)||[]
activeIds=[...new Set(activeIds.concat(studentIds))] //
accSum = activeIds.length
children = [{ def, code, isOk:true, studentIds }]
}
const studentSum = studentList.value.length || 0 //
const points = percent((activeIds.length / (studentSum||1)).toFixed(2)) //
// def: type active: points: , accSum
return { def: o, id: o.id, type: o.worktype, active: [], points, accSum, children }
})
console.log('获取数据: ', data)
dataList.value = data
}
// --
const ratio_1 = (row, sum = 1) => percent(((row.studentIds.length||0) / (sum||1)).toFixed(2))
// --
const ratio_2 = row => percent(((row.accSum||0) / (studentList.value.length||1)).toFixed(2))
// --txt
const getRatioTxt = row => row.type.includes('选题') ? '得分率' : '完成度'
// --
const getStatus = row => row.isOk ? 'success' : 'exception'
// -(id)
const getStudentName = id => studentList.value.length && (studentList.value.find(o => o.studentid == id)||{})?.name || id
// -
const getActive = ind => activeTopic.value != ind
// -
const clickInfo = async ind => {
activeTopic.value = activeTopic.value != ind ? ind : 0
setTimeout(() => {scrollToElement('collapse-' + ind)}, 300);
// elementPlus.ElMessage.warning('!')
}
// === ===
//
const scrollToElement = id => {
const el = document.getElementById(id)
!!el && el.scrollIntoView({ behavior: 'smooth', block: 'center',inline:'center' })
}
// 0-100
const percent = v => v > 1 ? 1 : v < 0 ? 0 : Math.round(v * 100)
// Unicode 65
const toCode = (v, b) => b ? v.charCodeAt() - 65 : String.fromCharCode(v + 65)
// json
const isJson = str => {if(typeof str == 'string'){
try {
const res = JSON.parse(str)
if(typeof res == 'object' && res) return true
} catch (error) {}}return false
}
// === ===
watchEffect(() => { initData() })
</script>
<style lang="scss" scoped>
//
.c-warp{
background: #F2F3F5;
height: 100vh;
margin: 0 !important;
.left{padding-left: 0 !important;}
.right{padding-right: 0 !important;}
.c-item{
padding: 10px;
background: #fff;
border: none;
overflow-y: auto;
height: 100vh;
}
.collapse-item{
.item-title-o{
margin: 0 10px;
font-size: 18px;
font-weight: bold;
}
&:last-child{
color: red;
:deep(.el-collapse-item__header){
border-bottom: none;
}
}
.respond{
.c-label{
b[t1]{margin-right: 10px;}
}
.c-childen{
padding: 15px;
border-radius: 4px;
border: 1px solid #CDD0D6;
.el-text[t1]{
margin-left: 10px;
}
.t-left{width: 160px;text-align: left;}
.c-respond{
.el-tag{margin: 0 5px;}
}
}
}
}
.right{
.title{
font-size: 18px;
font-weight: bold;
padding-bottom: 10px;
border-bottom: 1px solid #CDD0D6;
margin-bottom: 10px;
}
.respond{
height: calc(100vh - 65px);
overflow: auto;
.el-space{padding: 5px;}
.card-warp{
border: none;
:deep(.el-card__body){
padding: 10px !important;
}
}
.card-body{
display: flex;
flex-direction: column;
}
}
}
}
</style>

View File

@ -23,11 +23,24 @@
<span>已交</span> <span>已交</span>
</div> </div>
<div class="class-reserv-item-tool"> <div class="class-reserv-item-tool">
<span style="color: #ff7f00; font-weight: 900; font-size: 15px">{{ item.teacherRationgCount?item.teacherRationgCount:0 }}</span> <!-- 总人数-已批阅人数 -->
<span style="color: #ff7f00; font-weight: 900; font-size: 15px">{{ item.teacherrationgcount?item.workdatacount - item.teacherrationgcount:item.workdatacount }}</span>
<span>待批阅</span> <span>待批阅</span>
</div> </div>
<div class="class-reserv-item-tool"> <div class="class-reserv-item-tool">
<span><span style="color: #007fff; font-weight: 900; font-size: 15px">{{ item.averagetime?item.averagetime:0 }}</span>分钟 </span> <span>
<!-- {{ item.averagetime?item.averagetime:0 }} -->
<span v-if=" item.averagetime<60 ">
<span style="color: #007fff; font-weight: 900; font-size: 15px">{{ item.averagetime }}</span>分钟
</span>
<span v-if=" item.averagetime==60 ">
<span style="color: #007fff; font-weight: 900; font-size: 15px">1</span>小时
</span>
<span v-if=" item.averagetime>60 ">
<span style="color: #007fff; font-weight: 900; font-size: 15px">{{ Math.floor(item.averagetime / 60)}}</span>小时
<span style="color: #007fff; font-weight: 900; font-size: 15px">{{ Math.floor(item.averagetime % 60)}}</span>分钟
</span>
</span>
<span>平均用时</span> <span>平均用时</span>
</div> </div>
<div class="class-reserv-item-tool"> <div class="class-reserv-item-tool">